Jlm
RvsdgToIpGraphConverter.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2025 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
13 #include <jlm/rvsdg/delta.hpp>
14 #include <jlm/rvsdg/gamma.hpp>
15 #include <jlm/rvsdg/traverser.hpp>
16 #include <jlm/util/Statistics.hpp>
17 #include <jlm/util/time.hpp>
18 
19 #include <vector>
20 
21 namespace jlm::llvm
22 {
23 
25 {
26 public:
27  explicit Context(InterProceduralGraphModule & ipGraphModule)
28  : ControlFlowGraph_(nullptr),
29  IPGraphModule_(ipGraphModule),
31  {}
32 
33  Context(const Context &) = delete;
34 
35  Context(Context &&) = delete;
36 
37  Context &
38  operator=(const Context &) = delete;
39 
40  Context &
41  operator=(Context &&) = delete;
42 
43  [[nodiscard]] InterProceduralGraphModule &
44  GetIpGraphModule() const noexcept
45  {
46  return IPGraphModule_;
47  }
48 
49  void
50  InsertVariable(const rvsdg::Output * output, const llvm::Variable * variable)
51  {
52  JLM_ASSERT(VariableMap_.find(output) == VariableMap_.end());
53  JLM_ASSERT(*output->Type() == *variable->Type());
54  VariableMap_[output] = variable;
55  }
56 
57  const llvm::Variable *
58  GetVariable(const rvsdg::Output * output)
59  {
60  const auto it = VariableMap_.find(output);
61  JLM_ASSERT(it != VariableMap_.end());
62  return it->second;
63  }
64 
65  BasicBlock *
66  GetLastProcessedBasicBlock() const noexcept
67  {
69  }
70 
71  void
72  SetLastProcessedBasicBlock(BasicBlock * lastProcessedBasicBlock) noexcept
73  {
74  LastProcessedBasicBlock = lastProcessedBasicBlock;
75  }
76 
78  GetControlFlowGraph() const noexcept
79  {
80  return ControlFlowGraph_;
81  }
82 
83  void
85  {
86  ControlFlowGraph_ = cfg;
87  }
88 
89  static std::unique_ptr<Context>
91  {
92  return std::make_unique<Context>(ipGraphModule);
93  }
94 
95 private:
99  std::unordered_map<const rvsdg::Output *, const llvm::Variable *> VariableMap_;
100 };
101 
103 {
104 public:
105  ~Statistics() override = default;
106 
107  explicit Statistics(const util::FilePath & filename)
108  : util::Statistics(Id::RvsdgDestruction, filename)
109  {}
110 
111  void
112  Start(const rvsdg::Graph & graph) noexcept
113  {
114  AddMeasurement(Label::NumRvsdgNodes, rvsdg::nnodes(&graph.GetRootRegion()));
116  }
117 
118  void
120  {
123  }
124 
125  static std::unique_ptr<Statistics>
126  Create(const util::FilePath & sourceFile)
127  {
128  return std::make_unique<Statistics>(sourceFile);
129  }
130 };
131 
133 
135 
136 std::unique_ptr<DataNodeInit>
138 {
139  const auto subregion = deltaNode.subregion();
140 
141  // add delta dependencies to context
142  for (size_t n = 0; n < deltaNode.ninputs(); n++)
143  {
144  const auto variable = Context_->GetVariable(deltaNode.input(n)->origin());
145  Context_->InsertVariable(deltaNode.input(n)->arguments.first(), variable);
146  }
147 
148  if (subregion->numNodes() == 0)
149  {
150  auto value = Context_->GetVariable(subregion->result(0)->origin());
151  return std::make_unique<DataNodeInit>(value);
152  }
153 
154  tacsvector_t tacs;
155  for (const auto & node : rvsdg::TopDownTraverser(deltaNode.subregion()))
156  {
157  JLM_ASSERT(node->noutputs() == 1);
158  const auto output = node->output(0);
159 
160  // collect operand variables
161  std::vector<const Variable *> operands;
162  for (size_t n = 0; n < node->ninputs(); n++)
163  operands.push_back(Context_->GetVariable(node->input(n)->origin()));
164 
165  // convert node to tac
166  auto op = node->GetOperation().copy();
167  tacs.push_back(ThreeAddressCode::create(
168  std::unique_ptr<rvsdg::SimpleOperation>(
169  util::assertedCast<rvsdg::SimpleOperation>(op.release())),
170  operands));
171  Context_->InsertVariable(output, tacs.back()->result(0));
172  }
173 
174  return std::make_unique<DataNodeInit>(std::move(tacs));
175 }
176 
177 void
179 {
180  const auto entryBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
181  Context_->GetLastProcessedBasicBlock()->add_outedge(entryBlock);
182  Context_->SetLastProcessedBasicBlock(entryBlock);
183 
184  for (const auto & node : rvsdg::TopDownTraverser(&region))
185  ConvertNode(*node);
186 
187  const auto exitBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
188  Context_->GetLastProcessedBasicBlock()->add_outedge(exitBlock);
189  Context_->SetLastProcessedBasicBlock(exitBlock);
190 }
191 
192 std::unique_ptr<ControlFlowGraph>
194 {
195  JLM_ASSERT(Context_->GetLastProcessedBasicBlock() == nullptr);
196  const auto & lambdaOperation = *util::assertedCast<LlvmLambdaOperation>(&lambda.GetOperation());
197 
198  auto controlFlowGraph = ControlFlowGraph::create(Context_->GetIpGraphModule());
199  const auto entryBlock = BasicBlock::create(*controlFlowGraph);
200  controlFlowGraph->exit()->divert_inedges(entryBlock);
201  Context_->SetLastProcessedBasicBlock(entryBlock);
202  Context_->SetControlFlowGraph(controlFlowGraph.get());
203 
204  // add function arguments
205  for (const auto functionArgument : lambda.GetFunctionArguments())
206  {
207  auto name = util::strfmt("_a", functionArgument->index(), "_");
208  auto argument = Argument::create(
209  name,
210  functionArgument->Type(),
211  lambdaOperation.GetArgumentAttributes(functionArgument->index()));
212  const auto variable = controlFlowGraph->entry()->append_argument(std::move(argument));
213  Context_->InsertVariable(functionArgument, variable);
214  }
215 
216  // add context variables
217  for (const auto & [input, inner] : lambda.GetContextVars())
218  {
219  const auto variable = Context_->GetVariable(input->origin());
220  Context_->InsertVariable(inner, variable);
221  }
222 
223  ConvertRegion(*lambda.subregion());
224 
225  // add results
226  for (const auto result : lambda.GetFunctionResults())
227  controlFlowGraph->exit()->append_result(Context_->GetVariable(result->origin()));
228 
229  Context_->GetLastProcessedBasicBlock()->add_outedge(controlFlowGraph->exit());
230  Context_->SetLastProcessedBasicBlock(nullptr);
231  Context_->SetControlFlowGraph(nullptr);
232 
233  straighten(*controlFlowGraph);
234  JLM_ASSERT(is_closed(*controlFlowGraph));
235  return controlFlowGraph;
236 }
237 
238 void
240 {
241  std::vector<const Variable *> operands;
242  for (size_t n = 0; n < simpleNode.ninputs(); n++)
243  operands.push_back(Context_->GetVariable(simpleNode.input(n)->origin()));
244 
245  auto operation = simpleNode.GetOperation().copy();
246  Context_->GetLastProcessedBasicBlock()->append_last(ThreeAddressCode::create(
247  std::unique_ptr<rvsdg::SimpleOperation>(
248  util::assertedCast<rvsdg::SimpleOperation>(operation.release())),
249  operands));
250 
251  for (size_t n = 0; n < simpleNode.noutputs(); n++)
252  Context_->InsertVariable(
253  simpleNode.output(n),
254  Context_->GetLastProcessedBasicBlock()->last()->result(n));
255 }
256 
257 void
259 {
260  const auto numSubregions = gammaNode.nsubregions();
261  const auto predicate = gammaNode.predicate()->origin();
262  const auto controlFlowGraph = Context_->GetControlFlowGraph();
263 
264  const auto entryBlock = BasicBlock::create(*controlFlowGraph);
265  const auto exitBlock = BasicBlock::create(*controlFlowGraph);
266  Context_->GetLastProcessedBasicBlock()->add_outedge(entryBlock);
267 
268  // convert gamma regions
269  std::vector<ControlFlowGraphNode *> phi_nodes;
270  entryBlock->append_last(BranchOperation::create(numSubregions, Context_->GetVariable(predicate)));
271  auto entryvars = gammaNode.GetEntryVars();
272  for (size_t n = 0; n < gammaNode.nsubregions(); n++)
273  {
274  const auto subregion = gammaNode.subregion(n);
275 
276  // add arguments to context
277  for (size_t i = 0; i < entryvars.size(); i++)
278  {
279  auto & entryvar = entryvars[i];
280  Context_->InsertVariable(
281  entryvar.branchArgument[n],
282  Context_->GetVariable(entryvar.input->origin()));
283  }
284 
285  // convert subregion
286  const auto regionEntryBlock = BasicBlock::create(*controlFlowGraph);
287  entryBlock->add_outedge(regionEntryBlock);
288  Context_->SetLastProcessedBasicBlock(regionEntryBlock);
289  ConvertRegion(*subregion);
290 
291  phi_nodes.push_back(Context_->GetLastProcessedBasicBlock());
292  Context_->GetLastProcessedBasicBlock()->add_outedge(exitBlock);
293  }
294 
295  // add phi instructions
296  for (size_t n = 0; n < gammaNode.noutputs(); n++)
297  {
298  const auto output = gammaNode.output(n);
299 
300  bool invariant = true;
301  std::vector<std::pair<const Variable *, ControlFlowGraphNode *>> arguments;
302  for (size_t r = 0; r < gammaNode.nsubregions(); r++)
303  {
304  const auto origin = gammaNode.subregion(r)->result(n)->origin();
305 
306  auto v = Context_->GetVariable(origin);
307  arguments.push_back(std::make_pair(v, phi_nodes[r]));
308  invariant &= (v == Context_->GetVariable(gammaNode.subregion(0)->result(n)->origin()));
309  }
310 
311  if (invariant)
312  {
313  // all operands are the same
314  Context_->InsertVariable(output, arguments[0].first);
315  continue;
316  }
317 
318  // create phi instruction
319  exitBlock->append_last(SsaPhiOperation::create(arguments, output->Type()));
320  Context_->InsertVariable(output, exitBlock->last()->result(0));
321  }
322 
323  Context_->SetLastProcessedBasicBlock(exitBlock);
324 }
325 
326 bool
328  const rvsdg::ThetaNode::LoopVar & loopVar,
329  const Variable & v)
330 {
331  // FIXME: solely decide on the input instead of using the variable
332  if (is<GlobalVariable>(&v))
333  return false;
334 
335  if (ThetaLoopVarIsInvariant(loopVar))
336  return false;
337 
338  if (loopVar.pre->nusers() == 0)
339  return false;
340 
341  return true;
342 }
343 
344 void
346 {
347  const auto subregion = thetaNode.subregion();
348  const auto predicate = subregion->result(0)->origin();
349 
350  auto preEntryBlock = Context_->GetLastProcessedBasicBlock();
351  const auto entryBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
352  preEntryBlock->add_outedge(entryBlock);
353  Context_->SetLastProcessedBasicBlock(entryBlock);
354 
355  // create SSA phi nodes in entry block and add arguments to context
356  std::vector<llvm::ThreeAddressCode *> phis;
357  for (const auto & loopVar : thetaNode.GetLoopVars())
358  {
359  auto variable = Context_->GetVariable(loopVar.input->origin());
360  if (RequiresSsaPhiOperation(loopVar, *variable))
361  {
362  auto phi = entryBlock->append_last(SsaPhiOperation::create({}, loopVar.pre->Type()));
363  phis.push_back(phi);
364  variable = phi->result(0);
365  }
366  Context_->InsertVariable(loopVar.pre, variable);
367  }
368 
369  ConvertRegion(*subregion);
370 
371  // add phi operands and results to context
372  size_t phiIndex = 0;
373  for (const auto & loopVar : thetaNode.GetLoopVars())
374  {
375  auto entryVariable = Context_->GetVariable(loopVar.input->origin());
376  if (RequiresSsaPhiOperation(loopVar, *entryVariable))
377  {
378  auto resultVariable = Context_->GetVariable(loopVar.post->origin());
379  const auto phi = phis[phiIndex++];
380  phi->replace(
382  { preEntryBlock, Context_->GetLastProcessedBasicBlock() },
383  resultVariable->Type()),
384  { entryVariable, resultVariable });
385  Context_->InsertVariable(loopVar.output, resultVariable);
386  }
387  else
388  {
389  Context_->InsertVariable(loopVar.output, Context_->GetVariable(loopVar.post->origin()));
390  }
391  }
392  JLM_ASSERT(phiIndex == phis.size());
393 
394  Context_->GetLastProcessedBasicBlock()->append_last(
395  BranchOperation::create(2, Context_->GetVariable(predicate)));
396  const auto exitBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
397  Context_->GetLastProcessedBasicBlock()->add_outedge(exitBlock);
398  Context_->GetLastProcessedBasicBlock()->add_outedge(entryBlock);
399  Context_->SetLastProcessedBasicBlock(exitBlock);
400 }
401 
402 void
404 {
405  auto & ipGraphModule = Context_->GetIpGraphModule();
406  auto & ipGraph = ipGraphModule.ipgraph();
407 
408  const auto & operation = *util::assertedCast<LlvmLambdaOperation>(&lambdaNode.GetOperation());
409  const auto functionNode = FunctionNode::create(
410  ipGraph,
411  operation.name(),
412  operation.Type(),
413  operation.linkage(),
414  operation.attributes());
415  const auto variable = ipGraphModule.create_variable(functionNode);
416 
417  functionNode->add_cfg(CreateControlFlowGraph(lambdaNode));
418  Context_->InsertVariable(lambdaNode.output(), variable);
419 }
420 
421 void
423 {
424  const auto subregion = phiNode.subregion();
425  auto & ipGraphModule = Context_->GetIpGraphModule();
426  auto & ipGraph = ipGraphModule.ipgraph();
427 
428  // add dependencies to context
429  for (size_t n = 0; n < phiNode.ninputs(); n++)
430  {
431  const auto variable = Context_->GetVariable(phiNode.input(n)->origin());
432  Context_->InsertVariable(phiNode.input(n)->arguments.first(), variable);
433  }
434 
435  // forward declare all functions and global variables
436  for (size_t n = 0; n < subregion->nresults(); n++)
437  {
438  JLM_ASSERT(subregion->argument(n)->input() == nullptr);
439  const auto & origin = *subregion->result(n)->origin();
440 
441  if (const auto lambdaNode = rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(origin))
442  {
443  const auto & lambdaOperation =
444  dynamic_cast<LlvmLambdaOperation &>(lambdaNode->GetOperation());
445  const auto functionNode = FunctionNode::create(
446  ipGraph,
447  lambdaOperation.name(),
448  lambdaOperation.Type(),
449  lambdaOperation.linkage(),
450  lambdaOperation.attributes());
451  Context_->InsertVariable(subregion->argument(n), ipGraphModule.create_variable(functionNode));
452  }
453  else if (const auto deltaNode = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(origin))
454  {
455  auto op = util::assertedCast<const llvm::DeltaOperation>(&deltaNode->GetOperation());
456  const auto dataNode = DataNode::Create(
457  ipGraph,
458  op->name(),
459  op->Type(),
460  op->linkage(),
461  op->Section(),
462  op->constant());
463  Context_->InsertVariable(subregion->argument(n), ipGraphModule.create_global_value(dataNode));
464  }
465  else
466  {
468  "Unhandled node type: ",
469  rvsdg::AssertGetOwnerNode<rvsdg::Node>(origin).DebugString())
470  .c_str());
471  }
472  }
473 
474  // convert function bodies and global variable initializations
475  for (size_t n = 0; n < subregion->nresults(); n++)
476  {
477  JLM_ASSERT(subregion->argument(n)->input() == nullptr);
478  const auto result = subregion->result(n);
479  const auto & origin = *result->origin();
480 
481  if (const auto lambdaNode = rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(origin))
482  {
483  const auto variable =
484  util::assertedCast<const FunctionVariable>(Context_->GetVariable(subregion->argument(n)));
485  variable->function()->add_cfg(CreateControlFlowGraph(*lambdaNode));
486  Context_->InsertVariable(lambdaNode->output(), variable);
487  }
488  else if (const auto deltaNode = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(origin))
489  {
490  const auto variable =
491  util::assertedCast<const GlobalValue>(Context_->GetVariable(subregion->argument(n)));
492  variable->node()->set_initialization(CreateInitialization(*deltaNode));
493  Context_->InsertVariable(&deltaNode->output(), variable);
494  }
495  else
496  {
498  "Unhandled node type: ",
499  rvsdg::AssertGetOwnerNode<rvsdg::Node>(origin).DebugString())
500  .c_str());
501  }
502  }
503 
504  // add functions and globals to context
505  JLM_ASSERT(phiNode.noutputs() == subregion->nresults());
506  for (size_t n = 0; n < phiNode.noutputs(); n++)
507  Context_->InsertVariable(
508  phiNode.output(n),
509  Context_->GetVariable(subregion->result(n)->origin()));
510 }
511 
512 void
514 {
515  auto & ipGraphModule = Context_->GetIpGraphModule();
516 
517  auto op = util::assertedCast<const llvm::DeltaOperation>(&deltaNode.GetOperation());
518 
519  const auto dataNode = DataNode::Create(
520  ipGraphModule.ipgraph(),
521  op->name(),
522  op->Type(),
523  op->linkage(),
524  op->Section(),
525  op->constant());
526  dataNode->set_initialization(CreateInitialization(deltaNode));
527  const auto variable = ipGraphModule.create_global_value(dataNode);
528  Context_->InsertVariable(&deltaNode.output(), variable);
529 }
530 
531 void
533 {
534  if (const auto lambdaNode = dynamic_cast<const rvsdg::LambdaNode *>(&node))
535  {
536  ConvertLambdaNode(*lambdaNode);
537  }
538  else if (const auto gammaNode = dynamic_cast<const rvsdg::GammaNode *>(&node))
539  {
540  ConvertGammaNode(*gammaNode);
541  }
542  else if (const auto thetaNode = dynamic_cast<const rvsdg::ThetaNode *>(&node))
543  {
544  ConvertThetaNode(*thetaNode);
545  }
546  else if (const auto phiNode = dynamic_cast<const rvsdg::PhiNode *>(&node))
547  {
548  ConvertPhiNode(*phiNode);
549  }
550  else if (const auto deltaNode = dynamic_cast<const rvsdg::DeltaNode *>(&node))
551  {
552  ConvertDeltaNode(*deltaNode);
553  }
554  else if (const auto simpleNode = dynamic_cast<const rvsdg::SimpleNode *>(&node))
555  {
556  ConvertSimpleNode(*simpleNode);
557  }
558  else
559  {
560  JLM_UNREACHABLE(util::strfmt("Unhandled node type: ", node.DebugString()).c_str());
561  }
562 }
563 
564 void
566 {
567  for (const auto & node : rvsdg::TopDownTraverser(&graph.GetRootRegion()))
568  {
569  ConvertNode(*node);
570  }
571 }
572 
573 void
575 {
576  auto & ipGraphModule = Context_->GetIpGraphModule();
577  auto & ipGraph = ipGraphModule.ipgraph();
578 
579  for (size_t n = 0; n < graph.GetRootRegion().narguments(); n++)
580  {
581  const auto graphImport = util::assertedCast<LlvmGraphImport>(graph.GetRootRegion().argument(n));
582  if (const auto functionType =
583  std::dynamic_pointer_cast<const rvsdg::FunctionType>(graphImport->ValueType()))
584  {
585  const auto functionNode =
586  FunctionNode::create(ipGraph, graphImport->Name(), functionType, graphImport->linkage());
587  const auto variable = ipGraphModule.create_variable(functionNode);
588  Context_->InsertVariable(graphImport, variable);
589  }
590  else
591  {
592  const auto dataNode = DataNode::Create(
593  ipGraph,
594  graphImport->Name(),
595  graphImport->ValueType(),
596  graphImport->linkage(),
597  "",
598  false);
599  const auto variable = ipGraphModule.create_global_value(dataNode);
600  Context_->InsertVariable(graphImport, variable);
601  }
602  }
603 }
604 
605 std::unique_ptr<InterProceduralGraphModule>
607  LlvmRvsdgModule & rvsdgModule,
608  util::StatisticsCollector & statisticsCollector)
609 {
610  auto statistics = Statistics::Create(rvsdgModule.SourceFileName());
611  statistics->Start(rvsdgModule.Rvsdg());
612 
613  auto ipGraphModule = InterProceduralGraphModule::create(
614  rvsdgModule.SourceFileName(),
615  rvsdgModule.TargetTriple(),
616  rvsdgModule.DataLayout());
617 
618  Context_ = Context::Create(*ipGraphModule);
619  ConvertImports(rvsdgModule.Rvsdg());
620  ConvertNodes(rvsdgModule.Rvsdg());
621 
622  statistics->End(*ipGraphModule);
623  statisticsCollector.CollectDemandedStatistics(std::move(statistics));
624 
625  return ipGraphModule;
626 }
627 
628 std::unique_ptr<InterProceduralGraphModule>
630  LlvmRvsdgModule & rvsdgModule,
631  util::StatisticsCollector & statisticsCollector)
632 {
633  RvsdgToIpGraphConverter converter;
634  return converter.ConvertModule(rvsdgModule, statisticsCollector);
635 }
636 
637 }
static std::unique_ptr< Argument > create(const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > type, const AttributeSet &attributes)
Definition: cfg.hpp:58
static BasicBlock * create(ControlFlowGraph &cfg)
Definition: basic-block.cpp:37
static std::unique_ptr< llvm::ThreeAddressCode > create(size_t nalternatives, const Variable *operand)
Definition: operators.hpp:418
static std::unique_ptr< ControlFlowGraph > create(InterProceduralGraphModule &im)
Definition: cfg.hpp:266
static DataNode * Create(InterProceduralGraph &clg, const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > valueType, const llvm::Linkage &linkage, std::string section, bool constant)
Definition: ipgraph.hpp:385
static FunctionNode * create(InterProceduralGraph &ipg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage, const AttributeSet &attributes)
Definition: ipgraph.hpp:209
static std::unique_ptr< InterProceduralGraphModule > create(const jlm::util::FilePath &sourceFilename, const std::string &targetTriple, const std::string &dataLayout)
Lambda operation.
Definition: lambda.hpp:30
const util::FilePath & SourceFileName() const noexcept
const std::string & TargetTriple() const noexcept
const std::string & DataLayout() const noexcept
const llvm::Variable * GetVariable(const rvsdg::Output *output)
void InsertVariable(const rvsdg::Output *output, const llvm::Variable *variable)
ControlFlowGraph * GetControlFlowGraph() const noexcept
std::unordered_map< const rvsdg::Output *, const llvm::Variable * > VariableMap_
BasicBlock * GetLastProcessedBasicBlock() const noexcept
Context & operator=(const Context &)=delete
Context & operator=(Context &&)=delete
Context(InterProceduralGraphModule &ipGraphModule)
void SetControlFlowGraph(ControlFlowGraph *cfg) noexcept
InterProceduralGraphModule & GetIpGraphModule() const noexcept
void SetLastProcessedBasicBlock(BasicBlock *lastProcessedBasicBlock) noexcept
static std::unique_ptr< Context > Create(InterProceduralGraphModule &ipGraphModule)
void Start(const rvsdg::Graph &graph) noexcept
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
void End(const InterProceduralGraphModule &im)
std::unique_ptr< DataNodeInit > CreateInitialization(const rvsdg::DeltaNode &deltaNode)
std::unique_ptr< InterProceduralGraphModule > ConvertModule(LlvmRvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector)
static std::unique_ptr< InterProceduralGraphModule > CreateAndConvertModule(LlvmRvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector)
void ConvertDeltaNode(const rvsdg::DeltaNode &deltaNode)
static bool RequiresSsaPhiOperation(const rvsdg::ThetaNode::LoopVar &loopVar, const Variable &v)
void ConvertImports(const rvsdg::Graph &graph)
void ConvertNode(const rvsdg::Node &node)
void ConvertThetaNode(const rvsdg::ThetaNode &thetaNode)
void ConvertNodes(const rvsdg::Graph &graph)
void ConvertLambdaNode(const rvsdg::LambdaNode &lambdaNode)
void ConvertSimpleNode(const rvsdg::SimpleNode &simpleNode)
void ConvertGammaNode(const rvsdg::GammaNode &gammaNode)
void ConvertPhiNode(const rvsdg::PhiNode &phiNode)
std::unique_ptr< ControlFlowGraph > CreateControlFlowGraph(const rvsdg::LambdaNode &lambda)
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< std::pair< const Variable *, ControlFlowGraphNode * >> &arguments, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:74
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
Definition: tac.hpp:135
const std::shared_ptr< const jlm::rvsdg::Type > Type() const noexcept
Definition: variable.hpp:62
Delta node.
Definition: delta.hpp:129
rvsdg::Region * subregion() const noexcept
Definition: delta.hpp:234
const DeltaOperation & GetOperation() const noexcept override
Definition: delta.cpp:71
rvsdg::Output & output() const noexcept
Definition: delta.cpp:110
Conditional operator / pattern matching.
Definition: gamma.hpp:99
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
Definition: gamma.cpp:303
rvsdg::Input * predicate() const noexcept
Definition: gamma.hpp:398
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
Output * origin() const noexcept
Definition: node.hpp:58
Lambda node.
Definition: lambda.hpp:83
std::vector< rvsdg::Output * > GetFunctionArguments() const
Definition: lambda.cpp:57
rvsdg::Region * subregion() const noexcept
Definition: lambda.hpp:138
std::vector< rvsdg::Input * > GetFunctionResults() const
Definition: lambda.cpp:69
rvsdg::Output * output() const noexcept
Definition: lambda.cpp:176
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
Definition: lambda.cpp:119
LambdaOperation & GetOperation() const noexcept override
Definition: lambda.cpp:51
virtual std::string DebugString() const =0
size_t ninputs() const noexcept
Definition: node.hpp:609
size_t noutputs() const noexcept
Definition: node.hpp:644
virtual std::unique_ptr< Operation > copy() const =0
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:366
size_t nusers() const noexcept
Definition: node.hpp:280
A phi node represents the fixpoint of mutually recursive definitions.
Definition: Phi.hpp:46
rvsdg::Region * subregion() const noexcept
Definition: Phi.hpp:320
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
RegionResult * result(size_t index) const noexcept
Definition: region.hpp:471
RegionArgument * argument(size_t index) const noexcept
Definition: region.hpp:437
Graph & Rvsdg() noexcept
Definition: RvsdgModule.hpp:57
const SimpleOperation & GetOperation() const noexcept override
Definition: simple-node.cpp:48
NodeInput * input(size_t index) const noexcept
Definition: simple-node.hpp:82
NodeOutput * output(size_t index) const noexcept
Definition: simple-node.hpp:88
size_t nsubregions() const noexcept
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
Definition: theta.cpp:176
rvsdg::Region * subregion() const noexcept
Definition: theta.hpp:79
ElementType * first() const noexcept
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
Definition: Statistics.hpp:563
Statistics Interface.
Definition: Statistics.hpp:31
util::Timer & GetTimer(const std::string &name)
Definition: Statistics.cpp:134
util::Timer & AddTimer(std::string name)
Definition: Statistics.cpp:155
void AddMeasurement(std::string name, T value)
Definition: Statistics.hpp:174
void start() noexcept
Definition: time.hpp:54
void stop() noexcept
Definition: time.hpp:67
#define JLM_ASSERT(x)
Definition: common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition: common.hpp:43
Global memory state passed between functions.
std::vector< std::unique_ptr< llvm::ThreeAddressCode > > tacsvector_t
Definition: tac.hpp:202
void straighten(ControlFlowGraph &cfg)
size_t ntacs(const AggregationNode &root)
bool is_closed(const ControlFlowGraph &cfg)
static bool ThetaLoopVarIsInvariant(const ThetaNode::LoopVar &loopVar) noexcept
Definition: theta.hpp:227
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
Definition: region.cpp:629
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049
static std::string strfmt(Args... args)
Definition: strfmt.hpp:35
Description of a loop-carried variable.
Definition: theta.hpp:50
rvsdg::Output * pre
Variable before iteration (input argument to subregion).
Definition: theta.hpp:58
static const char * NumRvsdgNodes
Definition: Statistics.hpp:210
static const char * NumThreeAddressCodes
Definition: Statistics.hpp:208
static const char * Timer
Definition: Statistics.hpp:240