20 AddMeasurement(Label::NumRvsdgNodesBefore,
rvsdg::nnodes(&graph.GetRootRegion()));
21 AddMeasurement(Label::NumRvsdgInputsBefore,
rvsdg::ninputs(&graph.GetRootRegion()));
22 AddTimer(Label::Timer).start();
28 AddMeasurement(Label::NumRvsdgNodesAfter,
rvsdg::nnodes(&graph.GetRootRegion()));
29 AddMeasurement(Label::NumRvsdgInputsAfter,
rvsdg::ninputs(&graph.GetRootRegion()));
30 GetTimer(Label::Timer).stop();
44 if (
const auto it = NumIterations_.find(®ion); it != NumIterations_.end())
63 const auto & graph = rvsdgModule.
Rvsdg();
77 bool reductionPerformed =
false;
78 size_t numIterations = 0;
82 reductionPerformed =
false;
98 if (reductionPerformed)
104 }
while (reductionPerformed);
112 bool reductionPerformed =
false;
120 if (reductionPerformed)
127 for (
size_t n = 0; n < structuralNode.
nsubregions(); n++)
129 const auto subregion = structuralNode.
subregion(n);
150 if (is<LoadNonVolatileOperation>(&simpleNode))
154 if (is<StoreNonVolatileOperation>(&simpleNode))
158 if (is<MemoryStateMergeOperation>(&simpleNode))
162 if (is<MemoryStateJoinOperation>(&simpleNode))
166 if (is<MemoryStateSplitOperation>(&simpleNode))
170 if (is<LambdaEntryMemoryStateSplitOperation>(&simpleNode))
172 return rvsdg::ReduceNode<LambdaEntryMemoryStateSplitOperation>(
176 if (is<CallExitMemoryStateSplitOperation>(&simpleNode))
178 return rvsdg::ReduceNode<CallExitMemoryStateSplitOperation>(
182 if (is<LambdaExitMemoryStateMergeOperation>(&simpleNode))
186 if (is<rvsdg::UnaryOperation>(&simpleNode))
192 if (is<rvsdg::BinaryOperation>(&simpleNode))
203 JLM_ASSERT(is<LoadNonVolatileOperation>(&simpleNode));
205 return rvsdg::ReduceNode<LoadNonVolatileOperation>(
NormalizeLoadNode, simpleNode);
211 JLM_ASSERT(is<StoreNonVolatileOperation>(&simpleNode));
219 JLM_ASSERT(is<rvsdg::BinaryOperation>(&simpleNode));
227 JLM_ASSERT(is<MemoryStateMergeOperation>(&simpleNode));
235 JLM_ASSERT(is<MemoryStateSplitOperation>(&simpleNode));
243 JLM_ASSERT(is<LambdaExitMemoryStateMergeOperation>(&simpleNode));
244 return rvsdg::ReduceNode<LambdaExitMemoryStateMergeOperation>(
249 std::optional<std::vector<rvsdg::Output *>>
252 const std::vector<rvsdg::Output *> &
operands)
254 static std::vector<rvsdg::NodeNormalization<LoadNonVolatileOperation>> loadNodeNormalizations(
261 return rvsdg::NormalizeSequence<LoadNonVolatileOperation>(
262 loadNodeNormalizations,
267 std::optional<std::vector<rvsdg::Output *>>
270 const std::vector<rvsdg::Output *> &
operands)
272 static std::vector<rvsdg::NodeNormalization<StoreNonVolatileOperation>> storeNodeNormalizations(
280 return rvsdg::NormalizeSequence<StoreNonVolatileOperation>(
281 storeNodeNormalizations,
286 std::optional<std::vector<rvsdg::Output *>>
289 const std::vector<rvsdg::Output *> &
operands)
291 static std::vector<rvsdg::NodeNormalization<MemoryStateMergeOperation>> normalizations(
297 return rvsdg::NormalizeSequence<MemoryStateMergeOperation>(normalizations, operation,
operands);
300 std::optional<std::vector<rvsdg::Output *>>
303 const std::vector<rvsdg::Output *> &
operands)
305 static std::vector<rvsdg::NodeNormalization<MemoryStateJoinOperation>> normalizations(
309 return rvsdg::NormalizeSequence<MemoryStateJoinOperation>(normalizations, operation,
operands);
312 std::optional<std::vector<rvsdg::Output *>>
315 const std::vector<rvsdg::Output *> &
operands)
317 static std::vector<rvsdg::NodeNormalization<MemoryStateSplitOperation>> normalizations(
322 return rvsdg::NormalizeSequence<MemoryStateSplitOperation>(normalizations, operation,
operands);
325 std::optional<std::vector<rvsdg::Output *>>
328 const std::vector<rvsdg::Output *> &
operands)
330 static std::vector<rvsdg::NodeNormalization<CallExitMemoryStateSplitOperation>> normalizations(
333 return rvsdg::NormalizeSequence<CallExitMemoryStateSplitOperation>(
339 std::optional<std::vector<rvsdg::Output *>>
342 const std::vector<rvsdg::Output *> &
operands)
344 static std::vector<rvsdg::NodeNormalization<LambdaEntryMemoryStateSplitOperation>> normalizations(
347 return rvsdg::NormalizeSequence<LambdaEntryMemoryStateSplitOperation>(
353 std::optional<std::vector<rvsdg::Output *>>
356 const std::vector<rvsdg::Output *> &
operands)
358 static std::vector<rvsdg::NodeNormalization<LambdaExitMemoryStateMergeOperation>> normalizations(
363 return rvsdg::NormalizeSequence<LambdaExitMemoryStateMergeOperation>(
static std::optional< std::vector< rvsdg::Output * > > NormalizeLambdaExitMemoryStateMerge(const CallExitMemoryStateSplitOperation &callExitSplitOperation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeCallEntryMemoryStateMerge(const LambdaEntryMemoryStateSplitOperation &lambdaEntrySplitOperation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadFromAlloca(const LambdaExitMemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreToAlloca(const LambdaExitMemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeAlloca(const LambdaExitMemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeIOBarrierAllocaAddress(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Redirect the address operand of the LoadNonVolatileOperation from an IOBarrierOperation when it can b...
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadStoreState(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
If the producer of a load's address is an alloca operation, then we can remove all state edges origin...
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateStates(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Remove duplicated state operands.
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadAlloca(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
If the producer of a load's address is an alloca operation, then we can remove all state edges origin...
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadStore(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Forwards the value from a store operation.
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateOperands(const MemoryStateJoinOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes duplicated operands from the MemoryStateJoinOperation.
static std::optional< std::vector< rvsdg::Output * > > NormalizeSingleOperand(const MemoryStateJoinOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes the MemoryStateJoinOperation as it has only a single operand, i.e., no joining is performed.
static std::optional< std::vector< rvsdg::Output * > > NormalizeNestedMerges(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
Fuses nested merges into a single merge.
static std::optional< std::vector< rvsdg::Output * > > NormalizeMergeSplit(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
Fuses nested splits into a single merge.
static std::optional< std::vector< rvsdg::Output * > > NormalizeSingleOperand(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes the MemoryStateMergeOperation as it has only a single operand, i.e., no merging is performed.
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateOperands(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes duplicated operands from the MemoryStateMergeOperation.
static std::optional< std::vector< rvsdg::Output * > > NormalizeNestedSplits(const MemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
Fuses nested splits into a single split.
static std::optional< std::vector< rvsdg::Output * > > NormalizeSingleResult(const MemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes the MemoryStateSplitOperation as it has only a single result, i.e., no splitting is performed...
static std::optional< std::vector< rvsdg::Output * > > NormalizeSplitMerge(const MemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes an idempotent split-merge pair.
bool AddIteration(const rvsdg::Region ®ion, size_t numIterations)
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
void End(const rvsdg::Graph &graph) noexcept
std::unordered_map< const rvsdg::Region *, size_t > NumIterations_
void Start(const rvsdg::Graph &graph) noexcept
std::optional< size_t > GetNumIterations(const rvsdg::Region ®ion) const noexcept
static bool ReduceLambdaExitMemoryStateMergeNode(rvsdg::SimpleNode &simpleNode)
static std::optional< std::vector< rvsdg::Output * > > NormalizeMemoryStateMergeNode(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
void ReduceNodesInRegion(rvsdg::Region ®ion)
static bool ReduceMemoryStateSplitNode(rvsdg::SimpleNode &simpleNode)
std::unique_ptr< Statistics > Statistics_
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadNode(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeLambdaEntryMemoryStateSplitNode(const LambdaEntryMemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeMemoryStateSplitNode(const MemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreNode(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
bool ReduceStructuralNode(rvsdg::StructuralNode &structuralNode)
static std::optional< std::vector< rvsdg::Output * > > NormalizeMemoryStateJoinNode(const MemoryStateJoinOperation &operation, const std::vector< rvsdg::Output * > &operands)
static bool ReduceSimpleNode(rvsdg::SimpleNode &simpleNode)
static bool ReduceBinaryNode(rvsdg::SimpleNode &simpleNode)
static bool ReduceStoreNode(rvsdg::SimpleNode &simpleNode)
static bool ReduceMemoryStateMergeNode(rvsdg::SimpleNode &simpleNode)
~NodeReduction() noexcept override
static std::optional< std::vector< rvsdg::Output * > > NormalizeCallExitMemoryStateSplitNode(const CallExitMemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
static bool ReduceGammaNode(rvsdg::StructuralNode &gammaNode)
static bool ReduceLoadNode(rvsdg::SimpleNode &simpleNode)
static std::optional< std::vector< rvsdg::Output * > > NormalizeLambdaExitMemoryStateMergeNode(const LambdaExitMemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeIOBarrierAllocaAddress(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Redirect the address operand of the StoreNonVolatileOperation from an IOBarrierOperation when it can ...
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreMux(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Swaps a memory state merge operation and a store operation.
static std::optional< std::vector< rvsdg::Output * > > normalizeStoreAllocaSingleUser(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreAlloca(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes unnecessary state from a store node when its address originates directly from an alloca node.
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreStore(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes a duplicated store to the same address.
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateStates(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Remove duplicated state operands.
Conditional operator / pattern matching.
Represent acyclic RVSDG subgraphs.
void prune(bool recursive)
const std::optional< util::FilePath > & SourceFilePath() const noexcept
size_t nsubregions() const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
Global memory state passed between functions.
void MatchTypeOrFail(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
std::optional< std::vector< rvsdg::Output * > > NormalizeBinaryOperation(const BinaryOperation &operation, const std::vector< rvsdg::Output * > &operands)
Applies the reductions implemented in the binary operations reduction functions.
bool ReduceGammaWithStaticallyKnownPredicate(Node &node)
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
size_t ninputs(const rvsdg::Region *region) noexcept