diff --git a/src/bin/libint/dg.cc b/src/bin/libint/dg.cc index eded6a54f..f94443f4a 100644 --- a/src/bin/libint/dg.cc +++ b/src/bin/libint/dg.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include using namespace std; @@ -427,6 +428,7 @@ void DirectedGraph::reset() { targets_.clear(); first_to_compute_.reset(); func_names_.clear(); + hoisted_precomputed_.clear(); } /// Apply a strategy to all vertices not yet computed (i.e. which do not have @@ -1205,6 +1207,12 @@ void DirectedGraph::generate_code( def << context->macro_endif(); } + // load the precomputed quantities that assign_symbols() hoisted + for (const auto& h : hoisted_precomputed_) + def << context->decldef( + context->const_modifier() + context->type_name(), h.first, + h.second); + // now print out the code for this graph print_def(context, def, dims, args); @@ -1502,6 +1510,8 @@ void DirectedGraph::assign_symbols( } // then process all other symbols, EXCEPT operators + hoisted_precomputed_.clear(); + std::set hoisted_names; for (iter v = stack_.begin(); v != stack_.end(); ++v) { const ver_ptr& vptr = vertex_ptr(*v); #if DEBUG @@ -1528,10 +1538,22 @@ void DirectedGraph::assign_symbols( // test if the vertex is precomputed runtime quantity, like a geometric // parameter if ((vptr)->precomputed()) { - std::string symbol("inteval->"); - symbol += context->label_to_name((vptr)->label()); - symbol += "[vi]"; - (vptr)->set_symbol(symbol); + const std::string field = + "inteval->" + context->label_to_name((vptr)->label()); + // in scalar code load each such quantity from inteval once, into a + // local declared by generate_code(): stores to the stack may alias + // inteval's fields, so the compiler cannot hoist these loads itself. + // a vertex that refers to another takes its symbol from the referred + // vertex, so do not hoist it + if (context->cparams()->max_vector_length() == 1 && + !(vptr)->refers_to_another()) { + const std::string local = + "hv_" + context->label_to_name((vptr)->label()); + (vptr)->set_symbol(local); + if (hoisted_names.insert(local).second) + hoisted_precomputed_.emplace_back(local, field + "[0]"); + } else + (vptr)->set_symbol(field + "[vi]"); continue; } diff --git a/src/bin/libint/dg.h b/src/bin/libint/dg.h index 0f85abc8f..3bb8fa90e 100644 --- a/src/bin/libint/dg.h +++ b/src/bin/libint/dg.h @@ -341,6 +341,12 @@ class DirectedGraph : public std::enable_shared_from_this { */ FuncNameContainer func_names_; + /** precomputed quantities hoisted by assign_symbols() in scalar code, as + {local variable name, inteval field it is loaded from}, in the order + generate_code() declares them + */ + std::vector> hoisted_precomputed_; + #if !USE_ASSOCCONTAINER_BASED_DIRECTEDGRAPH static const unsigned int default_size_ = 100; #endif @@ -427,7 +433,7 @@ class DirectedGraph : public std::enable_shared_from_this { /// graph std::shared_ptr insert_expr_at( const std::shared_ptr& where, - const std::shared_ptr >& expr); + const std::shared_ptr>& expr); /// This function replaces RecurrenceRelations with concrete arithemtical /// expressions void replace_rr_with_expr(); @@ -529,7 +535,7 @@ void extract_symbols(const std::shared_ptr& dg); // use these functors with DirectedGraph::foreach struct PrerequisitesExtractor { - std::deque > vertices; + std::deque> vertices; void operator()(const std::shared_ptr& v); }; struct VertexPrinter {