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 auto tac = ThreeAddressCode::create(
268 std::unique_ptr<rvsdg::SimpleOperation>(
269 util::assertedCast<rvsdg::SimpleOperation>(operation.release())),
270 operands);
271 tac->setRvsdgNodeLocation(simpleNode);
272 Context_->GetLastProcessedBasicBlock()->append_last(std::move(tac));
273
274 for (size_t n = 0; n < simpleNode.noutputs(); n++)
275 Context_->InsertVariable(
276 simpleNode.output(n),
277 Context_->GetLastProcessedBasicBlock()->last()->result(n));
278}
279
280void
282{
283 const auto numSubregions = gammaNode.nsubregions();
284 const auto predicate = gammaNode.predicate()->origin();
285 const auto controlFlowGraph = Context_->GetControlFlowGraph();
286
287 const auto entryBlock = BasicBlock::create(*controlFlowGraph);
288 const auto exitBlock = BasicBlock::create(*controlFlowGraph);
289 Context_->GetLastProcessedBasicBlock()->add_outedge(entryBlock);
290
291 // convert gamma regions
292 std::vector<ControlFlowGraphNode *> phi_nodes;
293 auto branchTac = BranchOperation::create(numSubregions, Context_->GetVariable(predicate));
294 branchTac->setRvsdgNodeLocation(gammaNode);
295 entryBlock->append_last(std::move(branchTac));
296 auto entryvars = gammaNode.GetEntryVars();
297 for (size_t n = 0; n < gammaNode.nsubregions(); n++)
298 {
299 const auto subregion = gammaNode.subregion(n);
300
301 // add arguments to context
302 for (size_t i = 0; i < entryvars.size(); i++)
303 {
304 auto & entryvar = entryvars[i];
305 Context_->InsertVariable(
306 entryvar.branchArgument[n],
307 Context_->GetVariable(entryvar.input->origin()));
308 }
309
310 // convert subregion
311 const auto regionEntryBlock = BasicBlock::create(*controlFlowGraph);
312 entryBlock->add_outedge(regionEntryBlock);
313 Context_->SetLastProcessedBasicBlock(regionEntryBlock);
314 ConvertRegion(*subregion);
315
316 phi_nodes.push_back(Context_->GetLastProcessedBasicBlock());
317 Context_->GetLastProcessedBasicBlock()->add_outedge(exitBlock);
318 }
319
320 // add phi instructions
321 for (size_t n = 0; n < gammaNode.noutputs(); n++)
322 {
323 const auto output = gammaNode.output(n);
324
325 bool invariant = true;
326 std::vector<std::pair<const Variable *, ControlFlowGraphNode *>> arguments;
327 for (size_t r = 0; r < gammaNode.nsubregions(); r++)
328 {
329 const auto origin = gammaNode.subregion(r)->result(n)->origin();
330
331 auto v = Context_->GetVariable(origin);
332 arguments.push_back(std::make_pair(v, phi_nodes[r]));
333 invariant &= (v == Context_->GetVariable(gammaNode.subregion(0)->result(n)->origin()));
334 }
335
336 if (invariant)
337 {
338 // all operands are the same
339 Context_->InsertVariable(output, arguments[0].first);
340 continue;
341 }
342
343 // create phi instruction
344 auto ssaPhiTac = SsaPhiOperation::create(arguments, output->Type());
345 ssaPhiTac->setRvsdgNodeLocation(gammaNode);
346 exitBlock->append_last(std::move(ssaPhiTac));
347 Context_->InsertVariable(output, exitBlock->last()->result(0));
348 }
349
350 Context_->SetLastProcessedBasicBlock(exitBlock);
351}
352
353bool
355{
356 if (ThetaLoopVarIsInvariant(loopVar))
357 return false;
358
359 if (loopVar.pre->nusers() == 0)
360 return false;
361
362 return true;
363}
364
365void
367{
368 const auto subregion = thetaNode.subregion();
369 const auto predicate = subregion->result(0)->origin();
370
371 auto preEntryBlock = Context_->GetLastProcessedBasicBlock();
372 const auto entryBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
373 preEntryBlock->add_outedge(entryBlock);
374 Context_->SetLastProcessedBasicBlock(entryBlock);
375
376 // create SSA phi nodes in entry block and add arguments to context
377 std::vector<llvm::ThreeAddressCode *> phis;
378 for (const auto & loopVar : thetaNode.GetLoopVars())
379 {
380 auto variable = Context_->GetVariable(loopVar.input->origin());
381 if (RequiresSsaPhiOperation(loopVar))
382 {
383 auto ssaPhiTac = SsaPhiOperation::create({}, loopVar.pre->Type());
384 ssaPhiTac->setRvsdgNodeLocation(thetaNode);
385 auto phi = entryBlock->append_last(std::move(ssaPhiTac));
386 phis.push_back(phi);
387 variable = phi->result(0);
388 }
389 Context_->InsertVariable(loopVar.pre, variable);
390 }
391
392 ConvertRegion(*subregion);
393
394 // add phi operands and results to context
395 size_t phiIndex = 0;
396 for (const auto & loopVar : thetaNode.GetLoopVars())
397 {
398 auto resultVariable = Context_->GetVariable(loopVar.post->origin());
399 Context_->InsertVariable(loopVar.output, resultVariable);
400 if (RequiresSsaPhiOperation(loopVar))
401 {
402 auto entryVariable = Context_->GetVariable(loopVar.input->origin());
403 const auto phi = phis[phiIndex++];
404 phi->replace(
406 { preEntryBlock, Context_->GetLastProcessedBasicBlock() },
407 resultVariable->Type()),
408 { entryVariable, resultVariable });
409 }
410 }
411 JLM_ASSERT(phiIndex == phis.size());
412
413 auto branchTac = BranchOperation::create(2, Context_->GetVariable(predicate));
414 branchTac->setRvsdgNodeLocation(thetaNode);
415 Context_->GetLastProcessedBasicBlock()->append_last(std::move(branchTac));
416 const auto exitBlock = BasicBlock::create(*Context_->GetControlFlowGraph());
417 Context_->GetLastProcessedBasicBlock()->add_outedge(exitBlock);
418 Context_->GetLastProcessedBasicBlock()->add_outedge(entryBlock);
419 Context_->SetLastProcessedBasicBlock(exitBlock);
420}
421
422void
424{
425 auto & ipGraphModule = Context_->GetIpGraphModule();
426 auto & ipGraph = ipGraphModule.ipgraph();
427
428 const auto & operation = *util::assertedCast<LlvmLambdaOperation>(&lambdaNode.GetOperation());
429 const auto functionNode = FunctionNode::create(
430 ipGraph,
431 operation.name(),
432 operation.Type(),
433 operation.linkage(),
434 operation.callingConvention(),
435 operation.attributes());
436 functionNode->add_cfg(CreateControlFlowGraph(lambdaNode));
437
438 for (auto [input, _] : lambdaNode.GetContextVars())
439 {
440 auto & ipGraphNode = getInterProceduralGraphNode(*input->origin());
441 functionNode->add_dependency(&ipGraphNode);
442 }
443
444 const auto variable = ipGraphModule.create_variable(functionNode);
445 Context_->InsertVariable(lambdaNode.output(), variable);
446}
447
448void
450{
451 const auto subregion = phiNode.subregion();
452 auto & ipGraphModule = Context_->GetIpGraphModule();
453 auto & ipGraph = ipGraphModule.ipgraph();
454
455 // add dependencies to context
456 for (size_t n = 0; n < phiNode.ninputs(); n++)
457 {
458 const auto variable = Context_->GetVariable(phiNode.input(n)->origin());
459 Context_->InsertVariable(phiNode.input(n)->arguments.first(), variable);
460 }
461
462 // forward declare all functions and global variables
463 for (size_t n = 0; n < subregion->nresults(); n++)
464 {
465 JLM_ASSERT(subregion->argument(n)->input() == nullptr);
466 const auto & origin = *subregion->result(n)->origin();
467
468 if (const auto lambdaNode = rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(origin))
469 {
470 const auto & lambdaOperation =
471 dynamic_cast<LlvmLambdaOperation &>(lambdaNode->GetOperation());
472 const auto functionNode = FunctionNode::create(
473 ipGraph,
474 lambdaOperation.name(),
475 lambdaOperation.Type(),
476 lambdaOperation.linkage(),
477 lambdaOperation.callingConvention(),
478 lambdaOperation.attributes());
479 Context_->InsertVariable(subregion->argument(n), ipGraphModule.create_variable(functionNode));
480 }
481 else if (const auto deltaNode = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(origin))
482 {
483 auto op = util::assertedCast<const LlvmDeltaOperation>(&deltaNode->GetOperation());
484 const auto dataNode = DataNode::Create(
485 ipGraph,
486 op->name(),
487 op->Type(),
488 op->linkage(),
489 op->Section(),
490 op->constant(),
491 op->getAlignment());
492 Context_->InsertVariable(subregion->argument(n), ipGraphModule.create_global_value(dataNode));
493 }
494 else
495 {
497 "Unhandled node type: ",
498 rvsdg::AssertGetOwnerNode<rvsdg::Node>(origin).DebugString())
499 .c_str());
500 }
501 }
502
503 // convert function bodies and global variable initializations
504 for (size_t n = 0; n < subregion->nresults(); n++)
505 {
506 JLM_ASSERT(subregion->argument(n)->input() == nullptr);
507 const auto result = subregion->result(n);
508 const auto & origin = *result->origin();
509
510 if (const auto lambdaNode = rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(origin))
511 {
512 const auto variable =
513 util::assertedCast<const FunctionVariable>(Context_->GetVariable(subregion->argument(n)));
514 variable->function()->add_cfg(CreateControlFlowGraph(*lambdaNode));
515 Context_->InsertVariable(lambdaNode->output(), variable);
516
517 for (auto [input, _] : lambdaNode->GetContextVars())
518 {
519 auto & ipGraphNode = getInterProceduralGraphNode(*input->origin());
520 variable->function()->add_dependency(&ipGraphNode);
521 }
522 }
523 else if (const auto deltaNode = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(origin))
524 {
525 const auto variable =
526 util::assertedCast<const GlobalValue>(Context_->GetVariable(subregion->argument(n)));
527 variable->node()->set_initialization(CreateInitialization(*deltaNode));
528 Context_->InsertVariable(&deltaNode->output(), variable);
529
530 for (auto & [input, _] : deltaNode->GetContextVars())
531 {
532 auto & ipGraphNode = getInterProceduralGraphNode(*input->origin());
533 variable->node()->add_dependency(&ipGraphNode);
534 }
535 }
536 else
537 {
539 "Unhandled node type: ",
540 rvsdg::AssertGetOwnerNode<rvsdg::Node>(origin).DebugString())
541 .c_str());
542 }
543 }
544
545 // add functions and globals to context
546 JLM_ASSERT(phiNode.noutputs() == subregion->nresults());
547 for (size_t n = 0; n < phiNode.noutputs(); n++)
548 Context_->InsertVariable(
549 phiNode.output(n),
550 Context_->GetVariable(subregion->result(n)->origin()));
551}
552
553void
555{
556 auto & ipGraphModule = Context_->GetIpGraphModule();
557
558 auto op = util::assertedCast<const LlvmDeltaOperation>(&deltaNode.GetOperation());
559
560 const auto dataNode = DataNode::Create(
561 ipGraphModule.ipgraph(),
562 op->name(),
563 op->Type(),
564 op->linkage(),
565 op->Section(),
566 op->constant(),
567 op->getAlignment());
568 dataNode->set_initialization(CreateInitialization(deltaNode));
569
570 for (auto & [input, _] : deltaNode.GetContextVars())
571 {
572 auto & ipGraphNode = getInterProceduralGraphNode(*input->origin());
573 dataNode->add_dependency(&ipGraphNode);
574 }
575
576 const auto variable = ipGraphModule.create_global_value(dataNode);
577 Context_->InsertVariable(&deltaNode.output(), variable);
578}
579
580void
582{
583 if (const auto lambdaNode = dynamic_cast<const rvsdg::LambdaNode *>(&node))
584 {
585 ConvertLambdaNode(*lambdaNode);
586 }
587 else if (const auto gammaNode = dynamic_cast<const rvsdg::GammaNode *>(&node))
588 {
589 ConvertGammaNode(*gammaNode);
590 }
591 else if (const auto thetaNode = dynamic_cast<const rvsdg::ThetaNode *>(&node))
592 {
593 ConvertThetaNode(*thetaNode);
594 }
595 else if (const auto phiNode = dynamic_cast<const rvsdg::PhiNode *>(&node))
596 {
597 ConvertPhiNode(*phiNode);
598 }
599 else if (const auto deltaNode = dynamic_cast<const rvsdg::DeltaNode *>(&node))
600 {
601 ConvertDeltaNode(*deltaNode);
602 }
603 else if (const auto simpleNode = dynamic_cast<const rvsdg::SimpleNode *>(&node))
604 {
605 ConvertSimpleNode(*simpleNode);
606 }
607 else
608 {
609 JLM_UNREACHABLE(util::strfmt("Unhandled node type: ", node.DebugString()).c_str());
610 }
611}
612
613void
615{
616 for (const auto & node : rvsdg::TopDownTraverser(&graph.GetRootRegion()))
617 {
618 ConvertNode(*node);
619 }
620}
621
622void
624{
625 auto & ipGraphModule = Context_->GetIpGraphModule();
626 auto & ipGraph = ipGraphModule.ipgraph();
627
628 for (size_t n = 0; n < graph.GetRootRegion().narguments(); n++)
629 {
630 const auto graphImport = util::assertedCast<LlvmGraphImport>(graph.GetRootRegion().argument(n));
631 if (const auto functionType =
632 std::dynamic_pointer_cast<const rvsdg::FunctionType>(graphImport->ValueType()))
633 {
634 const auto functionNode = FunctionNode::create(
635 ipGraph,
636 graphImport->Name(),
637 functionType,
638 graphImport->linkage(),
639 graphImport->callingConvention(),
640 {});
641 const auto variable = ipGraphModule.create_variable(functionNode);
642 Context_->InsertVariable(graphImport, variable);
643 }
644 else
645 {
646 const auto dataNode = DataNode::Create(
647 ipGraph,
648 graphImport->Name(),
649 graphImport->ValueType(),
650 graphImport->linkage(),
651 "",
652 graphImport->isConstant(),
653 graphImport->getAlignment());
654 const auto variable = ipGraphModule.create_global_value(dataNode);
655 Context_->InsertVariable(graphImport, variable);
656 }
657 }
658}
659
660std::unique_ptr<InterProceduralGraphModule>
662 LlvmRvsdgModule & rvsdgModule,
664{
665 auto statistics = Statistics::Create(rvsdgModule.SourceFileName());
666 statistics->Start(rvsdgModule.Rvsdg());
667
668 // LLVM expects that we do not create any phi instructions for invariant values
669 // through theta and gamma nodes. This leads otherwise to compilation problems (and not just
670 // performance issues). For example, a direct call in a nested loop would all in a sudden be
671 // considered an indirect call as it would take as its function input the phi instruction, but
672 // not the function itself. See the NestedLoopWithCall test in the RvsdgToIpGraphConverterTests
673 // suite. We simply avoid this problem by removing all invariant theta/gamma values from the RVSDG
674 // using invariant value redirection before converting it to a control flow graph.
675 //
676 // FIXME: use designated initializers once we switched to C++20
677 constexpr InvariantValueRedirection::Configuration configuration{
678 true, // enableGammaOutputRedirection
679 false, // enableGammaControlConstantRedirection
680 true, // enableThetaOutputRedirection
681 false, // enableThetaGammaCorrelationRedirection
682 false, // enableCallOutputRedirection
683 false // enableLoadMemoryStateRedirection
684 };
685 InvariantValueRedirection::createAndRun(rvsdgModule, std::move(configuration));
686
687 auto ipGraphModule = InterProceduralGraphModule::create(
688 rvsdgModule.SourceFileName(),
689 rvsdgModule.TargetTriple(),
690 rvsdgModule.DataLayout());
691
692 Context_ = Context::Create(*ipGraphModule);
693 ConvertImports(rvsdgModule.Rvsdg());
694 ConvertNodes(rvsdgModule.Rvsdg());
695
696 statistics->End(*ipGraphModule);
697 statisticsCollector.CollectDemandedStatistics(std::move(statistics));
698
699 return ipGraphModule;
700}
701
702std::unique_ptr<InterProceduralGraphModule>
710
711}
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:155
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:193
rvsdg::Region * subregion() const noexcept
Definition theta.hpp:90
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.
static util::StatisticsCollector statisticsCollector
std::vector< std::unique_ptr< llvm::ThreeAddressCode > > tacsvector_t
Definition tac.hpp:223
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