Jlm
Loading...
Searching...
No Matches
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
16#include <jlm/rvsdg/delta.hpp>
17#include <jlm/rvsdg/gamma.hpp>
18#include <jlm/rvsdg/Phi.hpp>
21#include <jlm/util/time.hpp>
22
23#include <vector>
24
25namespace jlm::llvm
26{
27
29{
30public:
31 explicit Context(InterProceduralGraphModule & ipGraphModule)
32 : ControlFlowGraph_(nullptr),
33 IPGraphModule_(ipGraphModule),
35 {}
36
37 Context(const Context &) = delete;
38
39 Context(Context &&) = delete;
40
41 Context &
42 operator=(const Context &) = delete;
43
44 Context &
45 operator=(Context &&) = delete;
46
47 [[nodiscard]] InterProceduralGraphModule &
48 GetIpGraphModule() const noexcept
49 {
50 return IPGraphModule_;
51 }
52
53 void
54 InsertVariable(const rvsdg::Output * output, const llvm::Variable * variable)
55 {
56 JLM_ASSERT(VariableMap_.find(output) == VariableMap_.end());
57 JLM_ASSERT(*output->Type() == *variable->Type());
58 VariableMap_[output] = variable;
59 }
60
61 const llvm::Variable *
62 GetVariable(const rvsdg::Output * output)
63 {
64 const auto it = VariableMap_.find(output);
65 JLM_ASSERT(it != VariableMap_.end());
66 return it->second;
67 }
68
71 {
73 }
74
75 void
76 SetLastProcessedBasicBlock(BasicBlock * lastProcessedBasicBlock) noexcept
77 {
78 LastProcessedBasicBlock = lastProcessedBasicBlock;
79 }
80
82 GetControlFlowGraph() const noexcept
83 {
84 return ControlFlowGraph_;
85 }
86
87 void
89 {
91 }
92
93 static std::unique_ptr<Context>
95 {
96 return std::make_unique<Context>(ipGraphModule);
97 }
98
99private:
103 std::unordered_map<const rvsdg::Output *, const llvm::Variable *> VariableMap_;
104};
105
107{
108public:
109 ~Statistics() override = default;
110
111 explicit Statistics(const util::FilePath & filename)
112 : util::Statistics(Id::RvsdgDestruction, filename)
113 {}
114
115 void
116 Start(const rvsdg::Graph & graph) noexcept
117 {
118 AddMeasurement(Label::NumRvsdgNodes, rvsdg::nnodes(&graph.GetRootRegion()));
119 AddTimer(Label::Timer).start();
120 }
121
122 void
124 {
125 AddMeasurement(Label::NumThreeAddressCodes, llvm::ntacs(im));
126 GetTimer(Label::Timer).stop();
127 }
128
129 static std::unique_ptr<Statistics>
130 Create(const util::FilePath & sourceFile)
131 {
132 return std::make_unique<Statistics>(sourceFile);
133 }
134};
135
137
139
142{
143 const auto variable = Context_->GetVariable(&output);
144 if (const auto functionVariable = dynamic_cast<const FunctionVariable *>(variable))
145 {
146 return *functionVariable->function();
147 }
148
149 if (const auto globalValue = dynamic_cast<const GlobalValue *>(variable))
150 {
151 return *globalValue->node();
152 }
153
154 throw std::logic_error("Unhandled variable type.");
155}
156
157std::unique_ptr<DataNodeInit>
159{
160 const auto subregion = deltaNode.subregion();
161
162 // add delta dependencies to context
163 for (size_t n = 0; n < deltaNode.ninputs(); n++)
164 {
165 const auto variable = Context_->GetVariable(deltaNode.input(n)->origin());
166 Context_->InsertVariable(deltaNode.input(n)->arguments.first(), variable);
167 }
168
169 if (subregion->numNodes() == 0)
170 {
171 auto value = Context_->GetVariable(subregion->result(0)->origin());
172 return std::make_unique<DataNodeInit>(value);
173 }
174
175 tacsvector_t tacs;
176 for (const auto & node : rvsdg::TopDownTraverser(deltaNode.subregion()))
177 {
178 JLM_ASSERT(node->noutputs() == 1);
179 const auto output = node->output(0);
180
181 // collect operand variables
182 std::vector<const Variable *> operands;
183 for (size_t n = 0; n < node->ninputs(); n++)
184 operands.push_back(Context_->GetVariable(node->input(n)->origin()));
185
186 // convert node to tac
187 auto op = node->GetOperation().copy();
188 tacs.push_back(ThreeAddressCode::create(
189 std::unique_ptr<rvsdg::SimpleOperation>(
190 util::assertedCast<rvsdg::SimpleOperation>(op.release())),
191 operands));
192 Context_->InsertVariable(output, tacs.back()->result(0));
193 }
194
195 return std::make_unique<DataNodeInit>(std::move(tacs));
196}
197
198void
200{
201 const auto entryBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
202 Context_->GetLastProcessedBasicBlock()->add_outedge(entryBlock);
203 Context_->SetLastProcessedBasicBlock(entryBlock);
204
205 for (const auto & node : rvsdg::TopDownTraverser(&region))
206 ConvertNode(*node);
207
208 const auto exitBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
209 Context_->GetLastProcessedBasicBlock()->add_outedge(exitBlock);
210 Context_->SetLastProcessedBasicBlock(exitBlock);
211}
212
213std::unique_ptr<ControlFlowGraph>
215{
216 JLM_ASSERT(Context_->GetLastProcessedBasicBlock() == nullptr);
217 const auto & lambdaOperation = *util::assertedCast<LlvmLambdaOperation>(&lambda.GetOperation());
218
219 auto controlFlowGraph = ControlFlowGraph::create(Context_->GetIpGraphModule());
220 const auto entryBlock = BasicBlock::create(*controlFlowGraph);
221 controlFlowGraph->exit()->divert_inedges(entryBlock);
222 Context_->SetLastProcessedBasicBlock(entryBlock);
223 Context_->SetControlFlowGraph(controlFlowGraph.get());
224
225 // add function arguments
226 for (const auto functionArgument : lambda.GetFunctionArguments())
227 {
228 auto name = util::strfmt("_a", functionArgument->index(), "_");
229 auto argument = Argument::create(
230 name,
231 functionArgument->Type(),
232 lambdaOperation.GetArgumentAttributes(functionArgument->index()));
233 const auto variable = controlFlowGraph->entry()->append_argument(std::move(argument));
234 Context_->InsertVariable(functionArgument, variable);
235 }
236
237 // add context variables
238 for (const auto & [input, inner] : lambda.GetContextVars())
239 {
240 const auto variable = Context_->GetVariable(input->origin());
241 Context_->InsertVariable(inner, variable);
242 }
243
244 ConvertRegion(*lambda.subregion());
245
246 // add results
247 for (const auto result : lambda.GetFunctionResults())
248 controlFlowGraph->exit()->append_result(Context_->GetVariable(result->origin()));
249
250 Context_->GetLastProcessedBasicBlock()->add_outedge(controlFlowGraph->exit());
251 Context_->SetLastProcessedBasicBlock(nullptr);
252 Context_->SetControlFlowGraph(nullptr);
253
254 straighten(*controlFlowGraph);
255 JLM_ASSERT(is_closed(*controlFlowGraph));
256 return controlFlowGraph;
257}
258
259void
261{
262 std::vector<const Variable *> operands;
263 for (size_t n = 0; n < simpleNode.ninputs(); n++)
264 operands.push_back(Context_->GetVariable(simpleNode.input(n)->origin()));
265
266 auto operation = simpleNode.GetOperation().copy();
267 Context_->GetLastProcessedBasicBlock()->append_last(ThreeAddressCode::create(
268 std::unique_ptr<rvsdg::SimpleOperation>(
269 util::assertedCast<rvsdg::SimpleOperation>(operation.release())),
270 operands));
271
272 for (size_t n = 0; n < simpleNode.noutputs(); n++)
273 Context_->InsertVariable(
274 simpleNode.output(n),
275 Context_->GetLastProcessedBasicBlock()->last()->result(n));
276}
277
278void
280{
281 const auto numSubregions = gammaNode.nsubregions();
282 const auto predicate = gammaNode.predicate()->origin();
283 const auto controlFlowGraph = Context_->GetControlFlowGraph();
284
285 const auto entryBlock = BasicBlock::create(*controlFlowGraph);
286 const auto exitBlock = BasicBlock::create(*controlFlowGraph);
287 Context_->GetLastProcessedBasicBlock()->add_outedge(entryBlock);
288
289 // convert gamma regions
290 std::vector<ControlFlowGraphNode *> phi_nodes;
291 entryBlock->append_last(BranchOperation::create(numSubregions, Context_->GetVariable(predicate)));
292 auto entryvars = gammaNode.GetEntryVars();
293 for (size_t n = 0; n < gammaNode.nsubregions(); n++)
294 {
295 const auto subregion = gammaNode.subregion(n);
296
297 // add arguments to context
298 for (size_t i = 0; i < entryvars.size(); i++)
299 {
300 auto & entryvar = entryvars[i];
301 Context_->InsertVariable(
302 entryvar.branchArgument[n],
303 Context_->GetVariable(entryvar.input->origin()));
304 }
305
306 // convert subregion
307 const auto regionEntryBlock = BasicBlock::create(*controlFlowGraph);
308 entryBlock->add_outedge(regionEntryBlock);
309 Context_->SetLastProcessedBasicBlock(regionEntryBlock);
310 ConvertRegion(*subregion);
311
312 phi_nodes.push_back(Context_->GetLastProcessedBasicBlock());
313 Context_->GetLastProcessedBasicBlock()->add_outedge(exitBlock);
314 }
315
316 // add phi instructions
317 for (size_t n = 0; n < gammaNode.noutputs(); n++)
318 {
319 const auto output = gammaNode.output(n);
320
321 bool invariant = true;
322 std::vector<std::pair<const Variable *, ControlFlowGraphNode *>> arguments;
323 for (size_t r = 0; r < gammaNode.nsubregions(); r++)
324 {
325 const auto origin = gammaNode.subregion(r)->result(n)->origin();
326
327 auto v = Context_->GetVariable(origin);
328 arguments.push_back(std::make_pair(v, phi_nodes[r]));
329 invariant &= (v == Context_->GetVariable(gammaNode.subregion(0)->result(n)->origin()));
330 }
331
332 if (invariant)
333 {
334 // all operands are the same
335 Context_->InsertVariable(output, arguments[0].first);
336 continue;
337 }
338
339 // create phi instruction
340 exitBlock->append_last(SsaPhiOperation::create(arguments, output->Type()));
341 Context_->InsertVariable(output, exitBlock->last()->result(0));
342 }
343
344 Context_->SetLastProcessedBasicBlock(exitBlock);
345}
346
347bool
349{
350 if (ThetaLoopVarIsInvariant(loopVar))
351 return false;
352
353 if (loopVar.pre->nusers() == 0)
354 return false;
355
356 return true;
357}
358
359void
361{
362 const auto subregion = thetaNode.subregion();
363 const auto predicate = subregion->result(0)->origin();
364
365 auto preEntryBlock = Context_->GetLastProcessedBasicBlock();
366 const auto entryBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
367 preEntryBlock->add_outedge(entryBlock);
368 Context_->SetLastProcessedBasicBlock(entryBlock);
369
370 // create SSA phi nodes in entry block and add arguments to context
371 std::vector<llvm::ThreeAddressCode *> phis;
372 for (const auto & loopVar : thetaNode.GetLoopVars())
373 {
374 auto variable = Context_->GetVariable(loopVar.input->origin());
375 if (RequiresSsaPhiOperation(loopVar))
376 {
377 auto phi = entryBlock->append_last(SsaPhiOperation::create({}, loopVar.pre->Type()));
378 phis.push_back(phi);
379 variable = phi->result(0);
380 }
381 Context_->InsertVariable(loopVar.pre, variable);
382 }
383
384 ConvertRegion(*subregion);
385
386 // add phi operands and results to context
387 size_t phiIndex = 0;
388 for (const auto & loopVar : thetaNode.GetLoopVars())
389 {
390 auto resultVariable = Context_->GetVariable(loopVar.post->origin());
391 Context_->InsertVariable(loopVar.output, resultVariable);
392 if (RequiresSsaPhiOperation(loopVar))
393 {
394 auto entryVariable = Context_->GetVariable(loopVar.input->origin());
395 const auto phi = phis[phiIndex++];
396 phi->replace(
398 { preEntryBlock, Context_->GetLastProcessedBasicBlock() },
399 resultVariable->Type()),
400 { entryVariable, resultVariable });
401 }
402 }
403 JLM_ASSERT(phiIndex == phis.size());
404
405 Context_->GetLastProcessedBasicBlock()->append_last(
406 BranchOperation::create(2, Context_->GetVariable(predicate)));
407 const auto exitBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
408 Context_->GetLastProcessedBasicBlock()->add_outedge(exitBlock);
409 Context_->GetLastProcessedBasicBlock()->add_outedge(entryBlock);
410 Context_->SetLastProcessedBasicBlock(exitBlock);
411}
412
413void
415{
416 auto & ipGraphModule = Context_->GetIpGraphModule();
417 auto & ipGraph = ipGraphModule.ipgraph();
418
419 const auto & operation = *util::assertedCast<LlvmLambdaOperation>(&lambdaNode.GetOperation());
420 const auto functionNode = FunctionNode::create(
421 ipGraph,
422 operation.name(),
423 operation.Type(),
424 operation.linkage(),
425 operation.callingConvention(),
426 operation.attributes());
427 functionNode->add_cfg(CreateControlFlowGraph(lambdaNode));
428
429 for (auto [input, _] : lambdaNode.GetContextVars())
430 {
431 auto & ipGraphNode = getInterProceduralGraphNode(*input->origin());
432 functionNode->add_dependency(&ipGraphNode);
433 }
434
435 const auto variable = ipGraphModule.create_variable(functionNode);
436 Context_->InsertVariable(lambdaNode.output(), variable);
437}
438
439void
441{
442 const auto subregion = phiNode.subregion();
443 auto & ipGraphModule = Context_->GetIpGraphModule();
444 auto & ipGraph = ipGraphModule.ipgraph();
445
446 // add dependencies to context
447 for (size_t n = 0; n < phiNode.ninputs(); n++)
448 {
449 const auto variable = Context_->GetVariable(phiNode.input(n)->origin());
450 Context_->InsertVariable(phiNode.input(n)->arguments.first(), variable);
451 }
452
453 // forward declare all functions and global variables
454 for (size_t n = 0; n < subregion->nresults(); n++)
455 {
456 JLM_ASSERT(subregion->argument(n)->input() == nullptr);
457 const auto & origin = *subregion->result(n)->origin();
458
459 if (const auto lambdaNode = rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(origin))
460 {
461 const auto & lambdaOperation =
462 dynamic_cast<LlvmLambdaOperation &>(lambdaNode->GetOperation());
463 const auto functionNode = FunctionNode::create(
464 ipGraph,
465 lambdaOperation.name(),
466 lambdaOperation.Type(),
467 lambdaOperation.linkage(),
468 lambdaOperation.callingConvention(),
469 lambdaOperation.attributes());
470 Context_->InsertVariable(subregion->argument(n), ipGraphModule.create_variable(functionNode));
471 }
472 else if (const auto deltaNode = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(origin))
473 {
474 auto op = util::assertedCast<const LlvmDeltaOperation>(&deltaNode->GetOperation());
475 const auto dataNode = DataNode::Create(
476 ipGraph,
477 op->name(),
478 op->Type(),
479 op->linkage(),
480 op->Section(),
481 op->constant(),
482 op->getAlignment());
483 Context_->InsertVariable(subregion->argument(n), ipGraphModule.create_global_value(dataNode));
484 }
485 else
486 {
488 "Unhandled node type: ",
489 rvsdg::AssertGetOwnerNode<rvsdg::Node>(origin).DebugString())
490 .c_str());
491 }
492 }
493
494 // convert function bodies and global variable initializations
495 for (size_t n = 0; n < subregion->nresults(); n++)
496 {
497 JLM_ASSERT(subregion->argument(n)->input() == nullptr);
498 const auto result = subregion->result(n);
499 const auto & origin = *result->origin();
500
501 if (const auto lambdaNode = rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(origin))
502 {
503 const auto variable =
504 util::assertedCast<const FunctionVariable>(Context_->GetVariable(subregion->argument(n)));
505 variable->function()->add_cfg(CreateControlFlowGraph(*lambdaNode));
506 Context_->InsertVariable(lambdaNode->output(), variable);
507
508 for (auto [input, _] : lambdaNode->GetContextVars())
509 {
510 auto & ipGraphNode = getInterProceduralGraphNode(*input->origin());
511 variable->function()->add_dependency(&ipGraphNode);
512 }
513 }
514 else if (const auto deltaNode = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(origin))
515 {
516 const auto variable =
517 util::assertedCast<const GlobalValue>(Context_->GetVariable(subregion->argument(n)));
518 variable->node()->set_initialization(CreateInitialization(*deltaNode));
519 Context_->InsertVariable(&deltaNode->output(), variable);
520
521 for (auto & [input, _] : deltaNode->GetContextVars())
522 {
523 auto & ipGraphNode = getInterProceduralGraphNode(*input->origin());
524 variable->node()->add_dependency(&ipGraphNode);
525 }
526 }
527 else
528 {
530 "Unhandled node type: ",
531 rvsdg::AssertGetOwnerNode<rvsdg::Node>(origin).DebugString())
532 .c_str());
533 }
534 }
535
536 // add functions and globals to context
537 JLM_ASSERT(phiNode.noutputs() == subregion->nresults());
538 for (size_t n = 0; n < phiNode.noutputs(); n++)
539 Context_->InsertVariable(
540 phiNode.output(n),
541 Context_->GetVariable(subregion->result(n)->origin()));
542}
543
544void
546{
547 auto & ipGraphModule = Context_->GetIpGraphModule();
548
549 auto op = util::assertedCast<const LlvmDeltaOperation>(&deltaNode.GetOperation());
550
551 const auto dataNode = DataNode::Create(
552 ipGraphModule.ipgraph(),
553 op->name(),
554 op->Type(),
555 op->linkage(),
556 op->Section(),
557 op->constant(),
558 op->getAlignment());
559 dataNode->set_initialization(CreateInitialization(deltaNode));
560
561 for (auto & [input, _] : deltaNode.GetContextVars())
562 {
563 auto & ipGraphNode = getInterProceduralGraphNode(*input->origin());
564 dataNode->add_dependency(&ipGraphNode);
565 }
566
567 const auto variable = ipGraphModule.create_global_value(dataNode);
568 Context_->InsertVariable(&deltaNode.output(), variable);
569}
570
571void
573{
574 if (const auto lambdaNode = dynamic_cast<const rvsdg::LambdaNode *>(&node))
575 {
576 ConvertLambdaNode(*lambdaNode);
577 }
578 else if (const auto gammaNode = dynamic_cast<const rvsdg::GammaNode *>(&node))
579 {
580 ConvertGammaNode(*gammaNode);
581 }
582 else if (const auto thetaNode = dynamic_cast<const rvsdg::ThetaNode *>(&node))
583 {
584 ConvertThetaNode(*thetaNode);
585 }
586 else if (const auto phiNode = dynamic_cast<const rvsdg::PhiNode *>(&node))
587 {
588 ConvertPhiNode(*phiNode);
589 }
590 else if (const auto deltaNode = dynamic_cast<const rvsdg::DeltaNode *>(&node))
591 {
592 ConvertDeltaNode(*deltaNode);
593 }
594 else if (const auto simpleNode = dynamic_cast<const rvsdg::SimpleNode *>(&node))
595 {
596 ConvertSimpleNode(*simpleNode);
597 }
598 else
599 {
600 JLM_UNREACHABLE(util::strfmt("Unhandled node type: ", node.DebugString()).c_str());
601 }
602}
603
604void
606{
607 for (const auto & node : rvsdg::TopDownTraverser(&graph.GetRootRegion()))
608 {
609 ConvertNode(*node);
610 }
611}
612
613void
615{
616 auto & ipGraphModule = Context_->GetIpGraphModule();
617 auto & ipGraph = ipGraphModule.ipgraph();
618
619 for (size_t n = 0; n < graph.GetRootRegion().narguments(); n++)
620 {
621 const auto graphImport = util::assertedCast<LlvmGraphImport>(graph.GetRootRegion().argument(n));
622 if (const auto functionType =
623 std::dynamic_pointer_cast<const rvsdg::FunctionType>(graphImport->ValueType()))
624 {
625 const auto functionNode = FunctionNode::create(
626 ipGraph,
627 graphImport->Name(),
628 functionType,
629 graphImport->linkage(),
630 graphImport->callingConvention(),
631 {});
632 const auto variable = ipGraphModule.create_variable(functionNode);
633 Context_->InsertVariable(graphImport, variable);
634 }
635 else
636 {
637 const auto dataNode = DataNode::Create(
638 ipGraph,
639 graphImport->Name(),
640 graphImport->ValueType(),
641 graphImport->linkage(),
642 "",
643 graphImport->isConstant(),
644 graphImport->getAlignment());
645 const auto variable = ipGraphModule.create_global_value(dataNode);
646 Context_->InsertVariable(graphImport, variable);
647 }
648 }
649}
650
651std::unique_ptr<InterProceduralGraphModule>
653 LlvmRvsdgModule & rvsdgModule,
655{
656 auto statistics = Statistics::Create(rvsdgModule.SourceFileName());
657 statistics->Start(rvsdgModule.Rvsdg());
658
659 // LLVM expects that we do not create any phi instructions for invariant values
660 // through theta and gamma nodes. This leads otherwise to compilation problems (and not just
661 // performance issues). For example, a direct call in a nested loop would all in a sudden be
662 // considered an indirect call as it would take as its function input the phi instruction, but
663 // not the function itself. See the NestedLoopWithCall test in the RvsdgToIpGraphConverterTests
664 // suite. We simply avoid this problem by removing all invariant theta/gamma values from the RVSDG
665 // using invariant value redirection before converting it to a control flow graph.
666 constexpr InvariantValueRedirection::Configuration configuration{
667 true, // enableGammaOutputRedirection
668 true, // enableThetaOutputRedirection
669 false, // enableThetaGammaCorrelationRedirection
670 false, // enableCallOutputRedirection
671 false // enableLoadMemoryStateRedirection
672 };
673 InvariantValueRedirection::createAndRun(rvsdgModule, std::move(configuration));
674
675 auto ipGraphModule = InterProceduralGraphModule::create(
676 rvsdgModule.SourceFileName(),
677 rvsdgModule.TargetTriple(),
678 rvsdgModule.DataLayout());
679
680 Context_ = Context::Create(*ipGraphModule);
681 ConvertImports(rvsdgModule.Rvsdg());
682 ConvertNodes(rvsdgModule.Rvsdg());
683
684 statistics->End(*ipGraphModule);
685 statisticsCollector.CollectDemandedStatistics(std::move(statistics));
686
687 return ipGraphModule;
688}
689
690std::unique_ptr<InterProceduralGraphModule>
698
699}
static jlm::util::StatisticsCollector statisticsCollector
util::HashSet< rvsdg::Output * > arguments
static std::unique_ptr< Argument > create(const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > type, const AttributeSet &attributes)
Definition cfg.hpp:59
static BasicBlock * create(ControlFlowGraph &cfg)
static std::unique_ptr< llvm::ThreeAddressCode > create(size_t nalternatives, const Variable *operand)
static std::unique_ptr< ControlFlowGraph > create(InterProceduralGraphModule &im)
Definition cfg.hpp:267
static DataNode * Create(InterProceduralGraph &clg, const std::string &name, std::shared_ptr< const jlm::rvsdg::Type > valueType, const llvm::Linkage &linkage, std::string section, const bool constant, const size_t alignment)
Definition ipgraph.hpp:431
static FunctionNode * create(InterProceduralGraph &ipg, const std::string &name, std::shared_ptr< const rvsdg::FunctionType > type, const llvm::Linkage &linkage, const CallingConvention &callingConvention, const AttributeSet &attributes)
Definition ipgraph.hpp:242
static std::unique_ptr< InterProceduralGraphModule > create(const jlm::util::FilePath &sourceFilename, const std::string &targetTriple, const std::string &dataLayout)
static void createAndRun(rvsdg::RvsdgModule &rvsdgModule, Configuration configuration)
const util::FilePath & SourceFileName() const noexcept
const std::string & DataLayout() const noexcept
const std::string & TargetTriple() const noexcept
void InsertVariable(const rvsdg::Output *output, const llvm::Variable *variable)
std::unordered_map< const rvsdg::Output *, const llvm::Variable * > VariableMap_
ControlFlowGraph * GetControlFlowGraph() const noexcept
const llvm::Variable * GetVariable(const rvsdg::Output *output)
Context & operator=(const Context &)=delete
InterProceduralGraphModule & GetIpGraphModule() const noexcept
static std::unique_ptr< Context > Create(InterProceduralGraphModule &ipGraphModule)
Context(InterProceduralGraphModule &ipGraphModule)
Context & operator=(Context &&)=delete
void SetControlFlowGraph(ControlFlowGraph *cfg) noexcept
void SetLastProcessedBasicBlock(BasicBlock *lastProcessedBasicBlock) noexcept
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)
InterProceduralGraphNode & getInterProceduralGraphNode(const rvsdg::Output &output) const
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)
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:77
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
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
Definition delta.cpp:39
const DeltaOperation & GetOperation() const noexcept override
Definition delta.cpp:71
rvsdg::Region * subregion() const noexcept
Definition delta.hpp:234
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:305
rvsdg::Input * predicate() const noexcept
Definition gamma.hpp:487
Region & GetRootRegion() const noexcept
Definition graph.hpp:99
Output * origin() const noexcept
Definition node.hpp:58
std::vector< rvsdg::Output * > GetFunctionArguments() const
Definition lambda.cpp:58
std::vector< rvsdg::Input * > GetFunctionResults() const
Definition lambda.cpp:70
rvsdg::Output * output() const noexcept
Definition lambda.cpp:177
rvsdg::Region * subregion() const noexcept
Definition lambda.hpp:138
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
Definition lambda.cpp:120
LambdaOperation & GetOperation() const noexcept override
Definition lambda.cpp:52
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
RegionArgument * argument(size_t index) const noexcept
Definition region.hpp:466
RegionResult * result(size_t index) const noexcept
Definition region.hpp:500
Graph & Rvsdg() noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
size_t nsubregions() const noexcept
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(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)
Statistics Interface.
util::Timer & GetTimer(const std::string &name)
util::Timer & AddTimer(std::string name)
void AddMeasurement(std::string name, T value)
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)
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
Definition region.cpp:808
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872
detail::TopDownTraverserGeneric< false > TopDownTraverser
Traverser for visiting every node in a region in a top down order.
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