Jlm
Loading...
Searching...
No Matches
JlmToMlirConverter.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2024 Louis Maurin <louis7maurin@gmail.com>
3 * Copyright 2023 Magnus Sjalander <work@sjalander.com>
4 * See COPYING for terms of redistribution.
5 */
6
22#include <jlm/rvsdg/node.hpp>
25
26#include <llvm/Support/raw_os_ostream.h>
27
28#include <mlir/Dialect/Arith/IR/Arith.h>
29#include <mlir/IR/Builders.h>
30#include <mlir/IR/Verifier.h>
31
32#include <unordered_map>
33
34namespace jlm::mlir
35{
36
37void
38JlmToMlirConverter::Print(::mlir::rvsdg::OmegaNode & omega, const util::FilePath & filePath)
39{
40 if (failed(::mlir::verify(omega)))
41 {
42 omega.emitError("module verification error");
43 throw util::Error("Verification of RVSDG-MLIR failed");
44 }
45 if (filePath == "")
46 {
47 ::llvm::raw_os_ostream os(std::cout);
48 omega.print(os);
49 }
50 else
51 {
52 std::error_code ec;
53 ::llvm::raw_fd_ostream os(filePath.to_str(), ec);
54 omega.print(os);
55 }
56}
57
58::mlir::rvsdg::OmegaNode
60{
61 auto & graph = rvsdgModule.Rvsdg();
62
63 auto omega = Builder_->create<::mlir::rvsdg::OmegaNode>(Builder_->getUnknownLoc());
64 auto & omegaBlock = omega.getRegion().emplaceBlock();
65
66 ::llvm::SmallVector<::mlir::Value> regionResults =
67 ConvertRegion(graph.GetRootRegion(), omegaBlock, true);
68
69 // Build result types from the region results
70 ::llvm::SmallVector<::mlir::Type> resultTypes;
71 for (auto & result : regionResults)
72 {
73 resultTypes.push_back(result.getType());
74 }
75
76 // Collect export names from root region results.
77 // The order of graph.GetRootRegion().results() matches regionResults.
78 ::llvm::SmallVector<::mlir::Attribute> exportNames;
79 for (auto & result : graph.GetRootRegion().Results())
80 {
81 if (auto graphExport = dynamic_cast<const rvsdg::GraphExport *>(result))
82 {
83 exportNames.push_back(Builder_->getStringAttr(graphExport->Name()));
84 }
85 else
86 {
87 JLM_UNREACHABLE("This should not happen. All omega results should be a GraphExport");
88 }
89 }
90
91 // Create OmegaResult with proper signature including export names.
92 auto exportNamesAttr = ::mlir::ArrayAttr::get(Builder_->getContext(), exportNames);
93 ::llvm::SmallVector<::mlir::NamedAttribute> namedAttrs;
94 namedAttrs.push_back({ Builder_->getStringAttr("exportNames"), exportNamesAttr });
95
96 auto omegaResult = Builder_->create<::mlir::rvsdg::OmegaResult>(
97 Builder_->getUnknownLoc(),
98 resultTypes,
99 regionResults,
100 namedAttrs);
101 omegaBlock.push_back(omegaResult);
102
103 return omega;
104}
105
106::llvm::SmallVector<::mlir::Value>
107JlmToMlirConverter::ConvertRegion(rvsdg::Region & region, ::mlir::Block & block, bool isRoot)
108{
109 std::unordered_map<rvsdg::Output *, ::mlir::Value> valueMap;
110 size_t argIndex = 0;
111 for (size_t i = 0; i < region.narguments(); ++i)
112 {
113 auto arg = region.argument(i);
114 if (isRoot) // Omega arguments are treated separately
115 {
116 auto imp = util::assertedCast<llvm::LlvmGraphImport>(arg);
117 block.push_back(Builder_->create<::mlir::rvsdg::OmegaArgument>(
118 Builder_->getUnknownLoc(),
119 ConvertType(*imp->ImportedType()),
120 ConvertType(*imp->ValueType()),
121 Builder_->getStringAttr(llvm::linkageToString(imp->linkage())),
122 Builder_->getStringAttr(imp->Name())));
123 valueMap[arg] = block.back().getResult(0); // Add the output of the omega argument
124 }
125 else
126 {
127 block.addArgument(ConvertType(*arg->Type()), Builder_->getUnknownLoc());
128 valueMap[arg] = block.getArgument(argIndex);
129 ++argIndex;
130 }
131 }
132
133 // Create an MLIR operation for each RVSDG node.
134 // The mapping from RVSDG output to MLIR result is added to the valueMap for quick lookup.
135 for (rvsdg::Node * rvsdgNode : rvsdg::TopDownTraverser(&region))
136 {
137 ::llvm::SmallVector<::mlir::Value> inputs = GetConvertedInputs(*rvsdgNode, valueMap);
138
139 auto convertedNode = ConvertNode(*rvsdgNode, block, inputs);
140 for (size_t i = 0; i < rvsdgNode->noutputs(); i++)
141 {
142 valueMap[rvsdgNode->output(i)] = convertedNode->getResult(i);
143 }
144 }
145
146 // This code is used to get the results of the region
148 ::llvm::SmallVector<::mlir::Value> results;
149 for (size_t i = 0; i < region.nresults(); i++)
150 {
151 auto it = valueMap.find(region.result(i)->origin());
152 if (it != valueMap.end())
153 {
154 results.push_back(it->second);
155 }
156 else
157 {
158 auto message = util::strfmt(
159 "Unimplemented input type: ",
160 region.result(i)->origin()->debug_string(),
161 ": ",
162 region.result(i)->origin()->Type()->debug_string(),
163 " for region result: ",
164 region.result(i)->debug_string(),
165 " at index: ",
166 i);
167 JLM_UNREACHABLE(message.c_str());
168 }
169 }
170
171 return results;
172}
173
174::llvm::SmallVector<::mlir::Value>
176 const rvsdg::Node & node,
177 const std::unordered_map<rvsdg::Output *, ::mlir::Value> & valueMap)
178{
179 ::llvm::SmallVector<::mlir::Value> inputs;
180 for (size_t i = 0; i < node.ninputs(); i++)
181 {
182 auto it = valueMap.find(node.input(i)->origin());
183 if (it != valueMap.end())
184 {
185 inputs.push_back(it->second);
186 }
187 else
188 {
189 auto message = util::strfmt(
190 "Unimplemented input type: ",
191 node.input(i)->origin()->debug_string(),
192 ": ",
193 node.input(i)->origin()->Type()->debug_string(),
194 " for node: ",
195 node.DebugString(),
196 " at index: ",
197 i);
198 JLM_UNREACHABLE(message.c_str());
199 }
200 }
201 return inputs;
202}
203
204::mlir::Operation *
206 const rvsdg::Node & node,
207 ::mlir::Block & block,
208 const ::llvm::SmallVector<::mlir::Value> & inputs)
209{
210 if (auto simpleNode = dynamic_cast<const rvsdg::SimpleNode *>(&node))
211 {
212 return ConvertSimpleNode(*simpleNode, block, inputs);
213 }
214 else if (auto lambda = dynamic_cast<const rvsdg::LambdaNode *>(&node))
215 {
216 return ConvertLambda(*lambda, block, inputs);
217 }
218 else if (auto gamma = dynamic_cast<const rvsdg::GammaNode *>(&node))
219 {
220 return ConvertGamma(*gamma, block, inputs);
221 }
222 else if (auto theta = dynamic_cast<const rvsdg::ThetaNode *>(&node))
223 {
224 return ConvertTheta(*theta, block, inputs);
225 }
226 else if (auto delta = dynamic_cast<const rvsdg::DeltaNode *>(&node))
227 {
228 return ConvertDelta(*delta, block, inputs);
229 }
230 else
231 {
232 auto message = util::strfmt("Unimplemented structural node: ", node.DebugString());
233 JLM_UNREACHABLE(message.c_str());
234 }
235}
236
237::mlir::Operation *
240 ::llvm::SmallVector<::mlir::Value> inputs)
241{
242 switch (op.fpop())
243 {
245 return Builder_->create<::mlir::arith::AddFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
247 return Builder_->create<::mlir::arith::SubFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
249 return Builder_->create<::mlir::arith::MulFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
251 return Builder_->create<::mlir::arith::DivFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
253 return Builder_->create<::mlir::arith::RemFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
254 default:
255 JLM_UNREACHABLE("Unknown binary bitop");
256 }
257}
258
259::mlir::Operation *
261 const llvm::FCmpOperation & op,
262 ::llvm::SmallVector<::mlir::Value> inputs)
263{
264 const auto & map = GetFpCmpPredicateMap();
265 auto predicate = map.LookupValue(op.cmp());
266 return Builder_->create<::mlir::arith::CmpFOp>(
267 Builder_->getUnknownLoc(),
268 Builder_->getAttr<::mlir::arith::CmpFPredicateAttr>(predicate),
269 inputs[0],
270 inputs[1]);
271}
272
273::mlir::Operation *
275 const rvsdg::SimpleOperation & bitOp,
276 ::llvm::SmallVector<::mlir::Value> inputs)
277{
278 ::mlir::Operation * MlirOp = nullptr;
280 {
281 MlirOp =
282 Builder_->create<::mlir::arith::AddIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
283 }
285 {
286 MlirOp =
287 Builder_->create<::mlir::arith::AndIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
288 }
290 {
291 MlirOp =
292 Builder_->create<::mlir::arith::ShRUIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
293 }
295 {
296 MlirOp =
297 Builder_->create<::mlir::arith::MulIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
298 }
300 {
301 MlirOp =
302 Builder_->create<::mlir::arith::OrIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
303 }
305 {
306 MlirOp =
307 Builder_->create<::mlir::arith::DivSIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
308 }
310 {
311 MlirOp =
312 Builder_->create<::mlir::arith::ShLIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
313 }
315 {
316 MlirOp =
317 Builder_->create<::mlir::arith::ShRUIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
318 }
320 {
321 MlirOp =
322 Builder_->create<::mlir::arith::RemSIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
323 }
325 {
326 JLM_UNREACHABLE("Binary bit bitOp smulh not supported");
327 }
329 {
330 MlirOp =
331 Builder_->create<::mlir::arith::SubIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
332 }
334 {
335 MlirOp =
336 Builder_->create<::mlir::arith::DivUIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
337 }
339 {
340 MlirOp =
341 Builder_->create<::mlir::arith::RemUIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
342 }
344 {
345 JLM_UNREACHABLE("Binary bit bitOp umulh not supported");
346 }
348 {
349 MlirOp =
350 Builder_->create<::mlir::arith::XOrIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
351 }
352 else
353 {
354 JLM_UNREACHABLE("Unknown binary bitop");
355 }
356
357 return MlirOp;
358}
359
360::mlir::Operation *
362 const rvsdg::SimpleOperation & bitOp,
363 ::llvm::SmallVector<::mlir::Value> inputs)
364{
365 auto compPredicate = ::mlir::arith::CmpIPredicate::eq;
367 compPredicate = ::mlir::arith::CmpIPredicate::eq;
369 compPredicate = ::mlir::arith::CmpIPredicate::ne;
371 compPredicate = ::mlir::arith::CmpIPredicate::sge;
373 compPredicate = ::mlir::arith::CmpIPredicate::sgt;
375 compPredicate = ::mlir::arith::CmpIPredicate::sle;
377 compPredicate = ::mlir::arith::CmpIPredicate::slt;
379 compPredicate = ::mlir::arith::CmpIPredicate::uge;
381 compPredicate = ::mlir::arith::CmpIPredicate::ugt;
383 compPredicate = ::mlir::arith::CmpIPredicate::ule;
385 compPredicate = ::mlir::arith::CmpIPredicate::ult;
386 else
387 {
388 auto message = util::strfmt("Unknown compare operation: ", bitOp.debug_string());
389 JLM_UNREACHABLE(message.c_str());
390 }
391
392 auto MlirOp = Builder_->create<::mlir::arith::CmpIOp>(
393 Builder_->getUnknownLoc(),
394 compPredicate,
395 inputs[0],
396 inputs[1]);
397 return MlirOp;
398}
399
400::mlir::Operation *
402 const llvm::PtrCmpOperation & operation,
403 ::llvm::SmallVector<::mlir::Value> inputs)
404{
405 static std::unordered_map<llvm::ICmpPredicate, ::mlir::LLVM::ICmpPredicate> map = {
406 { llvm::ICmpPredicate::Eq, ::mlir::LLVM::ICmpPredicate::eq },
407 { llvm::ICmpPredicate::Ne, ::mlir::LLVM::ICmpPredicate::ne },
408 { llvm::ICmpPredicate::Ugt, ::mlir::LLVM::ICmpPredicate::ugt },
409 { llvm::ICmpPredicate::Uge, ::mlir::LLVM::ICmpPredicate::uge },
410 { llvm::ICmpPredicate::Ult, ::mlir::LLVM::ICmpPredicate::ult },
411 { llvm::ICmpPredicate::Ule, ::mlir::LLVM::ICmpPredicate::ule },
412 { llvm::ICmpPredicate::Sgt, ::mlir::LLVM::ICmpPredicate::sgt },
413 { llvm::ICmpPredicate::Sge, ::mlir::LLVM::ICmpPredicate::sge },
414 { llvm::ICmpPredicate::Slt, ::mlir::LLVM::ICmpPredicate::slt },
415 { llvm::ICmpPredicate::Sle, ::mlir::LLVM::ICmpPredicate::sle },
416 };
417
418 const auto mlirPredicate = map.at(operation.predicate());
419 auto MlirOp = Builder_->create<::mlir::LLVM::ICmpOp>(
420 Builder_->getUnknownLoc(),
421 mlirPredicate,
422 inputs[0],
423 inputs[1]);
424 return MlirOp;
425}
426
434static ::mlir::ArrayAttr
436 ::mlir::MLIRContext * context,
437 const std::vector<llvm::MemoryNodeId> & memoryNodeIndices)
438{
439 auto int64Type = ::mlir::IntegerType::get(context, 64);
440 ::llvm::SmallVector<::mlir::Attribute> intAttributes;
441 for (auto memoryNodeId : memoryNodeIndices)
442 {
443 intAttributes.push_back(::mlir::IntegerAttr::get(int64Type, memoryNodeId));
444 }
445 return ::mlir::ArrayAttr::get(context, intAttributes);
446}
447
448::mlir::Operation *
450 const rvsdg::SimpleNode & node,
451 ::mlir::Block & block,
452 const ::llvm::SmallVector<::mlir::Value> & inputs)
453{
454 ::mlir::Operation * MlirOp = nullptr;
455 auto & operation = node.GetOperation();
456 if (auto bitOp = dynamic_cast<const rvsdg::BitConstantOperation *>(&operation))
457 {
458 auto value = bitOp->value();
459 MlirOp = Builder_->create<::mlir::arith::ConstantIntOp>(
460 Builder_->getUnknownLoc(),
461 value.to_uint(),
462 value.nbits());
463 }
464 else if (
465 auto integerConstOp = dynamic_cast<const jlm::llvm::IntegerConstantOperation *>(&operation))
466 {
467 auto isNegative = integerConstOp->Representation().is_negative();
468 auto value = isNegative ? integerConstOp->Representation().to_int()
469 : integerConstOp->Representation().to_uint();
470 MlirOp = Builder_->create<::mlir::arith::ConstantIntOp>(
471 Builder_->getUnknownLoc(),
472 value,
473 integerConstOp->Representation().nbits());
474 }
475 else if (auto fpBinOp = dynamic_cast<const jlm::llvm::FBinaryOperation *>(&operation))
476 {
477 MlirOp = ConvertFpBinaryNode(*fpBinOp, inputs);
478 }
480 {
481 MlirOp = Builder_->create<::mlir::LLVM::FMulAddOp>(
482 Builder_->getUnknownLoc(),
483 inputs[0],
484 inputs[1],
485 inputs[2]);
486 }
488 {
490 *dynamic_cast<const jlm::llvm::IntegerBinaryOperation *>(&operation),
491 inputs);
492 }
493 else if (auto fpOp = dynamic_cast<const llvm::ConstantFP *>(&operation))
494 {
495 auto size = ConvertFPType(fpOp->size());
496 auto value = fpOp->constant();
497 MlirOp =
498 Builder_->create<::mlir::arith::ConstantFloatOp>(Builder_->getUnknownLoc(), value, size);
499 }
500 else if (auto zeroOp = dynamic_cast<const llvm::ConstantAggregateZeroOperation *>(&operation))
501 {
502 auto type = ConvertType(*zeroOp->result(0));
503 MlirOp = Builder_->create<::mlir::LLVM::ZeroOp>(Builder_->getUnknownLoc(), type);
504 }
505 else if (auto arrOp = dynamic_cast<const llvm::ConstantDataArrayOperation *>(&operation))
506 {
507 auto arrayType = ConvertType(*arrOp->result(0));
508 MlirOp = Builder_->create<::mlir::jlm::ConstantDataArray>(
509 Builder_->getUnknownLoc(),
510 arrayType,
511 inputs);
512 }
513 else if (auto zeroOp = dynamic_cast<const llvm::ConstantAggregateZeroOperation *>(&operation))
514 {
515 auto type = ConvertType(*zeroOp->result(0));
516 MlirOp = Builder_->create<::mlir::LLVM::ZeroOp>(Builder_->getUnknownLoc(), type);
517 }
518 else if (
519 auto constantPointerNullOp =
520 dynamic_cast<const llvm::ConstantPointerNullOperation *>(&operation))
521 {
522 // NULL pointers are a special case of ZeroOp
523 auto type = ConvertType(*constantPointerNullOp->result(0));
524 MlirOp = Builder_->create<::mlir::LLVM::ZeroOp>(Builder_->getUnknownLoc(), type);
525 }
527 {
528 MlirOp = ConvertBitBinaryNode(operation, inputs);
529 }
530 else if (auto fpBinOp = dynamic_cast<const jlm::llvm::FBinaryOperation *>(&operation))
531 {
532 MlirOp = ConvertFpBinaryNode(*fpBinOp, inputs);
533 }
535 {
536 MlirOp = Builder_->create<::mlir::arith::NegFOp>(Builder_->getUnknownLoc(), inputs[0]);
537 }
538 else if (auto fpextOp = dynamic_cast<const jlm::llvm::FPExtOperation *>(&operation))
539 {
540 MlirOp = Builder_->create<::mlir::arith::ExtFOp>(
541 Builder_->getUnknownLoc(),
542 ConvertType(*fpextOp->result(0)),
543 inputs[0]);
544 }
545
547 {
548 MlirOp = BitCompareNode(operation, inputs);
549 }
550 else if (auto fpCmpOp = dynamic_cast<const llvm::FCmpOperation *>(&operation))
551 {
552 MlirOp = ConvertFpCompareNode(*fpCmpOp, inputs);
553 }
554 else if (auto pointerCompareOp = dynamic_cast<const llvm::PtrCmpOperation *>(&operation))
555 {
556 MlirOp = ConvertPointerCompareNode(*pointerCompareOp, inputs);
557 }
558 else if (const auto zextOperation = dynamic_cast<const llvm::ZExtOperation *>(&operation))
559 {
560 MlirOp = Builder_->create<::mlir::arith::ExtUIOp>(
561 Builder_->getUnknownLoc(),
562 Builder_->getIntegerType(zextOperation->ndstbits()),
563 inputs[0]);
564 }
565 else if (auto sextOp = dynamic_cast<const jlm::llvm::SExtOperation *>(&operation))
566 {
567 MlirOp = Builder_->create<::mlir::arith::ExtSIOp>(
568 Builder_->getUnknownLoc(),
569 Builder_->getIntegerType(sextOp->ndstbits()),
570 inputs[0]);
571 }
572 else if (auto sitofpOp = dynamic_cast<const llvm::SIToFPOperation *>(&operation))
573 {
574 MlirOp = Builder_->create<::mlir::arith::SIToFPOp>(
575 Builder_->getUnknownLoc(),
576 ConvertType(*sitofpOp->result(0)),
577 inputs[0]);
578 }
579 else if (auto truncOp = dynamic_cast<const jlm::llvm::TruncOperation *>(&operation))
580 {
581 MlirOp = Builder_->create<::mlir::arith::TruncIOp>(
582 Builder_->getUnknownLoc(),
583 ConvertType(*truncOp->result(0)),
584 inputs[0]);
585 }
586 else if (auto intToPtrOp = dynamic_cast<const llvm::IntToPtrOperation *>(&operation))
587 {
588 MlirOp = Builder_->create<::mlir::LLVM::IntToPtrOp>(
589 Builder_->getUnknownLoc(),
590 ConvertType(*intToPtrOp->result(0)),
591 inputs[0]);
592 }
593 else if (auto bitCastOp = dynamic_cast<const jlm::llvm::BitCastOperation *>(&operation))
594 {
595 auto srcType = bitCastOp->argument(0);
596 auto dstType = bitCastOp->result(0);
597
598 // BitCast on pointer types maps to LLVM::BitcastOp
600 {
601 MlirOp = Builder_->create<::mlir::LLVM::BitcastOp>(
602 Builder_->getUnknownLoc(),
603 ConvertType(*bitCastOp->result(0)),
604 inputs[0]);
605 }
606 // BitCast on integer types maps to arith::ExtUIOp or arith::TruncIOp depending on size
607 else if (auto srcBitType = dynamic_cast<const rvsdg::BitType *>(srcType.get()))
608 {
609 if (auto dstBitType = dynamic_cast<const rvsdg::BitType *>(dstType.get()))
610 {
611 auto srcBits = srcBitType->nbits();
612 auto dstBits = dstBitType->nbits();
613
614 if (dstBits > srcBits)
615 {
616 MlirOp = Builder_->create<::mlir::arith::ExtUIOp>(
617 Builder_->getUnknownLoc(),
618 ConvertType(*bitCastOp->result(0)),
619 inputs[0]);
620 }
621 else if (dstBits < srcBits)
622 {
623 MlirOp = Builder_->create<::mlir::arith::TruncIOp>(
624 Builder_->getUnknownLoc(),
625 ConvertType(*bitCastOp->result(0)),
626 inputs[0]);
627 }
628 else
629 {
630 // Same bit width - just pass through
631 MlirOp = Builder_->create<::mlir::LLVM::BitcastOp>(
632 Builder_->getUnknownLoc(),
633 ConvertType(*bitCastOp->result(0)),
634 inputs[0]);
635 }
636 }
637 }
638 else
639 {
640 auto message =
641 util::strfmt("Unsupported bitcast type combination: ", bitCastOp->debug_string());
642 JLM_UNREACHABLE(message.c_str());
643 }
644 }
645 else if (dynamic_cast<const jlm::llvm::FunctionToPointerOperation *>(&operation))
646 {
647 MlirOp = Builder_->create<::mlir::jlm::FuncToPtr>(
648 Builder_->getUnknownLoc(),
649 Builder_->getType<::mlir::LLVM::LLVMPointerType>(),
650 inputs[0]);
651 }
652 else if (auto ptrToFnOp = dynamic_cast<const jlm::llvm::PointerToFunctionOperation *>(&operation))
653 {
654 MlirOp = Builder_->create<::mlir::jlm::PtrToFunc>(
655 Builder_->getUnknownLoc(),
656 ConvertType(*ptrToFnOp->result(0)),
657 inputs[0]);
658 }
659 // ** region structural nodes **
660 else if (auto ctlOp = dynamic_cast<const rvsdg::ControlConstantOperation *>(&operation))
661 {
662 MlirOp = Builder_->create<::mlir::rvsdg::ConstantCtrl>(
663 Builder_->getUnknownLoc(),
664 ConvertType(*node.output(0)->Type()), // Control, ouput type
665 ctlOp->value().alternative());
666 }
667 else if (auto vaOp = dynamic_cast<const llvm::VariadicArgumentListOperation *>(&operation))
668 {
669 MlirOp = Builder_->create<::mlir::jlm::CreateVarArgList>(
670 Builder_->getUnknownLoc(),
671 ConvertType(*vaOp->result(0)),
672 inputs);
673 }
674 else if (auto undefOp = dynamic_cast<const llvm::UndefValueOperation *>(&operation))
675 {
676 MlirOp = Builder_->create<::mlir::jlm::Undef>(
677 Builder_->getUnknownLoc(),
678 ConvertType(undefOp->GetType()));
679 }
680 else if (auto freeOp = dynamic_cast<const jlm::llvm::FreeOperation *>(&operation))
681 {
682 auto nMemstates = freeOp->narguments() - 2; // Subtract for pointer and io state
683
684 std::vector<::mlir::Type> memoryStates(
685 nMemstates,
686 Builder_->getType<::mlir::rvsdg::MemStateEdgeType>());
687 MlirOp = Builder_->create<::mlir::jlm::Free>(
688 Builder_->getUnknownLoc(),
689 Builder_->getType<::mlir::rvsdg::IOStateEdgeType>(),
690 ::mlir::TypeRange(::llvm::ArrayRef(memoryStates)),
691 inputs[0],
692 inputs[1],
693 ::mlir::ValueRange({ std::next(inputs.begin(), 2), inputs.end() }));
694 }
695 else if (auto alloca_op = dynamic_cast<const jlm::llvm::AllocaOperation *>(&operation))
696 {
697 MlirOp = Builder_->create<::mlir::jlm::Alloca>(
698 Builder_->getUnknownLoc(),
699 ConvertType(*alloca_op->result(0)), // ptr
700 ConvertType(*alloca_op->result(1)), // memstate
701 ConvertType(*alloca_op->allocatedType()), // value type
702 inputs[0], // size
703 alloca_op->alignment(), // alignment
704 ::mlir::ValueRange({ std::next(inputs.begin()), inputs.end() })); // inputMemStates
705 }
706 else if (auto malloc_op = dynamic_cast<const jlm::llvm::MallocOperation *>(&operation))
707 {
708 MlirOp = Builder_->create<::mlir::jlm::Malloc>(
709 Builder_->getUnknownLoc(),
710 ConvertType(*malloc_op->result(0)), // ptr
711 ConvertType(*malloc_op->result(1)), // IOState
712 ConvertType(*malloc_op->result(2)), // memstate
713 inputs[0], // size
714 inputs[1] // IOState
715 );
716 }
717 else if (auto load_op = dynamic_cast<const jlm::llvm::LoadOperation *>(&operation))
718 {
719 const bool isVolatile = rvsdg::is<jlm::llvm::LoadVolatileOperation>(operation);
720
721 // A volatile load threads an I/O state in and out; a non-volatile one does not.
722 ::mlir::Value inputIoState = isVolatile ? inputs[1] : nullptr;
723 ::mlir::Type outputIoState =
724 isVolatile ? Builder_->getType<::mlir::rvsdg::IOStateEdgeType>() : nullptr;
725
726 MlirOp = Builder_->create<::mlir::jlm::Load>(
727 Builder_->getUnknownLoc(),
728 ConvertType(*load_op->result(0)), // loaded value
729 outputIoState, // output I/O state
730 GetMemStateRange(load_op->NumMemoryStates()), // output memory states
731 inputs[0], // pointer
732 Builder_->getUI32IntegerAttr(load_op->GetAlignment()), // alignment
733 Builder_->getBoolAttr(isVolatile), // isVolatile
734 inputIoState,
735 ::mlir::ValueRange(
736 { std::next(inputs.begin(), isVolatile ? 2 : 1), inputs.end() })); // inputMemStates
737 }
738 else if (auto store_op = dynamic_cast<const jlm::llvm::StoreOperation *>(&operation))
739 {
740 const bool isVolatile = rvsdg::is<jlm::llvm::StoreVolatileOperation>(operation);
741
742 // A volatile store threads an I/O state in and out; a non-volatile one does not.
743 ::mlir::Value inputIoState = isVolatile ? inputs[2] : nullptr;
744 ::mlir::Type outputIoState =
745 isVolatile ? Builder_->getType<::mlir::rvsdg::IOStateEdgeType>() : nullptr;
746
747 MlirOp = Builder_->create<::mlir::jlm::Store>(
748 Builder_->getUnknownLoc(),
749 outputIoState,
750 GetMemStateRange(store_op->NumMemoryStates()), // output memory states
751 inputs[0], // pointer
752 inputs[1], // value
753 Builder_->getUI32IntegerAttr(store_op->GetAlignment()), // alignment
754 Builder_->getBoolAttr(isVolatile), // isVolatile
755 inputIoState,
756 ::mlir::ValueRange(
757 { std::next(inputs.begin(), isVolatile ? 3 : 2), inputs.end() })); // inputMemStates
758 }
760 {
761 MlirOp = Builder_->create<::mlir::rvsdg::MemStateMerge>(
762 Builder_->getUnknownLoc(),
763 ConvertType(*node.output(0)->Type()),
764 inputs);
765 }
767 {
768 MlirOp = Builder_->create<::mlir::jlm::IOBarrier>(
769 Builder_->getUnknownLoc(),
770 ConvertType(*node.output(0)->Type()),
771 inputs[0],
772 inputs[1]);
773 }
774 else if (
775 auto hoistBarrierOp = dynamic_cast<const llvm::MemoryHoistBarrierOperation *>(&operation))
776 {
777 MlirOp = Builder_->create<::mlir::jlm::MemoryHoistBarrier>(
778 Builder_->getUnknownLoc(),
779 Builder_->getType<::mlir::LLVM::LLVMPointerType>(),
780 inputs[0], // address
781 inputs[1], // ioState
782 hoistBarrierOp->getDereferenceableSize());
783 }
784 else if (auto op = dynamic_cast<const llvm::GetElementPtrOperation *>(&operation))
785 {
786 MlirOp = Builder_->create<::mlir::LLVM::GEPOp>(
787 Builder_->getUnknownLoc(),
788 ConvertType(*op->result(0)), // resultType
789 ConvertType(*op->getPointeeType()), // elementType
790 inputs[0], // basePtr
791 ::mlir::ValueRange({ std::next(inputs.begin()), inputs.end() })); // indices
792 }
793 else if (auto selectOp = dynamic_cast<const llvm::SelectOperation *>(&operation))
794 {
795 assert(selectOp->nresults() == 1);
796 assert(inputs.size() == 3);
797 MlirOp = Builder_->create<::mlir::arith::SelectOp>(
798 Builder_->getUnknownLoc(),
799 ConvertType(*selectOp->result(0)),
800 inputs[0],
801 inputs[1],
802 inputs[2]);
803 }
804 else if (auto matchOp = dynamic_cast<const rvsdg::MatchOperation *>(&operation))
805 {
806 // ** region Create the MLIR mapping vector **
810 ::llvm::SmallVector<::mlir::Attribute> mappingVector;
811 for (auto mapping : *matchOp)
812 {
813 ::mlir::rvsdg::MatchRuleAttr matchRule = ::mlir::rvsdg::MatchRuleAttr::get(
814 Builder_->getContext(),
815 ::llvm::ArrayRef(static_cast<int64_t>(mapping.first)),
816 mapping.second);
817
818 mappingVector.push_back(matchRule);
819 }
821 mappingVector.push_back(::mlir::rvsdg::MatchRuleAttr::get(
822 Builder_->getContext(),
823 ::llvm::ArrayRef<int64_t>(),
824 matchOp->default_alternative()));
825 // ** endregion Create the MLIR mapping vector **
826
827 MlirOp = Builder_->create<::mlir::rvsdg::Match>(
828 Builder_->getUnknownLoc(),
829 ConvertType(*node.output(0)->Type()), // Control, ouput type
830 inputs[0], // input
831 ::mlir::ArrayAttr::get(Builder_->getContext(), ::llvm::ArrayRef(mappingVector)));
832 }
833 else if (auto callOp = dynamic_cast<const jlm::llvm::CallOperation *>(&operation))
834 {
835 auto functionType = *callOp->GetFunctionType();
836 ::llvm::SmallVector<::mlir::Type> argumentTypes;
837 for (size_t i = 0; i < functionType.NumArguments(); i++)
838 {
839 argumentTypes.push_back(ConvertType(functionType.ArgumentType(i)));
840 }
841 ::llvm::SmallVector<::mlir::Type> resultTypes;
842 for (size_t i = 0; i < functionType.NumResults(); i++)
843 {
844 resultTypes.push_back(ConvertType(functionType.ResultType(i)));
845 }
846 MlirOp = Builder_->create<::mlir::jlm::Call>(
847 Builder_->getUnknownLoc(),
848 resultTypes,
849 inputs[0], // func ptr
850 ::mlir::ValueRange(
851 { std::next(inputs.begin()), std::prev(std::prev(inputs.end())) }), // args
852 inputs[inputs.size() - 2], // io
853 inputs[inputs.size() - 1] // mem
854 );
855 }
856 else if (
857 auto lambdaStateSplit =
858 dynamic_cast<const llvm::LambdaEntryMemoryStateSplitOperation *>(&operation))
859 {
860 auto memoryNodeIndicesAttr =
861 memoryNodeIndicesToArrayAttr(Builder_->getContext(), lambdaStateSplit->getMemoryNodeIds());
862
863 ::llvm::SmallVector<::mlir::Type> resultTypes;
864 for (size_t i = 0; i < lambdaStateSplit->nresults(); i++)
865 {
866 resultTypes.push_back(ConvertType(*lambdaStateSplit->result(i).get()));
867 }
868 MlirOp = Builder_->create<::mlir::rvsdg::LambdaEntryMemoryStateSplit>(
869 Builder_->getUnknownLoc(),
870 ::llvm::ArrayRef(resultTypes), // output types
871 inputs[0], // input
872 memoryNodeIndicesAttr);
873 }
874 else if (
875 auto lambdaStateMerge =
876 dynamic_cast<const jlm::llvm::LambdaExitMemoryStateMergeOperation *>(&operation))
877 {
878 auto memoryNodeIndicesAttr =
879 memoryNodeIndicesToArrayAttr(Builder_->getContext(), lambdaStateMerge->getMemoryNodeIds());
880
881 ::llvm::SmallVector<::mlir::Type> resultTypes;
882 for (size_t i = 0; i < lambdaStateMerge->nresults(); i++)
883 {
884 resultTypes.push_back(ConvertType(*lambdaStateMerge->result(i).get()));
885 }
886 MlirOp = Builder_->create<::mlir::rvsdg::LambdaExitMemoryStateMerge>(
887 Builder_->getUnknownLoc(),
888 ::llvm::ArrayRef(resultTypes), // output type
889 ::mlir::ValueRange(inputs), // inputs
890 memoryNodeIndicesAttr);
891 }
892 else if (
893 auto callStateSplit =
894 dynamic_cast<const jlm::llvm::CallExitMemoryStateSplitOperation *>(&operation))
895 {
896 auto memoryNodeIndicesAttr =
897 memoryNodeIndicesToArrayAttr(Builder_->getContext(), callStateSplit->getMemoryNodeIds());
898
899 ::llvm::SmallVector<::mlir::Type> resultTypes;
900 for (size_t i = 0; i < callStateSplit->nresults(); i++)
901 {
902 resultTypes.push_back(ConvertType(*callStateSplit->result(i).get()));
903 }
904 MlirOp = Builder_->create<::mlir::rvsdg::CallExitMemoryStateSplit>(
905 Builder_->getUnknownLoc(),
906 ::llvm::ArrayRef(resultTypes), // output types
907 inputs[0], // input
908 memoryNodeIndicesAttr);
909 }
910 else if (
911 auto callStateMerge =
912 dynamic_cast<const jlm::llvm::CallEntryMemoryStateMergeOperation *>(&operation))
913 {
914 auto memoryNodeIndicesAttr =
915 memoryNodeIndicesToArrayAttr(Builder_->getContext(), callStateMerge->getMemoryNodeIds());
916
917 ::llvm::SmallVector<::mlir::Type> resultTypes;
918 for (size_t i = 0; i < callStateMerge->nresults(); i++)
919 {
920 resultTypes.push_back(ConvertType(*callStateMerge->result(i).get()));
921 }
922 MlirOp = Builder_->create<::mlir::rvsdg::CallEntryMemoryStateMerge>(
923 Builder_->getUnknownLoc(),
924 ::llvm::ArrayRef(resultTypes), // output type
925 ::mlir::ValueRange(inputs), // inputs
926 memoryNodeIndicesAttr);
927 }
928 else if (auto memoryStateJoin = dynamic_cast<const llvm::MemoryStateJoinOperation *>(&operation))
929 {
930 ::mlir::Type resultType = ConvertType(*memoryStateJoin->result(0));
931
932 MlirOp = Builder_->create<::mlir::rvsdg::MemoryStateJoin>(
933 Builder_->getUnknownLoc(),
934 resultType,
935 ::mlir::ValueRange(inputs));
936 }
937 // ** endregion structural nodes **
938 else
939 {
940 auto message = util::strfmt("Unimplemented simple node: ", operation.debug_string());
941 JLM_UNREACHABLE(message.c_str());
942 }
943
944 block.push_back(MlirOp);
945 return MlirOp;
946}
947
948::llvm::SmallVector<::mlir::Type>
950{
951 ::llvm::SmallVector<::mlir::Type> typeRange;
952 for (size_t i = 0; i < nresults; ++i)
953 {
954 typeRange.push_back(Builder_->getType<::mlir::rvsdg::MemStateEdgeType>());
955 }
956 return typeRange;
957}
958
959::mlir::Operation *
961 const rvsdg::LambdaNode & lambdaNode,
962 ::mlir::Block & block,
963 const ::llvm::SmallVector<::mlir::Value> & inputs)
964{
965 // Add function attributes, e.g., the function name and linkage
966 ::llvm::SmallVector<::mlir::NamedAttribute> attributes;
967 auto symbolName = Builder_->getNamedAttr(
968 Builder_->getStringAttr("sym_name"),
969 Builder_->getStringAttr(
970 dynamic_cast<llvm::LlvmLambdaOperation &>(lambdaNode.GetOperation()).name()));
971 attributes.push_back(symbolName);
972 auto linkage = Builder_->getNamedAttr(
973 Builder_->getStringAttr("linkage"),
974 Builder_->getStringAttr(llvm::linkageToString(
975 dynamic_cast<llvm::LlvmLambdaOperation &>(lambdaNode.GetOperation()).linkage())));
976 attributes.push_back(linkage);
977
978 auto lambda = Builder_->create<::mlir::rvsdg::LambdaNode>(
979 Builder_->getUnknownLoc(),
980 ConvertType(*lambdaNode.output()->Type()),
981 inputs,
982 ::llvm::ArrayRef<::mlir::NamedAttribute>(attributes));
983 block.push_back(lambda);
984
985 auto & lambdaBlock = lambda.getRegion().emplaceBlock();
986 auto regionResults = ConvertRegion(*lambdaNode.subregion(), lambdaBlock);
987 auto lambdaResult =
988 Builder_->create<::mlir::rvsdg::LambdaResult>(Builder_->getUnknownLoc(), regionResults);
989 lambdaBlock.push_back(lambdaResult);
990
991 return lambda;
992}
993
994::mlir::Operation *
996 const rvsdg::GammaNode & gammaNode,
997 ::mlir::Block & block,
998 const ::llvm::SmallVector<::mlir::Value> & inputs)
999{
1000 auto & gammaOp = *util::assertedCast<const rvsdg::GammaOperation>(&gammaNode.GetOperation());
1001
1002 ::llvm::SmallVector<::mlir::Type> typeRangeOuput;
1003 for (size_t i = 0; i < gammaNode.noutputs(); ++i)
1004 {
1005 typeRangeOuput.push_back(ConvertType(*gammaNode.output(i)->Type()));
1006 }
1007
1008 // The predicate is always the first input
1009 // Predicate is used to select the region to execute
1010 ::mlir::Value predicate = inputs[0];
1011
1012 auto gamma = Builder_->create<::mlir::rvsdg::GammaNode>(
1013 Builder_->getUnknownLoc(),
1014 ::mlir::TypeRange(::llvm::ArrayRef(typeRangeOuput)), // Ouputs types
1015 predicate,
1016 ::mlir::ValueRange({ std::next(inputs.begin()), inputs.end() }), // Inputs
1017 gammaOp.nalternatives() // regionsCount
1018 );
1019 block.push_back(gamma);
1020
1021 for (size_t i = 0; i < gammaOp.nalternatives(); ++i)
1022 {
1023 auto & gammaBlock = gamma.getRegion(i).emplaceBlock();
1024 auto regionResults = ConvertRegion(*gammaNode.subregion(i), gammaBlock);
1025 auto gammaResult =
1026 Builder_->create<::mlir::rvsdg::GammaResult>(Builder_->getUnknownLoc(), regionResults);
1027 gammaBlock.push_back(gammaResult);
1028 }
1029
1030 return gamma;
1031}
1032
1033::mlir::Operation *
1035 const rvsdg::ThetaNode & thetaNode,
1036 ::mlir::Block & block,
1037 const ::llvm::SmallVector<::mlir::Value> & inputs)
1038{
1039 ::llvm::SmallVector<::mlir::Type> outputTypeRange;
1040 for (size_t i = 0; i < thetaNode.noutputs(); ++i)
1041 {
1042 outputTypeRange.push_back(ConvertType(*thetaNode.output(i)->Type()));
1043 }
1044
1045 ::llvm::SmallVector<::mlir::NamedAttribute> attributes;
1046
1047 auto theta = Builder_->create<::mlir::rvsdg::ThetaNode>(
1048 Builder_->getUnknownLoc(),
1049 ::mlir::TypeRange(::llvm::ArrayRef(outputTypeRange)),
1050 ::mlir::ValueRange(::llvm::ArrayRef(inputs)),
1051 attributes);
1052
1053 block.push_back(theta);
1054 auto & thetaBlock = theta.getRegion().emplaceBlock();
1055 auto regionResults = ConvertRegion(*thetaNode.subregion(), thetaBlock);
1056 auto results = ::mlir::ValueRange({ std::next(regionResults.begin()), regionResults.end() });
1057 auto thetaResult = Builder_->create<::mlir::rvsdg::ThetaResult>(
1058 Builder_->getUnknownLoc(),
1059 regionResults[0],
1060 results);
1061 thetaBlock.push_back(thetaResult);
1062 return theta;
1063}
1064
1065::mlir::Operation *
1067 const rvsdg::DeltaNode & deltaNode,
1068 ::mlir::Block & block,
1069 const ::llvm::SmallVector<::mlir::Value> & inputs)
1070{
1071 auto op = util::assertedCast<const llvm::LlvmDeltaOperation>(&deltaNode.GetOperation());
1072 auto delta = Builder_->create<::mlir::rvsdg::DeltaNode>(
1073 Builder_->getUnknownLoc(),
1074 Builder_->getType<::mlir::LLVM::LLVMPointerType>(),
1075 inputs,
1076 ::llvm::StringRef(op->name()),
1077 ::llvm::StringRef(llvm::linkageToString(op->linkage())),
1078 ::llvm::StringRef(op->Section()),
1079 op->constant());
1080 block.push_back(delta);
1081 auto & deltaBlock = delta.getRegion().emplaceBlock();
1082 auto regionResults = ConvertRegion(*deltaNode.subregion(), deltaBlock);
1083 JLM_ASSERT(regionResults.size() == 1); // Delta nodes have 1 output
1084 auto deltaResult =
1085 Builder_->create<::mlir::rvsdg::DeltaResult>(Builder_->getUnknownLoc(), regionResults[0]);
1086 deltaBlock.push_back(deltaResult);
1087 return delta;
1088}
1089
1090::mlir::FloatType
1092{
1093 switch (size)
1094 {
1096 return Builder_->getF16Type();
1098 return Builder_->getF32Type();
1100 return Builder_->getF64Type();
1102 return Builder_->getF80Type();
1104 return Builder_->getF128Type();
1105 default:
1106 auto message = util::strfmt(
1107 "Floating point type conversion not implemented: ",
1108 llvm::FloatingPointType(size).debug_string());
1109 JLM_UNREACHABLE(message.c_str());
1110 }
1111}
1112
1113::mlir::FunctionType
1115{
1116 ::llvm::SmallVector<::mlir::Type> argumentTypes;
1117 for (size_t i = 0; i < functionType.NumArguments(); i++)
1118 {
1119 argumentTypes.push_back(ConvertType(functionType.ArgumentType(i)));
1120 }
1121 ::llvm::SmallVector<::mlir::Type> resultTypes;
1122 for (size_t i = 0; i < functionType.NumResults(); i++)
1123 {
1124 resultTypes.push_back(ConvertType(functionType.ResultType(i)));
1125 }
1126 return Builder_->getFunctionType(argumentTypes, resultTypes);
1127}
1128
1129::mlir::Type
1131{
1132 if (auto bt = dynamic_cast<const rvsdg::BitType *>(&type))
1133 {
1134 return Builder_->getIntegerType(bt->nbits());
1135 }
1136 else if (auto fpt = dynamic_cast<const jlm::llvm::FloatingPointType *>(&type))
1137 {
1138 return ConvertFPType(fpt->size());
1139 }
1140 else if (rvsdg::is<llvm::IOStateType>(type))
1141 {
1142 return Builder_->getType<::mlir::rvsdg::IOStateEdgeType>();
1143 }
1144 else if (rvsdg::is<llvm::MemoryStateType>(type))
1145 {
1146 return Builder_->getType<::mlir::rvsdg::MemStateEdgeType>();
1147 }
1148 else if (auto clt = dynamic_cast<const rvsdg::ControlType *>(&type))
1149 {
1150 return Builder_->getType<::mlir::rvsdg::RVSDG_CTRLType>(clt->nalternatives());
1151 }
1152 else if (rvsdg::is<llvm::PointerType>(type))
1153 {
1154 return Builder_->getType<::mlir::LLVM::LLVMPointerType>();
1155 }
1156 else if (auto arrayType = dynamic_cast<const llvm::ArrayType *>(&type))
1157 {
1158 return Builder_->getType<::mlir::LLVM::LLVMArrayType>(
1159 ConvertType(arrayType->element_type()),
1160 arrayType->nelements());
1161 }
1162 else if (auto functionType = dynamic_cast<const jlm::rvsdg::FunctionType *>(&type))
1163 {
1164 return ConvertFunctionType(*functionType);
1165 }
1167 {
1168 return Builder_->getType<::mlir::jlm::VarargListType>();
1169 }
1170 else if (rvsdg::is<const rvsdg::UnitType>(type))
1171 {
1172 return Builder_->getType<::mlir::NoneType>();
1173 }
1174 else if (auto structType = dynamic_cast<const llvm::StructType *>(&type))
1175 {
1176 std::vector<::mlir::Type> elements;
1177 for (size_t i = 0; i < structType->numElements(); i++)
1178 {
1179 elements.push_back(ConvertType(*structType->getElementType(i)));
1180 }
1181
1182 if (structType->IsLiteral())
1183 {
1184 return ::mlir::LLVM::LLVMStructType::getLiteral(
1185 Builder_->getContext(),
1186 elements,
1187 structType->IsPacked());
1188 }
1189 else
1190 {
1191 auto mlirStructType = ::mlir::LLVM::LLVMStructType::getIdentified(
1192 Builder_->getContext(),
1193 structType->GetName());
1194 if (mlirStructType.isInitialized())
1195 return mlirStructType;
1196 if (mlirStructType.setBody(elements, structType->IsPacked()).failed())
1197 {
1198 throw util::Error("Not able to set the body of struct in the MLIR backend.");
1199 }
1200 return mlirStructType;
1201 }
1202 }
1203 else
1204 {
1205 auto message = util::strfmt("Type conversion not implemented: ", type.debug_string());
1206 JLM_UNREACHABLE(message.c_str());
1207 }
1208}
1209
1210::mlir::Operation *
1212 const jlm::llvm::IntegerBinaryOperation & operation,
1213 ::llvm::SmallVector<::mlir::Value> inputs)
1214{
1216 {
1217 return Builder_->create<::mlir::arith::AddIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1218 }
1220 {
1221 return Builder_->create<::mlir::arith::SubIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1222 }
1224 {
1225 return Builder_->create<::mlir::arith::MulIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1226 }
1228 {
1229 return Builder_->create<::mlir::arith::DivSIOp>(
1230 Builder_->getUnknownLoc(),
1231 inputs[0],
1232 inputs[1]);
1233 }
1235 {
1236 return Builder_->create<::mlir::arith::DivUIOp>(
1237 Builder_->getUnknownLoc(),
1238 inputs[0],
1239 inputs[1]);
1240 }
1242 {
1243 return Builder_->create<::mlir::arith::RemSIOp>(
1244 Builder_->getUnknownLoc(),
1245 inputs[0],
1246 inputs[1]);
1247 }
1249 {
1250 return Builder_->create<::mlir::arith::RemUIOp>(
1251 Builder_->getUnknownLoc(),
1252 inputs[0],
1253 inputs[1]);
1254 }
1256 {
1257 return Builder_->create<::mlir::LLVM::AShrOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1258 }
1260 {
1261 return Builder_->create<::mlir::LLVM::ShlOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1262 }
1264 {
1265 return Builder_->create<::mlir::LLVM::LShrOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1266 }
1268 {
1269 return Builder_->create<::mlir::arith::AndIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1270 }
1271 else if (rvsdg::is<jlm::llvm::IntegerOrOperation>(operation))
1272 {
1273 return Builder_->create<::mlir::arith::OrIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1274 }
1276 {
1277 return Builder_->create<::mlir::arith::XOrIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1278 }
1279 else if (rvsdg::is<jlm::llvm::IntegerEqOperation>(operation))
1280 {
1281 return Builder_->create<::mlir::arith::CmpIOp>(
1282 Builder_->getUnknownLoc(),
1283 ::mlir::arith::CmpIPredicate::eq,
1284 inputs[0],
1285 inputs[1]);
1286 }
1287 else if (rvsdg::is<jlm::llvm::IntegerNeOperation>(operation))
1288 {
1289 return Builder_->create<::mlir::arith::CmpIOp>(
1290 Builder_->getUnknownLoc(),
1291 ::mlir::arith::CmpIPredicate::ne,
1292 inputs[0],
1293 inputs[1]);
1294 }
1296 {
1297 return Builder_->create<::mlir::arith::CmpIOp>(
1298 Builder_->getUnknownLoc(),
1299 ::mlir::arith::CmpIPredicate::sge,
1300 inputs[0],
1301 inputs[1]);
1302 }
1304 {
1305 return Builder_->create<::mlir::arith::CmpIOp>(
1306 Builder_->getUnknownLoc(),
1307 ::mlir::arith::CmpIPredicate::sgt,
1308 inputs[0],
1309 inputs[1]);
1310 }
1312 {
1313 return Builder_->create<::mlir::arith::CmpIOp>(
1314 Builder_->getUnknownLoc(),
1315 ::mlir::arith::CmpIPredicate::sle,
1316 inputs[0],
1317 inputs[1]);
1318 }
1320 {
1321 return Builder_->create<::mlir::arith::CmpIOp>(
1322 Builder_->getUnknownLoc(),
1323 ::mlir::arith::CmpIPredicate::slt,
1324 inputs[0],
1325 inputs[1]);
1326 }
1328 {
1329 return Builder_->create<::mlir::arith::CmpIOp>(
1330 Builder_->getUnknownLoc(),
1331 ::mlir::arith::CmpIPredicate::uge,
1332 inputs[0],
1333 inputs[1]);
1334 }
1336 {
1337 return Builder_->create<::mlir::arith::CmpIOp>(
1338 Builder_->getUnknownLoc(),
1339 ::mlir::arith::CmpIPredicate::ugt,
1340 inputs[0],
1341 inputs[1]);
1342 }
1344 {
1345 return Builder_->create<::mlir::arith::CmpIOp>(
1346 Builder_->getUnknownLoc(),
1347 ::mlir::arith::CmpIPredicate::ule,
1348 inputs[0],
1349 inputs[1]);
1350 }
1352 {
1353 return Builder_->create<::mlir::arith::CmpIOp>(
1354 Builder_->getUnknownLoc(),
1355 ::mlir::arith::CmpIPredicate::ult,
1356 inputs[0],
1357 inputs[1]);
1358 }
1359 else
1360 {
1361 auto message =
1362 util::strfmt("Unimplemented integer binary operation: ", operation.debug_string());
1363 JLM_UNREACHABLE(message.c_str());
1364 }
1365}
1366
1367} // namespace jlm::mlir
Call operation class.
Definition call.hpp:251
ConstantPointerNullOperation class.
const llvm::fpop & fpop() const noexcept
const fpcmp & cmp() const noexcept
Get address of compiled function object.
const jlm::llvm::Linkage & linkage() const noexcept
Definition lambda.hpp:48
const std::string & name() const noexcept
Definition lambda.hpp:42
Interpret pointer as callable function.
ICmpPredicate predicate() const noexcept
StructType class.
Definition types.hpp:184
UndefValueOperation class.
::mlir::Operation * ConvertDelta(const rvsdg::DeltaNode &node, ::mlir::Block &block, const ::llvm::SmallVector<::mlir::Value > &inputs)
::llvm::SmallVector<::mlir::Value > ConvertRegion(rvsdg::Region &region, ::mlir::Block &block, bool isRoot=false)
::mlir::FloatType ConvertFPType(const llvm::fpsize size)
::mlir::FunctionType ConvertFunctionType(const jlm::rvsdg::FunctionType &functionType)
::mlir::Operation * ConvertTheta(const rvsdg::ThetaNode &thetaNode, ::mlir::Block &block, const ::llvm::SmallVector<::mlir::Value > &inputs)
::mlir::Type ConvertType(const rvsdg::Type &type)
::mlir::Operation * ConvertNode(const rvsdg::Node &node, ::mlir::Block &block, const ::llvm::SmallVector<::mlir::Value > &inputs)
::mlir::Operation * BitCompareNode(const rvsdg::SimpleOperation &bitOp, ::llvm::SmallVector<::mlir::Value > inputs)
::llvm::SmallVector<::mlir::Type > GetMemStateRange(size_t nresults)
::mlir::Operation * ConvertPointerCompareNode(const llvm::PtrCmpOperation &pointerCompareOp, ::llvm::SmallVector<::mlir::Value > inputs)
::mlir::Operation * ConvertGamma(const rvsdg::GammaNode &gammaNode, ::mlir::Block &block, const ::llvm::SmallVector<::mlir::Value > &inputs)
static void Print(::mlir::rvsdg::OmegaNode &omega, const util::FilePath &filePath)
static ::llvm::SmallVector<::mlir::Value > GetConvertedInputs(const rvsdg::Node &node, const std::unordered_map< rvsdg::Output *, ::mlir::Value > &valueMap)
::mlir::Operation * ConvertFpBinaryNode(const jlm::llvm::FBinaryOperation &op, ::llvm::SmallVector<::mlir::Value > inputs)
::mlir::Operation * ConvertLambda(const rvsdg::LambdaNode &node, ::mlir::Block &block, const ::llvm::SmallVector<::mlir::Value > &inputs)
::mlir::Operation * ConvertIntegerBinaryOperation(const jlm::llvm::IntegerBinaryOperation &operation, ::llvm::SmallVector<::mlir::Value > inputs)
::mlir::Operation * ConvertBitBinaryNode(const rvsdg::SimpleOperation &bitOp, ::llvm::SmallVector<::mlir::Value > inputs)
::mlir::Operation * ConvertSimpleNode(const rvsdg::SimpleNode &node, ::mlir::Block &block, const ::llvm::SmallVector<::mlir::Value > &inputs)
::mlir::rvsdg::OmegaNode ConvertModule(const llvm::LlvmRvsdgModule &rvsdgModule)
std::unique_ptr<::mlir::OpBuilder > Builder_
::mlir::Operation * ConvertFpCompareNode(const jlm::llvm::FCmpOperation &op, ::llvm::SmallVector<::mlir::Value > inputs)
const DeltaOperation & GetOperation() const noexcept override
Definition delta.cpp:71
rvsdg::Region * subregion() const noexcept
Definition delta.hpp:234
Function type class.
const jlm::rvsdg::Type & ArgumentType(size_t index) const noexcept
size_t NumArguments() const noexcept
size_t NumResults() const noexcept
const jlm::rvsdg::Type & ResultType(size_t index) const noexcept
Conditional operator / pattern matching.
Definition gamma.hpp:99
const GammaOperation & GetOperation() const noexcept override
Definition gamma.cpp:254
Output * origin() const noexcept
Definition node.hpp:58
rvsdg::Output * output() const noexcept
Definition lambda.cpp:177
rvsdg::Region * subregion() const noexcept
Definition lambda.hpp:138
LambdaOperation & GetOperation() const noexcept override
Definition lambda.cpp:52
NodeInput * input(size_t index) const noexcept
Definition node.hpp:615
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::string debug_string() const =0
virtual std::string debug_string() const
Definition node.cpp:168
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:366
std::string debug_string() const override
Definition region.cpp:100
Represent acyclic RVSDG subgraphs.
Definition region.hpp:213
RegionArgument * argument(size_t index) const noexcept
Definition region.hpp:466
size_t nresults() const noexcept
Definition region.hpp:494
RegionResult * result(size_t index) const noexcept
Definition region.hpp:500
size_t narguments() const noexcept
Definition region.hpp:460
Graph & Rvsdg() noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeOutput * output(size_t index) const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
StructuralOutput * output(size_t index) const noexcept
rvsdg::Region * subregion() const noexcept
Definition theta.hpp:90
virtual std::string debug_string() const =0
const std::string & to_str() const noexcept
Definition file.hpp:275
#define JLM_ASSERT(x)
Definition common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition common.hpp:43
std::string_view linkageToString(const Linkage linkage)
Definition Linkage.cpp:17
const util::BijectiveMap<::mlir::arith::CmpFPredicate, llvm::fpcmp > & GetFpCmpPredicateMap()
::mlir::ArrayAttr memoryNodeIndicesToArrayAttr(::mlir::MLIRContext *context, const std::vector< llvm::MemoryNodeId > &memoryNodeIndices)
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