souffle  2.0.2-371-g6315b36
Public Member Functions | Protected Member Functions | Protected Attributes
souffle::ram::transform::HoistAggregateTransformer Class Reference

#include <HoistAggregate.h>

Inheritance diagram for souffle::ram::transform::HoistAggregateTransformer:
Inheritance graph
Collaboration diagram for souffle::ram::transform::HoistAggregateTransformer:
Collaboration graph

Public Member Functions

std::string getName () const override
 @Brief get name of the transformer More...
 
bool hoistAggregate (Program &program)
 Apply hoistAggregate to the whole program. More...
 
- Public Member Functions inherited from souffle::ram::transform::Transformer
bool apply (TranslationUnit &translationUnit)
 @Brief apply the transformer to a translation unit @Param translationUnit that will be transformed. More...
 
virtual ~Transformer ()=default
 

Protected Member Functions

bool transform (TranslationUnit &translationUnit) override
 @Brief transform the translation unit / used by apply @Param translationUnit that will be transformed. More...
 

Protected Attributes

analysis::LevelAnalysisrla {nullptr}
 

Detailed Description

Definition at line 38 of file HoistAggregate.h.

Member Function Documentation

◆ getName()

std::string souffle::ram::transform::HoistAggregateTransformer::getName ( ) const
inlineoverridevirtual

@Brief get name of the transformer

Implements souffle::ram::transform::Transformer.

Definition at line 40 of file HoistAggregate.h.

49  :
50  analysis::LevelAnalysis* rla{nullptr};

◆ hoistAggregate()

bool souffle::ram::transform::HoistAggregateTransformer::hoistAggregate ( Program program)

Apply hoistAggregate to the whole program.

Parameters
RAMprogram
Returns
A flag indicating whether the RAM program has been changed.

Pushes an Aggregate up the loop nest if possible

Definition at line 34 of file HoistAggregate.cpp.

40  {
41  Own<NestedOperation> newAgg;
42  bool priorTupleOp = false;
43  std::function<Own<Node>(Own<Node>)> aggRewriter = [&](Own<Node> node) -> Own<Node> {
44  if (isA<Aggregate>(node.get())) {
45  auto* tupleOp = dynamic_cast<TupleOperation*>(node.get());
46  assert(tupleOp != nullptr && "aggregate conversion to tuple operation failed");
47  if (rla->getLevel(tupleOp) == -1 && !priorTupleOp) {
48  changed = true;
49  newAgg = souffle::clone(tupleOp);
50  assert(newAgg != nullptr && "failed to make a clone");
51  return souffle::clone(&tupleOp->getOperation());
52  }
53  } else if (isA<TupleOperation>(node.get())) {
54  // tuple operation that is a non-aggregate
55  priorTupleOp = true;
56  }
57  node->apply(makeLambdaRamMapper(aggRewriter));
58  return node;
59  };
60  const_cast<Query*>(&query)->apply(makeLambdaRamMapper(aggRewriter));
61  if (newAgg != nullptr) {
62  newAgg->rewrite(&newAgg->getOperation(), souffle::clone(&query.getOperation()));
63  const_cast<Query*>(&query)->rewrite(&query.getOperation(), std::move(newAgg));
64  }
65  });
66 
67  // hoist a single aggregate to an outer scope that is data-dependent on a prior operation.
68  visitDepthFirst(program, [&](const Query& query) {
69  int newLevel = -1;
70  Own<NestedOperation> newAgg;
71  int priorOpLevel = -1;
72 
73  std::function<Own<Node>(Own<Node>)> aggRewriter = [&](Own<Node> node) -> Own<Node> {
74  if (isA<AbstractAggregate>(node.get())) {
75  auto* tupleOp = dynamic_cast<TupleOperation*>(node.get());
76  assert(tupleOp != nullptr && "aggregate conversion to nested operation failed");
77  int dataDepLevel = rla->getLevel(tupleOp);
78  if (dataDepLevel != -1 && dataDepLevel < tupleOp->getTupleId() - 1) {
79  // If all tuple ops between the data-dependence level and agg
80  // are aggregates, then we do not hoist, i.e., we would
81  // continuously swap their positions.
82  if (dataDepLevel != priorOpLevel) {
83  changed = true;
84  newLevel = dataDepLevel;
85  newAgg = souffle::clone(tupleOp);
86  assert(newAgg != nullptr && "failed to make a clone");
87  return souffle::clone(&tupleOp->getOperation());
88  }
89  }
90  } else if (const TupleOperation* tupleOp = dynamic_cast<TupleOperation*>(node.get())) {
91  priorOpLevel = tupleOp->getTupleId();
92  }
93  node->apply(makeLambdaRamMapper(aggRewriter));
94  if (auto* search = dynamic_cast<TupleOperation*>(node.get())) {
95  if (newAgg != nullptr && search->getTupleId() == newLevel) {
96  newAgg->rewrite(&newAgg->getOperation(), souffle::clone(&search->getOperation()));
97  search->rewrite(&search->getOperation(), std::move(newAgg));
98  }
99  }
100  return node;
101  };
102  const_cast<Query*>(&query)->apply(makeLambdaRamMapper(aggRewriter));
103  });
104  return changed;
105 } // namespace souffle
106 
107 } // namespace souffle::ram::transform

References souffle::ram::transform::Transformer::apply(), souffle::clone(), souffle::ram::analysis::LevelAnalysis::getLevel(), souffle::ram::Query::getOperation(), souffle::ram::makeLambdaRamMapper(), and rla.

Here is the call graph for this function:

◆ transform()

bool souffle::ram::transform::HoistAggregateTransformer::transform ( TranslationUnit translationUnit)
inlineoverrideprotectedvirtual

@Brief transform the translation unit / used by apply @Param translationUnit that will be transformed.

@Return flag reporting whether the RAM program has changed

Implements souffle::ram::transform::Transformer.

Definition at line 55 of file HoistAggregate.h.

Field Documentation

◆ rla

analysis::LevelAnalysis* souffle::ram::transform::HoistAggregateTransformer::rla {nullptr}
protected

Definition at line 54 of file HoistAggregate.h.

Referenced by hoistAggregate().


The documentation for this class was generated from the following files:
souffle::ram::analysis::LevelAnalysis::getLevel
int getLevel(const Node *value) const
Get level of a RAM expression/condition.
Definition: Level.cpp:64
souffle::ram::transform::Transformer::apply
bool apply(TranslationUnit &translationUnit)
@Brief apply the transformer to a translation unit @Param translationUnit that will be transformed.
Definition: Transformer.cpp:39
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
souffle::ram::transform::HoistAggregateTransformer::rla
analysis::LevelAnalysis * rla
Definition: HoistAggregate.h:54
souffle::ram::visitDepthFirst
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the RAM fragments rooted by the given node recursively i...
Definition: Visitor.h:357
souffle::ram::makeLambdaRamMapper
LambdaNodeMapper< Lambda > makeLambdaRamMapper(const Lambda &lambda)
Creates a node mapper based on a corresponding lambda expression.
Definition: LambdaNodeMapper.h:67