LIBINT 2.9.0
dg.h
1/*
2 * Copyright (C) 2004-2024 Edward F. Valeev
3 *
4 * This file is part of Libint compiler.
5 *
6 * Libint compiler is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Libint compiler is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Libint compiler. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#ifndef _libint2_src_bin_libint_dg_h_
22#define _libint2_src_bin_libint_dg_h_
23
24#include <dgvertex.h>
25#include <exception.h>
26#include <global_macros.h>
27#include <key.h>
28#include <smart_ptr.h>
29
30#include <algorithm>
31#include <cassert>
32#include <deque>
33#include <iostream>
34#include <list>
35#include <map>
36#include <stdexcept>
37#include <string>
38#include <vector>
39
40namespace libint2 {
41
42// class DGVertex;
43class DGArc;
44template <class T>
45class DGArcRel;
46template <class T>
47class AlgebraicOperator;
48class Strategy;
49class Tactic;
50class CodeContext;
51class MemoryManager;
52class ImplicitDimensions;
53class CodeSymbols;
54class GraphRegistry;
55class InternalGraphRegistry;
56
65class DirectedGraph : public std::enable_shared_from_this<DirectedGraph> {
66 public:
67 typedef DGVertex vertex;
68 typedef DGArc arc;
69 typedef std::shared_ptr<DGVertex> ver_ptr;
70 typedef std::shared_ptr<DGArc> arc_ptr;
71 typedef DGVertexKey key_type;
72 typedef std::multimap<key_type, ver_ptr> VPtrAssociativeContainer;
73 typedef std::list<ver_ptr> VPtrSequenceContainer;
74
75 typedef VPtrSequenceContainer targets;
76#if USE_ASSOCCONTAINER_BASED_DIRECTEDGRAPH
77 typedef VPtrAssociativeContainer vertices;
78#else
79 typedef VPtrSequenceContainer vertices;
80#endif
81 typedef targets::iterator target_iter;
82 typedef targets::const_iterator target_citer;
83 typedef vertices::iterator ver_iter;
84 typedef vertices::const_iterator ver_citer;
85 // not possible: typedef vertex::Address address;
86 typedef int address;
87 // not possible: typedef vertex::Size size;
88 typedef unsigned int size;
89 typedef std::vector<address> addresses;
90
91 private:
93 static inline const ver_ptr& vertex_ptr(
94 const VPtrAssociativeContainer::value_type& v) {
95 return v.second;
96 }
97 static inline const ver_ptr& vertex_ptr(
98 const VPtrSequenceContainer::value_type& v) {
99 return v;
100 }
102 static inline ver_ptr& vertex_ptr(VPtrAssociativeContainer::value_type& v) {
103 return v.second;
104 }
105 static inline ver_ptr& vertex_ptr(VPtrSequenceContainer::value_type& v) {
106 return v;
107 }
108
109 public:
114
116 unsigned int num_vertices() const { return stack_.size(); }
117#if 0
119 const vertices& all_vertices() const { return stack_; }
121 const targets& all_targets() const { return targets_; }
122#endif
126 const std::shared_ptr<DGVertex>& find(
127 const std::shared_ptr<DGVertex>& v) const {
128 return vertex_is_on(v);
129 }
130
134 std::shared_ptr<DGVertex> append_vertex(const std::shared_ptr<DGVertex>& v);
135
138 void append_target(const std::shared_ptr<DGVertex>&);
139
152 template <class I, class RR>
153 void append_target(const std::shared_ptr<I>& target) {
154 target->make_a_target();
155 recurse<I, RR>(target);
156 }
157
168 template <class RR>
170 typedef typename RR::TargetType TT;
171 typedef vertices::iterator iter;
172 for (iter v = stack_.begin(); v != stack_.end(); ++v) {
173 ver_ptr& vptr = vertex_ptr(*v);
174 if ((vptr)->num_exit_arcs() != 0) continue;
175 std::shared_ptr<TT> tptr = std::dynamic_pointer_cast<TT, DGVertex>(v);
176 if (tptr == 0) continue;
177
178 std::shared_ptr<RR> rr0(new RR(tptr));
179 const int num_children = rr0->num_children();
180
181 for (int c = 0; c < num_children; c++) {
182 std::shared_ptr<DGVertex> child = rr0->child(c);
183 std::shared_ptr<DGArc> arc(new DGArcRel<RR>(tptr, child, rr0));
184 tptr->add_exit_arc(arc);
185
186 recurse<RR>(child);
187 }
188 }
189 }
190
197 void apply(const std::shared_ptr<Strategy>& strategy,
198 const std::shared_ptr<Tactic>& tactic);
199
200 typedef void (DGVertex::*DGVertexMethodPtr)();
204 template <DGVertexMethodPtr method>
205 void apply_at(const std::shared_ptr<DGVertex>& vertex) const {
206 ((vertex.get())->*method)();
207 typedef DGVertex::ArcSetType::const_iterator aciter;
208 const aciter abegin = vertex->first_exit_arc();
209 const aciter aend = vertex->plast_exit_arc();
210 for (aciter a = abegin; a != aend; ++a) apply_at<method>((*a)->dest());
211 }
212
214 template <class Method>
215 void foreach (Method& m) {
216 typedef vertices::iterator iter;
217 for (iter v = stack_.begin(); v != stack_.end(); ++v) {
218 ver_ptr& vptr = vertex_ptr(*v);
219 m(vptr);
220 }
221 }
222
224 template <class Method>
225 void foreach (Method& m) const {
226 typedef vertices::const_iterator citer;
227 for (citer v = stack_.begin(); v != stack_.end(); ++v) {
228 const ver_ptr& vptr = vertex_ptr(*v);
229 m(vptr);
230 }
231 }
233 template <class Method>
234 void rforeach(Method& m) {
235 typedef vertices::reverse_iterator riter;
236 for (riter v = stack_.rbegin(); v != stack_.rend(); ++v) {
237 ver_ptr& vptr = vertex_ptr(*v);
238 m(vptr);
239 }
240 }
241
243 template <class Method>
244 void rforeach(Method& m) const {
245 typedef vertices::const_reverse_iterator criter;
246 for (criter v = stack_.rbegin(); v != stack_.rend(); ++v) {
247 const ver_ptr& vptr = vertex_ptr(*v);
248 m(vptr);
249 }
250 }
251
256 void optimize_rr_out(const std::shared_ptr<CodeContext>& context);
257
261 void traverse();
262
265 void update_func_names();
266
268 void debug_print_traversal(std::ostream& os) const;
269
275 void print_to_dot(bool symbols, std::ostream& os = std::cout) const;
276
285 void generate_code(const std::shared_ptr<CodeContext>& context,
286 const std::shared_ptr<MemoryManager>& memman,
287 const std::shared_ptr<ImplicitDimensions>& dims,
288 const std::shared_ptr<CodeSymbols>& args,
289 const std::string& label, std::ostream& decl,
290 std::ostream& code);
291
295 void reset();
296
300 template <class RR>
301 unsigned int num_children_on(const std::shared_ptr<RR>& rr) const {
302 unsigned int nchildren = rr->num_children();
303 unsigned int nchildren_on_stack = 0;
304 for (unsigned int c = 0; c < nchildren; c++) {
305 if (!vertex_is_on(rr->rr_child(c)))
306 continue;
307 else
308 nchildren_on_stack++;
309 }
310
311 return nchildren_on_stack;
312 }
313
315 std::shared_ptr<GraphRegistry>& registry() { return registry_; }
316 const std::shared_ptr<GraphRegistry>& registry() const { return registry_; }
317
319 const std::string& label() const { return label_; }
321 void set_label(const std::string& new_label) { label_ = new_label; }
322
324 bool missing_prerequisites() const;
325
326 private:
328 vertices stack_;
331 targets targets_;
333 addresses target_accums_;
334
335 // graph label, used for annotating internal work, e.g. graphviz plots
336 std::string label_;
337
338 typedef std::map<std::string, bool> FuncNameContainer;
342 FuncNameContainer func_names_;
343
344#if !USE_ASSOCCONTAINER_BASED_DIRECTEDGRAPH
345 static const unsigned int default_size_ = 100;
346#endif
347
348 // maintains data about the graph which does not belong IN the graph
349 std::shared_ptr<GraphRegistry> registry_;
350 // maintains private data about the graph which does not belong IN the graph
351 std::shared_ptr<InternalGraphRegistry> iregistry_;
352
354 std::shared_ptr<InternalGraphRegistry>& iregistry() { return iregistry_; }
355 const std::shared_ptr<InternalGraphRegistry>& iregistry() const {
356 return iregistry_;
357 }
358
361 std::shared_ptr<DGVertex> add_vertex(const std::shared_ptr<DGVertex>&);
364 void add_new_vertex(const std::shared_ptr<DGVertex>&);
366 const std::shared_ptr<DGVertex>& vertex_is_on(
367 const std::shared_ptr<DGVertex>& vertex) const;
369 void del_vertex(vertices::iterator&);
373 template <class I, class RR>
374 void recurse(const std::shared_ptr<I>& vertex) {
375 std::shared_ptr<DGVertex> dgvertex = add_vertex(vertex);
376 if (dgvertex != vertex) return;
377
378 std::shared_ptr<RR> rr0(new RR(vertex));
379 const int num_children = rr0->num_children();
380
381 for (int c = 0; c < num_children; c++) {
382 std::shared_ptr<DGVertex> child = rr0->child(c);
383 std::shared_ptr<DGArc> arc(new DGArcRel<RR>(vertex, child, rr0));
384 vertex->add_exit_arc(arc);
385
386 std::shared_ptr<I> child_cast =
387 std::dynamic_pointer_cast<I, DGVertex>(child);
388 if (child_cast == 0)
389 throw std::runtime_error(
390 "DirectedGraph::recurse(const std::shared_ptr<I>& vertex) -- "
391 "dynamic cast failed, most probably this is a logic error!");
392 recurse<I, RR>(child_cast);
393 }
394 }
395
399 template <class RR>
400 void recurse(const std::shared_ptr<DGVertex>& vertex) {
401 std::shared_ptr<DGVertex> dgvertex = add_vertex(vertex);
402 if (dgvertex != vertex) return;
403
404 typedef typename RR::TargetType TT;
405 std::shared_ptr<TT> tptr = std::dynamic_pointer_cast<TT, DGVertex>(vertex);
406 if (tptr == 0) return;
407
408 std::shared_ptr<RR> rr0(new RR(tptr));
409 const int num_children = rr0->num_children();
410
411 for (int c = 0; c < num_children; c++) {
412 std::shared_ptr<DGVertex> child = rr0->child(c);
413 std::shared_ptr<DGArc> arc(new DGArcRel<RR>(vertex, child, rr0));
414 vertex->add_exit_arc(arc);
415
416 recurse<RR>(child);
417 }
418 }
419
423 void apply_to(const std::shared_ptr<DGVertex>& vertex,
424 const std::shared_ptr<Strategy>& strategy,
425 const std::shared_ptr<Tactic>& tactic);
428 std::shared_ptr<DGVertex> insert_expr_at(
429 const std::shared_ptr<DGVertex>& where,
430 const std::shared_ptr<AlgebraicOperator<DGVertex> >& expr);
433 void replace_rr_with_expr();
436 void remove_trivial_arithmetics();
441 void handle_trivial_nodes(const std::shared_ptr<CodeContext>& context);
443 void remove_disconnected_vertices();
447 void find_subtrees();
450 void find_subtrees_from(const std::shared_ptr<DGVertex>& v);
456 bool remove_vertex_at(const std::shared_ptr<DGVertex>& v1,
457 const std::shared_ptr<DGVertex>& v2);
458
459 // Which vertex is the first to compute
460 std::shared_ptr<DGVertex> first_to_compute_;
461 // prepare_to_traverse must be called before actual traversal
462 void prepare_to_traverse();
463 // traverse_from(arc) build recurively the traversal order
464 void traverse_from(const std::shared_ptr<DGArc>&);
465 // schedule_computation(vertex) puts vertex first in the computation order
466 void schedule_computation(const std::shared_ptr<DGVertex>&);
467
468 // Compute addresses on stack assuming that quantities larger than
469 // min_size_to_alloc to be allocated on stack
470 void allocate_mem(const std::shared_ptr<MemoryManager>& memman,
471 const std::shared_ptr<ImplicitDimensions>& dims,
472 unsigned int min_size_to_alloc = 1);
473 // Assign symbols to the vertices
474 void assign_symbols(const std::shared_ptr<CodeContext>& context,
475 const std::shared_ptr<ImplicitDimensions>& dims);
476 // If v is an AlgebraicOperator, assign (recursively) symbol to the operator.
477 // All other must have been already assigned
478 void assign_oper_symbol(const std::shared_ptr<CodeContext>& context,
479 std::shared_ptr<DGVertex>& v);
480 // Print the code using symbols generated with assign_symbols()
481 void print_def(const std::shared_ptr<CodeContext>& context, std::ostream& os,
482 const std::shared_ptr<ImplicitDimensions>& dims,
483 const std::shared_ptr<CodeSymbols>& args);
484
490 bool cannot_enclose_in_outer_vloop() const;
491};
492
493//
494// Nonmember utilities
495//
496
498inline const DirectedGraph::ver_ptr& vertex_ptr(
499 const DirectedGraph::VPtrAssociativeContainer::value_type& v) {
500 return v.second;
501}
502inline const DirectedGraph::ver_ptr& vertex_ptr(
503 const DirectedGraph::VPtrSequenceContainer::value_type& v) {
504 return v;
505}
507inline DirectedGraph::ver_ptr& vertex_ptr(
508 DirectedGraph::VPtrAssociativeContainer::value_type& v) {
509 return v.second;
510}
511inline DirectedGraph::ver_ptr& vertex_ptr(
512 DirectedGraph::VPtrSequenceContainer::value_type& v) {
513 return v;
514}
515
516#if USE_ASSOCCONTAINER_BASED_DIRECTEDGRAPH
517inline DirectedGraph::key_type key(const DGVertex& v);
518#endif
519
520//
521// Nonmember predicates
522//
523
525bool nonunrolled_targets(const DirectedGraph::targets& targets);
526
528void extract_symbols(const std::shared_ptr<DirectedGraph>& dg);
529
530// use these functors with DirectedGraph::foreach
532 std::deque<std::shared_ptr<DGVertex> > vertices;
533 void operator()(const std::shared_ptr<DGVertex>& v);
534};
536 VertexPrinter(std::ostream& ostr) : os(ostr) {}
537 std::ostream& os;
538 void operator()(const std::shared_ptr<DGVertex>& v);
539};
540
541}; // namespace libint2
542
543#endif
Class DGArcRel describes arcs in a directed graph which is represented by a relationship ArcRel.
Definition dgarc.h:85
Class DGArc describes arcs in a directed graph.
Definition dgarc.h:35
This is a vertex of a Directed Graph (DG)
Definition dgvertex.h:44
ArcSetType::const_iterator plast_exit_arc() const
returns children::end()
Definition dgvertex.h:128
ArcSetType::const_iterator first_exit_arc() const
returns children::begin()
Definition dgvertex.h:124
DirectedGraph is an implementation of a directed graph composed of vertices represented by DGVertex o...
Definition dg.h:65
void debug_print_traversal(std::ostream &os) const
Prints out call sequence.
Definition dg.cc:346
void rforeach(Method &m) const
calls Method(v) for each v, iterating in reverse direction
Definition dg.h:244
void print_to_dot(bool symbols, std::ostream &os=std::cout) const
Prints out the graph in format understood by program "dot" of package "graphviz".
Definition dg.cc:389
void reset()
Resets the graph and all vertices.
Definition dg.cc:416
unsigned int num_children_on(const std::shared_ptr< RR > &rr) const
num_children_on(rr) returns the number of children of rr which are already on this graph.
Definition dg.h:301
const targets & all_targets() const
Returns all targets.
Definition dg.h:121
std::shared_ptr< DGVertex > append_vertex(const std::shared_ptr< DGVertex > &v)
appends v to the graph.
Definition dg.cc:83
bool missing_prerequisites() const
return true if there are vertices with 0 children but not pre-computed
Definition dg.cc:2351
void apply_to_all()
apply_to_all applies RR to all vertices already on the graph.
Definition dg.h:169
void update_func_names()
update func_names_
Definition dg.cc:2229
std::shared_ptr< GraphRegistry > & registry()
Returns the registry.
Definition dg.h:315
DirectedGraph()
Creates an empty DAG.
Definition dg.cc:61
unsigned int num_vertices() const
Returns the number of vertices.
Definition dg.h:116
void append_target(const std::shared_ptr< I > &target)
append_target appends I to the graph as a target vertex and applies RR to it.
Definition dg.h:153
void generate_code(const std::shared_ptr< CodeContext > &context, const std::shared_ptr< MemoryManager > &memman, const std::shared_ptr< ImplicitDimensions > &dims, const std::shared_ptr< CodeSymbols > &args, const std::string &label, std::ostream &decl, std::ostream &code)
Generates code for the current computation using context.
Definition dg.cc:1057
void append_target(const std::shared_ptr< DGVertex > &)
non-template append_target appends the vertex to the graph as a target
Definition dg.cc:77
const std::string & label() const
return the graph label
Definition dg.h:319
const vertices & all_vertices() const
Returns all vertices.
Definition dg.h:119
void set_label(const std::string &new_label)
sets label to new_label
Definition dg.h:321
void apply_at(const std::shared_ptr< DGVertex > &vertex) const
apply_at<method>(vertex) calls method() on vertex and all of its descendants
Definition dg.h:205
void optimize_rr_out(const std::shared_ptr< CodeContext > &context)
after Strategy has been applied, simple recurrence relations need to be optimized away.
Definition dg.cc:501
const std::shared_ptr< DGVertex > & find(const std::shared_ptr< DGVertex > &v) const
Find vertex v or it's equivalent on the graph.
Definition dg.h:126
void rforeach(Method &m)
calls Method(v) for each v, iterating in reverse direction
Definition dg.h:234
void traverse()
after all apply's have been called, traverse() construct a heuristic order of traversal for the graph...
Definition dg.cc:260
void apply(const std::shared_ptr< Strategy > &strategy, const std::shared_ptr< Tactic > &tactic)
after all append_target's have been called, apply(strategy,tactic) constructs a graph.
Definition dg.cc:434
Type/Instance combination serves as a key to quickly compare 2 polymorphic Singletons.
Definition key.h:35
Defaults definitions for various parameters assumed by Libint.
Definition algebra.cc:24
bool nonunrolled_targets(const DirectedGraph::targets &targets)
return true if there are non-unrolled targets
Definition dg.cc:2381
const DirectedGraph::ver_ptr & vertex_ptr(const DirectedGraph::VPtrAssociativeContainer::value_type &v)
converts what is stored in the container to a smart ptr to the vertex
Definition dg.h:498
void extract_symbols(const std::shared_ptr< DirectedGraph > &dg)
extracts external symbols and RRs from the graph
Definition dg.cc:2394
Definition dg.h:535