Jlm
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>
23 #include <jlm/rvsdg/traverser.hpp>
24 #include <jlm/rvsdg/UnitType.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 
34 namespace jlm::mlir
35 {
36 
37 void
38 JlmToMlirConverter::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  auto omegaResult =
70  Builder_->create<::mlir::rvsdg::OmegaResult>(Builder_->getUnknownLoc(), regionResults);
71  omegaBlock.push_back(omegaResult);
72  return omega;
73 }
74 
75 ::llvm::SmallVector<::mlir::Value>
76 JlmToMlirConverter::ConvertRegion(rvsdg::Region & region, ::mlir::Block & block, bool isRoot)
77 {
78  std::unordered_map<rvsdg::Output *, ::mlir::Value> valueMap;
79  size_t argIndex = 0;
80  for (size_t i = 0; i < region.narguments(); ++i)
81  {
82  auto arg = region.argument(i);
83  if (isRoot) // Omega arguments are treated separately
84  {
85  auto imp = util::assertedCast<llvm::LlvmGraphImport>(arg);
86  block.push_back(Builder_->create<::mlir::rvsdg::OmegaArgument>(
87  Builder_->getUnknownLoc(),
88  ConvertType(*imp->ImportedType()),
89  ConvertType(*imp->ValueType()),
90  Builder_->getStringAttr(llvm::linkageToString(imp->linkage())),
91  Builder_->getStringAttr(imp->Name())));
92  valueMap[arg] = block.back().getResult(0); // Add the output of the omega argument
93  }
94  else
95  {
96  block.addArgument(ConvertType(*arg->Type()), Builder_->getUnknownLoc());
97  valueMap[arg] = block.getArgument(argIndex);
98  ++argIndex;
99  }
100  }
101 
102  // Create an MLIR operation for each RVSDG node.
103  // The mapping from RVSDG output to MLIR result is added to the valueMap for quick lookup.
104  for (rvsdg::Node * rvsdgNode : rvsdg::TopDownTraverser(&region))
105  {
106  ::llvm::SmallVector<::mlir::Value> inputs = GetConvertedInputs(*rvsdgNode, valueMap);
107 
108  auto convertedNode = ConvertNode(*rvsdgNode, block, inputs);
109  for (size_t i = 0; i < rvsdgNode->noutputs(); i++)
110  {
111  valueMap[rvsdgNode->output(i)] = convertedNode->getResult(i);
112  }
113  }
114 
115  // This code is used to get the results of the region
117  ::llvm::SmallVector<::mlir::Value> results;
118  for (size_t i = 0; i < region.nresults(); i++)
119  {
120  auto it = valueMap.find(region.result(i)->origin());
121  if (it != valueMap.end())
122  {
123  results.push_back(it->second);
124  }
125  else
126  {
127  auto message = util::strfmt(
128  "Unimplemented input type: ",
129  region.result(i)->origin()->debug_string(),
130  ": ",
131  region.result(i)->origin()->Type()->debug_string(),
132  " for region result: ",
133  region.result(i)->debug_string(),
134  " at index: ",
135  i);
136  JLM_UNREACHABLE(message.c_str());
137  }
138  }
139 
140  return results;
141 }
142 
143 ::llvm::SmallVector<::mlir::Value>
145  const rvsdg::Node & node,
146  const std::unordered_map<rvsdg::Output *, ::mlir::Value> & valueMap)
147 {
148  ::llvm::SmallVector<::mlir::Value> inputs;
149  for (size_t i = 0; i < node.ninputs(); i++)
150  {
151  auto it = valueMap.find(node.input(i)->origin());
152  if (it != valueMap.end())
153  {
154  inputs.push_back(it->second);
155  }
156  else
157  {
158  auto message = util::strfmt(
159  "Unimplemented input type: ",
160  node.input(i)->origin()->debug_string(),
161  ": ",
162  node.input(i)->origin()->Type()->debug_string(),
163  " for node: ",
164  node.DebugString(),
165  " at index: ",
166  i);
167  JLM_UNREACHABLE(message.c_str());
168  }
169  }
170  return inputs;
171 }
172 
173 ::mlir::Operation *
175  const rvsdg::Node & node,
176  ::mlir::Block & block,
177  const ::llvm::SmallVector<::mlir::Value> & inputs)
178 {
179  if (auto simpleNode = dynamic_cast<const rvsdg::SimpleNode *>(&node))
180  {
181  return ConvertSimpleNode(*simpleNode, block, inputs);
182  }
183  else if (auto lambda = dynamic_cast<const rvsdg::LambdaNode *>(&node))
184  {
185  return ConvertLambda(*lambda, block, inputs);
186  }
187  else if (auto gamma = dynamic_cast<const rvsdg::GammaNode *>(&node))
188  {
189  return ConvertGamma(*gamma, block, inputs);
190  }
191  else if (auto theta = dynamic_cast<const rvsdg::ThetaNode *>(&node))
192  {
193  return ConvertTheta(*theta, block, inputs);
194  }
195  else if (auto delta = dynamic_cast<const rvsdg::DeltaNode *>(&node))
196  {
197  return ConvertDelta(*delta, block, inputs);
198  }
199  else
200  {
201  auto message = util::strfmt("Unimplemented structural node: ", node.DebugString());
202  JLM_UNREACHABLE(message.c_str());
203  }
204 }
205 
206 ::mlir::Operation *
208  const jlm::llvm::FBinaryOperation & op,
209  ::llvm::SmallVector<::mlir::Value> inputs)
210 {
211  switch (op.fpop())
212  {
214  return Builder_->create<::mlir::arith::AddFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
216  return Builder_->create<::mlir::arith::SubFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
218  return Builder_->create<::mlir::arith::MulFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
220  return Builder_->create<::mlir::arith::DivFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
222  return Builder_->create<::mlir::arith::RemFOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
223  default:
224  JLM_UNREACHABLE("Unknown binary bitop");
225  }
226 }
227 
228 ::mlir::Operation *
230  const llvm::FCmpOperation & op,
231  ::llvm::SmallVector<::mlir::Value> inputs)
232 {
233  const auto & map = GetFpCmpPredicateMap();
234  auto predicate = map.LookupValue(op.cmp());
235  return Builder_->create<::mlir::arith::CmpFOp>(
236  Builder_->getUnknownLoc(),
237  Builder_->getAttr<::mlir::arith::CmpFPredicateAttr>(predicate),
238  inputs[0],
239  inputs[1]);
240 }
241 
242 ::mlir::Operation *
244  const rvsdg::SimpleOperation & bitOp,
245  ::llvm::SmallVector<::mlir::Value> inputs)
246 {
247  ::mlir::Operation * MlirOp = nullptr;
248  if (jlm::rvsdg::is<const rvsdg::bitadd_op>(bitOp))
249  {
250  MlirOp =
251  Builder_->create<::mlir::arith::AddIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
252  }
253  else if (jlm::rvsdg::is<const rvsdg::bitand_op>(bitOp))
254  {
255  MlirOp =
256  Builder_->create<::mlir::arith::AndIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
257  }
258  else if (jlm::rvsdg::is<const rvsdg::bitashr_op>(bitOp))
259  {
260  MlirOp =
261  Builder_->create<::mlir::arith::ShRUIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
262  }
263  else if (jlm::rvsdg::is<const rvsdg::bitmul_op>(bitOp))
264  {
265  MlirOp =
266  Builder_->create<::mlir::arith::MulIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
267  }
268  else if (jlm::rvsdg::is<const rvsdg::bitor_op>(bitOp))
269  {
270  MlirOp =
271  Builder_->create<::mlir::arith::OrIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
272  }
273  else if (jlm::rvsdg::is<const rvsdg::bitsdiv_op>(bitOp))
274  {
275  MlirOp =
276  Builder_->create<::mlir::arith::DivSIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
277  }
278  else if (jlm::rvsdg::is<const rvsdg::bitshl_op>(bitOp))
279  {
280  MlirOp =
281  Builder_->create<::mlir::arith::ShLIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
282  }
283  else if (jlm::rvsdg::is<const rvsdg::bitshr_op>(bitOp))
284  {
285  MlirOp =
286  Builder_->create<::mlir::arith::ShRUIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
287  }
288  else if (jlm::rvsdg::is<const rvsdg::bitsmod_op>(bitOp))
289  {
290  MlirOp =
291  Builder_->create<::mlir::arith::RemSIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
292  }
293  else if (jlm::rvsdg::is<const rvsdg::bitsmulh_op>(bitOp))
294  {
295  JLM_UNREACHABLE("Binary bit bitOp smulh not supported");
296  }
297  else if (jlm::rvsdg::is<const rvsdg::bitsub_op>(bitOp))
298  {
299  MlirOp =
300  Builder_->create<::mlir::arith::SubIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
301  }
302  else if (jlm::rvsdg::is<const rvsdg::bitudiv_op>(bitOp))
303  {
304  MlirOp =
305  Builder_->create<::mlir::arith::DivUIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
306  }
307  else if (jlm::rvsdg::is<const rvsdg::bitumod_op>(bitOp))
308  {
309  MlirOp =
310  Builder_->create<::mlir::arith::RemUIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
311  }
312  else if (jlm::rvsdg::is<const rvsdg::bitumulh_op>(bitOp))
313  {
314  JLM_UNREACHABLE("Binary bit bitOp umulh not supported");
315  }
316  else if (jlm::rvsdg::is<const rvsdg::bitxor_op>(bitOp))
317  {
318  MlirOp =
319  Builder_->create<::mlir::arith::XOrIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
320  }
321  else
322  {
323  JLM_UNREACHABLE("Unknown binary bitop");
324  }
325 
326  return MlirOp;
327 }
328 
329 ::mlir::Operation *
331  const rvsdg::SimpleOperation & bitOp,
332  ::llvm::SmallVector<::mlir::Value> inputs)
333 {
334  auto compPredicate = ::mlir::arith::CmpIPredicate::eq;
335  if (jlm::rvsdg::is<const rvsdg::biteq_op>(bitOp))
336  compPredicate = ::mlir::arith::CmpIPredicate::eq;
337  else if (jlm::rvsdg::is<const rvsdg::bitne_op>(bitOp))
338  compPredicate = ::mlir::arith::CmpIPredicate::ne;
339  else if (jlm::rvsdg::is<const rvsdg::bitsge_op>(bitOp))
340  compPredicate = ::mlir::arith::CmpIPredicate::sge;
341  else if (jlm::rvsdg::is<const rvsdg::bitsgt_op>(bitOp))
342  compPredicate = ::mlir::arith::CmpIPredicate::sgt;
343  else if (jlm::rvsdg::is<const rvsdg::bitsle_op>(bitOp))
344  compPredicate = ::mlir::arith::CmpIPredicate::sle;
345  else if (jlm::rvsdg::is<const rvsdg::bitslt_op>(bitOp))
346  compPredicate = ::mlir::arith::CmpIPredicate::slt;
347  else if (jlm::rvsdg::is<const rvsdg::bituge_op>(bitOp))
348  compPredicate = ::mlir::arith::CmpIPredicate::uge;
349  else if (jlm::rvsdg::is<const rvsdg::bitugt_op>(bitOp))
350  compPredicate = ::mlir::arith::CmpIPredicate::ugt;
351  else if (jlm::rvsdg::is<const rvsdg::bitule_op>(bitOp))
352  compPredicate = ::mlir::arith::CmpIPredicate::ule;
353  else if (jlm::rvsdg::is<const rvsdg::bitult_op>(bitOp))
354  compPredicate = ::mlir::arith::CmpIPredicate::ult;
355  else
356  {
357  auto message = util::strfmt("Unknown compare operation: ", bitOp.debug_string());
358  JLM_UNREACHABLE(message.c_str());
359  }
360 
361  auto MlirOp = Builder_->create<::mlir::arith::CmpIOp>(
362  Builder_->getUnknownLoc(),
363  compPredicate,
364  inputs[0],
365  inputs[1]);
366  return MlirOp;
367 }
368 
369 ::mlir::Operation *
371  const llvm::PtrCmpOperation & operation,
372  ::llvm::SmallVector<::mlir::Value> inputs)
373 {
374  static std::unordered_map<llvm::ICmpPredicate, ::mlir::LLVM::ICmpPredicate> map = {
375  { llvm::ICmpPredicate::Eq, ::mlir::LLVM::ICmpPredicate::eq },
376  { llvm::ICmpPredicate::Ne, ::mlir::LLVM::ICmpPredicate::ne },
377  { llvm::ICmpPredicate::Ugt, ::mlir::LLVM::ICmpPredicate::ugt },
378  { llvm::ICmpPredicate::Uge, ::mlir::LLVM::ICmpPredicate::uge },
379  { llvm::ICmpPredicate::Ult, ::mlir::LLVM::ICmpPredicate::ult },
380  { llvm::ICmpPredicate::Ule, ::mlir::LLVM::ICmpPredicate::ule },
381  { llvm::ICmpPredicate::Sgt, ::mlir::LLVM::ICmpPredicate::sgt },
382  { llvm::ICmpPredicate::Sge, ::mlir::LLVM::ICmpPredicate::sge },
383  { llvm::ICmpPredicate::Slt, ::mlir::LLVM::ICmpPredicate::slt },
384  { llvm::ICmpPredicate::Sle, ::mlir::LLVM::ICmpPredicate::sle },
385  };
386 
387  const auto mlirPredicate = map.at(operation.predicate());
388  auto MlirOp = Builder_->create<::mlir::LLVM::ICmpOp>(
389  Builder_->getUnknownLoc(),
390  mlirPredicate,
391  inputs[0],
392  inputs[1]);
393  return MlirOp;
394 }
395 
403 static ::mlir::ArrayAttr
405  ::mlir::MLIRContext * context,
406  const std::vector<llvm::MemoryNodeId> & memoryNodeIndices)
407 {
408  auto int64Type = ::mlir::IntegerType::get(context, 64);
409  ::llvm::SmallVector<::mlir::Attribute> intAttributes;
410  for (auto memoryNodeId : memoryNodeIndices)
411  {
412  intAttributes.push_back(::mlir::IntegerAttr::get(int64Type, memoryNodeId));
413  }
414  return ::mlir::ArrayAttr::get(context, intAttributes);
415 }
416 
417 ::mlir::Operation *
419  const rvsdg::SimpleNode & node,
420  ::mlir::Block & block,
421  const ::llvm::SmallVector<::mlir::Value> & inputs)
422 {
423  ::mlir::Operation * MlirOp = nullptr;
424  auto & operation = node.GetOperation();
425  if (auto bitOp = dynamic_cast<const rvsdg::BitConstantOperation *>(&operation))
426  {
427  auto value = bitOp->value();
428  MlirOp = Builder_->create<::mlir::arith::ConstantIntOp>(
429  Builder_->getUnknownLoc(),
430  value.to_uint(),
431  value.nbits());
432  }
433  else if (
434  auto integerConstOp = dynamic_cast<const jlm::llvm::IntegerConstantOperation *>(&operation))
435  {
436  auto isNegative = integerConstOp->Representation().is_negative();
437  auto value = isNegative ? integerConstOp->Representation().to_int()
438  : integerConstOp->Representation().to_uint();
439  MlirOp = Builder_->create<::mlir::arith::ConstantIntOp>(
440  Builder_->getUnknownLoc(),
441  value,
442  integerConstOp->Representation().nbits());
443  }
444  else if (auto fpBinOp = dynamic_cast<const jlm::llvm::FBinaryOperation *>(&operation))
445  {
446  MlirOp = ConvertFpBinaryNode(*fpBinOp, inputs);
447  }
448  else if (rvsdg::is<jlm::llvm::FMulAddIntrinsicOperation>(operation))
449  {
450  MlirOp = Builder_->create<::mlir::LLVM::FMulAddOp>(
451  Builder_->getUnknownLoc(),
452  inputs[0],
453  inputs[1],
454  inputs[2]);
455  }
456  else if (rvsdg::is<jlm::llvm::IntegerBinaryOperation>(operation))
457  {
459  *dynamic_cast<const jlm::llvm::IntegerBinaryOperation *>(&operation),
460  inputs);
461  }
462  else if (auto fpOp = dynamic_cast<const llvm::ConstantFP *>(&operation))
463  {
464  auto size = ConvertFPType(fpOp->size());
465  auto value = fpOp->constant();
466  MlirOp =
467  Builder_->create<::mlir::arith::ConstantFloatOp>(Builder_->getUnknownLoc(), value, size);
468  }
469  else if (auto zeroOp = dynamic_cast<const llvm::ConstantAggregateZeroOperation *>(&operation))
470  {
471  auto type = ConvertType(*zeroOp->result(0));
472  MlirOp = Builder_->create<::mlir::LLVM::ZeroOp>(Builder_->getUnknownLoc(), type);
473  }
474  else if (auto arrOp = dynamic_cast<const llvm::ConstantDataArray *>(&operation))
475  {
476  auto arrayType = ConvertType(*arrOp->result(0));
477  MlirOp = Builder_->create<::mlir::jlm::ConstantDataArray>(
478  Builder_->getUnknownLoc(),
479  arrayType,
480  inputs);
481  }
482  else if (auto zeroOp = dynamic_cast<const llvm::ConstantAggregateZeroOperation *>(&operation))
483  {
484  auto type = ConvertType(*zeroOp->result(0));
485  MlirOp = Builder_->create<::mlir::LLVM::ZeroOp>(Builder_->getUnknownLoc(), type);
486  }
487  else if (
488  auto constantPointerNullOp =
489  dynamic_cast<const llvm::ConstantPointerNullOperation *>(&operation))
490  {
491  // NULL pointers are a special case of ZeroOp
492  auto type = ConvertType(*constantPointerNullOp->result(0));
493  MlirOp = Builder_->create<::mlir::LLVM::ZeroOp>(Builder_->getUnknownLoc(), type);
494  }
495  else if (jlm::rvsdg::is<const rvsdg::BitBinaryOperation>(operation))
496  {
497  MlirOp = ConvertBitBinaryNode(operation, inputs);
498  }
499  else if (auto fpBinOp = dynamic_cast<const jlm::llvm::FBinaryOperation *>(&operation))
500  {
501  MlirOp = ConvertFpBinaryNode(*fpBinOp, inputs);
502  }
503  else if (rvsdg::is<const jlm::llvm::FNegOperation>(operation))
504  {
505  MlirOp = Builder_->create<::mlir::arith::NegFOp>(Builder_->getUnknownLoc(), inputs[0]);
506  }
507  else if (auto fpextOp = dynamic_cast<const jlm::llvm::FPExtOperation *>(&operation))
508  {
509  MlirOp = Builder_->create<::mlir::arith::ExtFOp>(
510  Builder_->getUnknownLoc(),
511  ConvertType(*fpextOp->result(0)),
512  inputs[0]);
513  }
514 
515  else if (jlm::rvsdg::is<const rvsdg::BitCompareOperation>(operation))
516  {
517  MlirOp = BitCompareNode(operation, inputs);
518  }
519  else if (auto fpCmpOp = dynamic_cast<const llvm::FCmpOperation *>(&operation))
520  {
521  MlirOp = ConvertFpCompareNode(*fpCmpOp, inputs);
522  }
523  else if (auto pointerCompareOp = dynamic_cast<const llvm::PtrCmpOperation *>(&operation))
524  {
525  MlirOp = ConvertPointerCompareNode(*pointerCompareOp, inputs);
526  }
527  else if (const auto zextOperation = dynamic_cast<const llvm::ZExtOperation *>(&operation))
528  {
529  MlirOp = Builder_->create<::mlir::arith::ExtUIOp>(
530  Builder_->getUnknownLoc(),
531  Builder_->getIntegerType(zextOperation->ndstbits()),
532  inputs[0]);
533  }
534  else if (auto sextOp = dynamic_cast<const jlm::llvm::SExtOperation *>(&operation))
535  {
536  MlirOp = Builder_->create<::mlir::arith::ExtSIOp>(
537  Builder_->getUnknownLoc(),
538  Builder_->getIntegerType(sextOp->ndstbits()),
539  inputs[0]);
540  }
541  else if (auto sitofpOp = dynamic_cast<const llvm::SIToFPOperation *>(&operation))
542  {
543  MlirOp = Builder_->create<::mlir::arith::SIToFPOp>(
544  Builder_->getUnknownLoc(),
545  ConvertType(*sitofpOp->result(0)),
546  inputs[0]);
547  }
548  else if (auto truncOp = dynamic_cast<const jlm::llvm::TruncOperation *>(&operation))
549  {
550  MlirOp = Builder_->create<::mlir::arith::TruncIOp>(
551  Builder_->getUnknownLoc(),
552  ConvertType(*truncOp->result(0)),
553  inputs[0]);
554  }
555  // ** region structural nodes **
556  else if (auto ctlOp = dynamic_cast<const rvsdg::ControlConstantOperation *>(&operation))
557  {
558  MlirOp = Builder_->create<::mlir::rvsdg::ConstantCtrl>(
559  Builder_->getUnknownLoc(),
560  ConvertType(*node.output(0)->Type()), // Control, ouput type
561  ctlOp->value().alternative());
562  }
563  else if (auto vaOp = dynamic_cast<const llvm::VariadicArgumentListOperation *>(&operation))
564  {
565  MlirOp = Builder_->create<::mlir::jlm::CreateVarArgList>(
566  Builder_->getUnknownLoc(),
567  ConvertType(*vaOp->result(0)),
568  inputs);
569  }
570  else if (auto undefOp = dynamic_cast<const llvm::UndefValueOperation *>(&operation))
571  {
572  MlirOp = Builder_->create<::mlir::jlm::Undef>(
573  Builder_->getUnknownLoc(),
574  ConvertType(undefOp->GetType()));
575  }
576  else if (auto freeOp = dynamic_cast<const jlm::llvm::FreeOperation *>(&operation))
577  {
578  auto nMemstates = freeOp->narguments() - 2; // Subtract for pointer and io state
579 
580  std::vector<::mlir::Type> memoryStates(
581  nMemstates,
582  Builder_->getType<::mlir::rvsdg::MemStateEdgeType>());
583  MlirOp = Builder_->create<::mlir::jlm::Free>(
584  Builder_->getUnknownLoc(),
585  ::mlir::TypeRange(::llvm::ArrayRef(memoryStates)),
586  Builder_->getType<::mlir::rvsdg::IOStateEdgeType>(),
587  inputs[0],
588  ::mlir::ValueRange({ std::next(inputs.begin()), std::prev(inputs.end()) }),
589  inputs[inputs.size() - 1]);
590  }
591  else if (auto alloca_op = dynamic_cast<const jlm::llvm::AllocaOperation *>(&operation))
592  {
593  MlirOp = Builder_->create<::mlir::jlm::Alloca>(
594  Builder_->getUnknownLoc(),
595  ConvertType(*alloca_op->result(0)), // ptr
596  ConvertType(*alloca_op->result(1)), // memstate
597  ConvertType(*alloca_op->allocatedType()), // value type
598  inputs[0], // size
599  alloca_op->alignment(), // alignment
600  ::mlir::ValueRange({ std::next(inputs.begin()), inputs.end() })); // inputMemStates
601  }
602  else if (auto malloc_op = dynamic_cast<const jlm::llvm::MallocOperation *>(&operation))
603  {
604  MlirOp = Builder_->create<::mlir::jlm::Malloc>(
605  Builder_->getUnknownLoc(),
606  ConvertType(*malloc_op->result(0)), // ptr
607  ConvertType(*malloc_op->result(1)), // IOState
608  ConvertType(*malloc_op->result(2)), // memstate
609  inputs[0], // size
610  inputs[1] // IOState
611  );
612  }
613  else if (auto load_op = dynamic_cast<const jlm::llvm::LoadOperation *>(&operation))
614  {
615  // Can have more than a single memory state
616  ::llvm::SmallVector<::mlir::Type> memStateTypes;
617  for (size_t i = 1; i < load_op->nresults(); i++)
618  {
619  memStateTypes.push_back(ConvertType(*load_op->result(i)));
620  }
621  MlirOp = Builder_->create<::mlir::jlm::Load>(
622  Builder_->getUnknownLoc(),
623  ConvertType(*load_op->result(0)), // ptr
624  GetMemStateRange(load_op->nresults() - 1), // memstate(s)
625  inputs[0], // pointer
626  Builder_->getUI32IntegerAttr(load_op->GetAlignment()), // alignment
627  ::mlir::ValueRange({ std::next(inputs.begin()), inputs.end() }) // inputMemStates
628  );
629  }
630  else if (auto store_op = dynamic_cast<const jlm::llvm::StoreOperation *>(&operation))
631  {
632  MlirOp = Builder_->create<::mlir::jlm::Store>(
633  Builder_->getUnknownLoc(),
634  GetMemStateRange(store_op->nresults()), // memstate(s)
635  inputs[0], // ptr
636  inputs[1], // value
637  Builder_->getUI32IntegerAttr(store_op->GetAlignment()), // alignment
638  ::mlir::ValueRange({ std::next(std::next(inputs.begin())), inputs.end() }) // inputMemStates
639  );
640  }
641  else if (rvsdg::is<jlm::llvm::MemoryStateMergeOperation>(operation))
642  {
643  MlirOp = Builder_->create<::mlir::rvsdg::MemStateMerge>(
644  Builder_->getUnknownLoc(),
645  ConvertType(*node.output(0)->Type()),
646  inputs);
647  }
648  else if (rvsdg::is<jlm::llvm::IOBarrierOperation>(operation))
649  {
650  MlirOp = Builder_->create<::mlir::jlm::IOBarrier>(
651  Builder_->getUnknownLoc(),
652  ConvertType(*node.output(0)->Type()),
653  inputs[0],
654  inputs[1]);
655  }
656  else if (auto op = dynamic_cast<const llvm::GetElementPtrOperation *>(&operation))
657  {
658  MlirOp = Builder_->create<::mlir::LLVM::GEPOp>(
659  Builder_->getUnknownLoc(),
660  ConvertType(*op->result(0)), // resultType
661  ConvertType(op->getPointeeType()), // elementType
662  inputs[0], // basePtr
663  ::mlir::ValueRange({ std::next(inputs.begin()), inputs.end() })); // indices
664  }
665  else if (auto selectOp = dynamic_cast<const llvm::SelectOperation *>(&operation))
666  {
667  assert(selectOp->nresults() == 1);
668  assert(inputs.size() == 3);
669  MlirOp = Builder_->create<::mlir::arith::SelectOp>(
670  Builder_->getUnknownLoc(),
671  ConvertType(*selectOp->result(0)),
672  inputs[0],
673  inputs[1],
674  inputs[2]);
675  }
676  else if (auto matchOp = dynamic_cast<const rvsdg::MatchOperation *>(&operation))
677  {
678  // ** region Create the MLIR mapping vector **
682  ::llvm::SmallVector<::mlir::Attribute> mappingVector;
683  for (auto mapping : *matchOp)
684  {
685  ::mlir::rvsdg::MatchRuleAttr matchRule = ::mlir::rvsdg::MatchRuleAttr::get(
686  Builder_->getContext(),
687  ::llvm::ArrayRef(static_cast<int64_t>(mapping.first)),
688  mapping.second);
689 
690  mappingVector.push_back(matchRule);
691  }
693  mappingVector.push_back(::mlir::rvsdg::MatchRuleAttr::get(
694  Builder_->getContext(),
695  ::llvm::ArrayRef<int64_t>(),
696  matchOp->default_alternative()));
697  // ** endregion Create the MLIR mapping vector **
698 
699  MlirOp = Builder_->create<::mlir::rvsdg::Match>(
700  Builder_->getUnknownLoc(),
701  ConvertType(*node.output(0)->Type()), // Control, ouput type
702  inputs[0], // input
703  ::mlir::ArrayAttr::get(Builder_->getContext(), ::llvm::ArrayRef(mappingVector)));
704  }
705  else if (auto callOp = dynamic_cast<const jlm::llvm::CallOperation *>(&operation))
706  {
707  auto functionType = *callOp->GetFunctionType();
708  ::llvm::SmallVector<::mlir::Type> argumentTypes;
709  for (size_t i = 0; i < functionType.NumArguments(); i++)
710  {
711  argumentTypes.push_back(ConvertType(functionType.ArgumentType(i)));
712  }
713  ::llvm::SmallVector<::mlir::Type> resultTypes;
714  for (size_t i = 0; i < functionType.NumResults(); i++)
715  {
716  resultTypes.push_back(ConvertType(functionType.ResultType(i)));
717  }
718  MlirOp = Builder_->create<::mlir::jlm::Call>(
719  Builder_->getUnknownLoc(),
720  resultTypes,
721  inputs[0], // func ptr
722  ::mlir::ValueRange(
723  { std::next(inputs.begin()), std::prev(std::prev(inputs.end())) }), // args
724  inputs[inputs.size() - 2], // io
725  inputs[inputs.size() - 1] // mem
726  );
727  }
728  else if (
729  auto lambdaStateSplit =
730  dynamic_cast<const llvm::LambdaEntryMemoryStateSplitOperation *>(&operation))
731  {
732  auto memoryNodeIndicesAttr =
733  memoryNodeIndicesToArrayAttr(Builder_->getContext(), lambdaStateSplit->getMemoryNodeIds());
734 
735  ::llvm::SmallVector<::mlir::Type> resultTypes;
736  for (size_t i = 0; i < lambdaStateSplit->nresults(); i++)
737  {
738  resultTypes.push_back(ConvertType(*lambdaStateSplit->result(i).get()));
739  }
740  MlirOp = Builder_->create<::mlir::rvsdg::LambdaEntryMemoryStateSplit>(
741  Builder_->getUnknownLoc(),
742  ::llvm::ArrayRef(resultTypes), // output types
743  inputs[0], // input
744  memoryNodeIndicesAttr);
745  }
746  else if (
747  auto lambdaStateMerge =
748  dynamic_cast<const jlm::llvm::LambdaExitMemoryStateMergeOperation *>(&operation))
749  {
750  auto memoryNodeIndicesAttr =
751  memoryNodeIndicesToArrayAttr(Builder_->getContext(), lambdaStateMerge->getMemoryNodeIds());
752 
753  ::llvm::SmallVector<::mlir::Type> resultTypes;
754  for (size_t i = 0; i < lambdaStateMerge->nresults(); i++)
755  {
756  resultTypes.push_back(ConvertType(*lambdaStateMerge->result(i).get()));
757  }
758  MlirOp = Builder_->create<::mlir::rvsdg::LambdaExitMemoryStateMerge>(
759  Builder_->getUnknownLoc(),
760  ::llvm::ArrayRef(resultTypes), // output type
761  ::mlir::ValueRange(inputs), // inputs
762  memoryNodeIndicesAttr);
763  }
764  else if (
765  auto callStateSplit =
766  dynamic_cast<const jlm::llvm::CallExitMemoryStateSplitOperation *>(&operation))
767  {
768  auto memoryNodeIndicesAttr =
769  memoryNodeIndicesToArrayAttr(Builder_->getContext(), callStateSplit->getMemoryNodeIds());
770 
771  ::llvm::SmallVector<::mlir::Type> resultTypes;
772  for (size_t i = 0; i < callStateSplit->nresults(); i++)
773  {
774  resultTypes.push_back(ConvertType(*callStateSplit->result(i).get()));
775  }
776  MlirOp = Builder_->create<::mlir::rvsdg::CallExitMemoryStateSplit>(
777  Builder_->getUnknownLoc(),
778  ::llvm::ArrayRef(resultTypes), // output types
779  inputs[0], // input
780  memoryNodeIndicesAttr);
781  }
782  else if (
783  auto callStateMerge =
784  dynamic_cast<const jlm::llvm::CallEntryMemoryStateMergeOperation *>(&operation))
785  {
786  auto memoryNodeIndicesAttr =
787  memoryNodeIndicesToArrayAttr(Builder_->getContext(), callStateMerge->getMemoryNodeIds());
788 
789  ::llvm::SmallVector<::mlir::Type> resultTypes;
790  for (size_t i = 0; i < callStateMerge->nresults(); i++)
791  {
792  resultTypes.push_back(ConvertType(*callStateMerge->result(i).get()));
793  }
794  MlirOp = Builder_->create<::mlir::rvsdg::CallEntryMemoryStateMerge>(
795  Builder_->getUnknownLoc(),
796  ::llvm::ArrayRef(resultTypes), // output type
797  ::mlir::ValueRange(inputs), // inputs
798  memoryNodeIndicesAttr);
799  }
800  else if (auto memoryStateJoin = dynamic_cast<const llvm::MemoryStateJoinOperation *>(&operation))
801  {
802  ::mlir::Type resultType = ConvertType(*memoryStateJoin->result(0));
803 
804  MlirOp = Builder_->create<::mlir::rvsdg::MemoryStateJoin>(
805  Builder_->getUnknownLoc(),
806  resultType,
807  ::mlir::ValueRange(inputs));
808  }
809  // ** endregion structural nodes **
810  else
811  {
812  auto message = util::strfmt("Unimplemented simple node: ", operation.debug_string());
813  JLM_UNREACHABLE(message.c_str());
814  }
815 
816  block.push_back(MlirOp);
817  return MlirOp;
818 }
819 
820 ::llvm::SmallVector<::mlir::Type>
822 {
823  ::llvm::SmallVector<::mlir::Type> typeRange;
824  for (size_t i = 0; i < nresults; ++i)
825  {
826  typeRange.push_back(Builder_->getType<::mlir::rvsdg::MemStateEdgeType>());
827  }
828  return typeRange;
829 }
830 
831 ::mlir::Operation *
833  const rvsdg::LambdaNode & lambdaNode,
834  ::mlir::Block & block,
835  const ::llvm::SmallVector<::mlir::Value> & inputs)
836 {
837  // Add function attributes, e.g., the function name and linkage
838  ::llvm::SmallVector<::mlir::NamedAttribute> attributes;
839  auto symbolName = Builder_->getNamedAttr(
840  Builder_->getStringAttr("sym_name"),
841  Builder_->getStringAttr(
842  dynamic_cast<llvm::LlvmLambdaOperation &>(lambdaNode.GetOperation()).name()));
843  attributes.push_back(symbolName);
844  auto linkage = Builder_->getNamedAttr(
845  Builder_->getStringAttr("linkage"),
846  Builder_->getStringAttr(llvm::linkageToString(
847  dynamic_cast<llvm::LlvmLambdaOperation &>(lambdaNode.GetOperation()).linkage())));
848  attributes.push_back(linkage);
849 
850  auto lambda = Builder_->create<::mlir::rvsdg::LambdaNode>(
851  Builder_->getUnknownLoc(),
852  ConvertType(*lambdaNode.output()->Type()),
853  inputs,
854  ::llvm::ArrayRef<::mlir::NamedAttribute>(attributes));
855  block.push_back(lambda);
856 
857  auto & lambdaBlock = lambda.getRegion().emplaceBlock();
858  auto regionResults = ConvertRegion(*lambdaNode.subregion(), lambdaBlock);
859  auto lambdaResult =
860  Builder_->create<::mlir::rvsdg::LambdaResult>(Builder_->getUnknownLoc(), regionResults);
861  lambdaBlock.push_back(lambdaResult);
862 
863  return lambda;
864 }
865 
866 ::mlir::Operation *
868  const rvsdg::GammaNode & gammaNode,
869  ::mlir::Block & block,
870  const ::llvm::SmallVector<::mlir::Value> & inputs)
871 {
872  auto & gammaOp = *util::assertedCast<const rvsdg::GammaOperation>(&gammaNode.GetOperation());
873 
874  ::llvm::SmallVector<::mlir::Type> typeRangeOuput;
875  for (size_t i = 0; i < gammaNode.noutputs(); ++i)
876  {
877  typeRangeOuput.push_back(ConvertType(*gammaNode.output(i)->Type()));
878  }
879 
880  // The predicate is always the first input
881  // Predicate is used to select the region to execute
882  ::mlir::Value predicate = inputs[0];
883 
884  auto gamma = Builder_->create<::mlir::rvsdg::GammaNode>(
885  Builder_->getUnknownLoc(),
886  ::mlir::TypeRange(::llvm::ArrayRef(typeRangeOuput)), // Ouputs types
887  predicate,
888  ::mlir::ValueRange({ std::next(inputs.begin()), inputs.end() }), // Inputs
889  gammaOp.nalternatives() // regionsCount
890  );
891  block.push_back(gamma);
892 
893  for (size_t i = 0; i < gammaOp.nalternatives(); ++i)
894  {
895  auto & gammaBlock = gamma.getRegion(i).emplaceBlock();
896  auto regionResults = ConvertRegion(*gammaNode.subregion(i), gammaBlock);
897  auto gammaResult =
898  Builder_->create<::mlir::rvsdg::GammaResult>(Builder_->getUnknownLoc(), regionResults);
899  gammaBlock.push_back(gammaResult);
900  }
901 
902  return gamma;
903 }
904 
905 ::mlir::Operation *
907  const rvsdg::ThetaNode & thetaNode,
908  ::mlir::Block & block,
909  const ::llvm::SmallVector<::mlir::Value> & inputs)
910 {
911  ::llvm::SmallVector<::mlir::Type> outputTypeRange;
912  for (size_t i = 0; i < thetaNode.noutputs(); ++i)
913  {
914  outputTypeRange.push_back(ConvertType(*thetaNode.output(i)->Type()));
915  }
916 
917  ::llvm::SmallVector<::mlir::NamedAttribute> attributes;
918 
919  auto theta = Builder_->create<::mlir::rvsdg::ThetaNode>(
920  Builder_->getUnknownLoc(),
921  ::mlir::TypeRange(::llvm::ArrayRef(outputTypeRange)),
922  ::mlir::ValueRange(::llvm::ArrayRef(inputs)),
923  attributes);
924 
925  block.push_back(theta);
926  auto & thetaBlock = theta.getRegion().emplaceBlock();
927  auto regionResults = ConvertRegion(*thetaNode.subregion(), thetaBlock);
928  auto results = ::mlir::ValueRange({ std::next(regionResults.begin()), regionResults.end() });
929  auto thetaResult = Builder_->create<::mlir::rvsdg::ThetaResult>(
930  Builder_->getUnknownLoc(),
931  regionResults[0],
932  results);
933  thetaBlock.push_back(thetaResult);
934  return theta;
935 }
936 
937 ::mlir::Operation *
939  const rvsdg::DeltaNode & deltaNode,
940  ::mlir::Block & block,
941  const ::llvm::SmallVector<::mlir::Value> & inputs)
942 {
943  auto op = util::assertedCast<const llvm::DeltaOperation>(&deltaNode.GetOperation());
944  auto delta = Builder_->create<::mlir::rvsdg::DeltaNode>(
945  Builder_->getUnknownLoc(),
946  Builder_->getType<::mlir::LLVM::LLVMPointerType>(),
947  inputs,
948  ::llvm::StringRef(op->name()),
949  ::llvm::StringRef(llvm::linkageToString(op->linkage())),
950  ::llvm::StringRef(op->Section()),
951  op->constant());
952  block.push_back(delta);
953  auto & deltaBlock = delta.getRegion().emplaceBlock();
954  auto regionResults = ConvertRegion(*deltaNode.subregion(), deltaBlock);
955  JLM_ASSERT(regionResults.size() == 1); // Delta nodes have 1 output
956  auto deltaResult =
957  Builder_->create<::mlir::rvsdg::DeltaResult>(Builder_->getUnknownLoc(), regionResults[0]);
958  deltaBlock.push_back(deltaResult);
959  return delta;
960 }
961 
962 ::mlir::FloatType
964 {
965  switch (size)
966  {
968  return Builder_->getF16Type();
970  return Builder_->getF32Type();
972  return Builder_->getF64Type();
974  return Builder_->getF80Type();
976  return Builder_->getF128Type();
977  default:
978  auto message = util::strfmt(
979  "Floating point type conversion not implemented: ",
980  llvm::FloatingPointType(size).debug_string());
981  JLM_UNREACHABLE(message.c_str());
982  }
983 }
984 
985 ::mlir::FunctionType
987 {
988  ::llvm::SmallVector<::mlir::Type> argumentTypes;
989  for (size_t i = 0; i < functionType.NumArguments(); i++)
990  {
991  argumentTypes.push_back(ConvertType(functionType.ArgumentType(i)));
992  }
993  ::llvm::SmallVector<::mlir::Type> resultTypes;
994  for (size_t i = 0; i < functionType.NumResults(); i++)
995  {
996  resultTypes.push_back(ConvertType(functionType.ResultType(i)));
997  }
998  return Builder_->getFunctionType(argumentTypes, resultTypes);
999 }
1000 
1001 ::mlir::Type
1003 {
1004  if (auto bt = dynamic_cast<const rvsdg::BitType *>(&type))
1005  {
1006  return Builder_->getIntegerType(bt->nbits());
1007  }
1008  else if (auto fpt = dynamic_cast<const jlm::llvm::FloatingPointType *>(&type))
1009  {
1010  return ConvertFPType(fpt->size());
1011  }
1012  else if (rvsdg::is<llvm::IOStateType>(type))
1013  {
1014  return Builder_->getType<::mlir::rvsdg::IOStateEdgeType>();
1015  }
1016  else if (rvsdg::is<llvm::MemoryStateType>(type))
1017  {
1018  return Builder_->getType<::mlir::rvsdg::MemStateEdgeType>();
1019  }
1020  else if (auto clt = dynamic_cast<const rvsdg::ControlType *>(&type))
1021  {
1022  return Builder_->getType<::mlir::rvsdg::RVSDG_CTRLType>(clt->nalternatives());
1023  }
1024  else if (rvsdg::is<llvm::PointerType>(type))
1025  {
1026  return Builder_->getType<::mlir::LLVM::LLVMPointerType>();
1027  }
1028  else if (auto arrayType = dynamic_cast<const llvm::ArrayType *>(&type))
1029  {
1030  return Builder_->getType<::mlir::LLVM::LLVMArrayType>(
1031  ConvertType(arrayType->element_type()),
1032  arrayType->nelements());
1033  }
1034  else if (auto functionType = dynamic_cast<const jlm::rvsdg::FunctionType *>(&type))
1035  {
1036  return ConvertFunctionType(*functionType);
1037  }
1038  else if (rvsdg::is<const llvm::VariableArgumentType>(type))
1039  {
1040  return Builder_->getType<::mlir::jlm::VarargListType>();
1041  }
1042  else if (rvsdg::is<const rvsdg::UnitType>(type))
1043  {
1044  return Builder_->getType<::mlir::NoneType>();
1045  }
1046  else if (auto structType = dynamic_cast<const llvm::StructType *>(&type))
1047  {
1048  std::vector<::mlir::Type> elements;
1049  for (size_t i = 0; i < structType->numElements(); i++)
1050  {
1051  elements.push_back(ConvertType(*structType->getElementType(i)));
1052  }
1053 
1054  if (structType->IsLiteral())
1055  {
1056  return ::mlir::LLVM::LLVMStructType::getLiteral(
1057  Builder_->getContext(),
1058  elements,
1059  structType->IsPacked());
1060  }
1061  else
1062  {
1063  auto mlirStructType = ::mlir::LLVM::LLVMStructType::getIdentified(
1064  Builder_->getContext(),
1065  structType->GetName());
1066  if (mlirStructType.isInitialized())
1067  return mlirStructType;
1068  if (mlirStructType.setBody(elements, structType->IsPacked()).failed())
1069  {
1070  throw util::Error("Not able to set the body of struct in the MLIR backend.");
1071  }
1072  return mlirStructType;
1073  }
1074  }
1075  else
1076  {
1077  auto message = util::strfmt("Type conversion not implemented: ", type.debug_string());
1078  JLM_UNREACHABLE(message.c_str());
1079  }
1080 }
1081 
1082 ::mlir::Operation *
1084  const jlm::llvm::IntegerBinaryOperation & operation,
1085  ::llvm::SmallVector<::mlir::Value> inputs)
1086 {
1087  if (rvsdg::is<jlm::llvm::IntegerAddOperation>(operation))
1088  {
1089  return Builder_->create<::mlir::arith::AddIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1090  }
1091  else if (rvsdg::is<jlm::llvm::IntegerSubOperation>(operation))
1092  {
1093  return Builder_->create<::mlir::arith::SubIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1094  }
1095  else if (rvsdg::is<jlm::llvm::IntegerMulOperation>(operation))
1096  {
1097  return Builder_->create<::mlir::arith::MulIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1098  }
1099  else if (rvsdg::is<jlm::llvm::IntegerSDivOperation>(operation))
1100  {
1101  return Builder_->create<::mlir::arith::DivSIOp>(
1102  Builder_->getUnknownLoc(),
1103  inputs[0],
1104  inputs[1]);
1105  }
1106  else if (rvsdg::is<jlm::llvm::IntegerUDivOperation>(operation))
1107  {
1108  return Builder_->create<::mlir::arith::DivUIOp>(
1109  Builder_->getUnknownLoc(),
1110  inputs[0],
1111  inputs[1]);
1112  }
1113  else if (rvsdg::is<jlm::llvm::IntegerSRemOperation>(operation))
1114  {
1115  return Builder_->create<::mlir::arith::RemSIOp>(
1116  Builder_->getUnknownLoc(),
1117  inputs[0],
1118  inputs[1]);
1119  }
1120  else if (rvsdg::is<jlm::llvm::IntegerURemOperation>(operation))
1121  {
1122  return Builder_->create<::mlir::arith::RemUIOp>(
1123  Builder_->getUnknownLoc(),
1124  inputs[0],
1125  inputs[1]);
1126  }
1127  else if (rvsdg::is<jlm::llvm::IntegerAShrOperation>(operation))
1128  {
1129  return Builder_->create<::mlir::LLVM::AShrOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1130  }
1131  else if (rvsdg::is<jlm::llvm::IntegerShlOperation>(operation))
1132  {
1133  return Builder_->create<::mlir::LLVM::ShlOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1134  }
1135  else if (rvsdg::is<jlm::llvm::IntegerLShrOperation>(operation))
1136  {
1137  return Builder_->create<::mlir::LLVM::LShrOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1138  }
1139  else if (rvsdg::is<jlm::llvm::IntegerAndOperation>(operation))
1140  {
1141  return Builder_->create<::mlir::arith::AndIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1142  }
1143  else if (rvsdg::is<jlm::llvm::IntegerOrOperation>(operation))
1144  {
1145  return Builder_->create<::mlir::arith::OrIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1146  }
1147  else if (rvsdg::is<jlm::llvm::IntegerXorOperation>(operation))
1148  {
1149  return Builder_->create<::mlir::arith::XOrIOp>(Builder_->getUnknownLoc(), inputs[0], inputs[1]);
1150  }
1151  else if (rvsdg::is<jlm::llvm::IntegerEqOperation>(operation))
1152  {
1153  return Builder_->create<::mlir::arith::CmpIOp>(
1154  Builder_->getUnknownLoc(),
1155  ::mlir::arith::CmpIPredicate::eq,
1156  inputs[0],
1157  inputs[1]);
1158  }
1159  else if (rvsdg::is<jlm::llvm::IntegerNeOperation>(operation))
1160  {
1161  return Builder_->create<::mlir::arith::CmpIOp>(
1162  Builder_->getUnknownLoc(),
1163  ::mlir::arith::CmpIPredicate::ne,
1164  inputs[0],
1165  inputs[1]);
1166  }
1167  else if (rvsdg::is<jlm::llvm::IntegerSgeOperation>(operation))
1168  {
1169  return Builder_->create<::mlir::arith::CmpIOp>(
1170  Builder_->getUnknownLoc(),
1171  ::mlir::arith::CmpIPredicate::sge,
1172  inputs[0],
1173  inputs[1]);
1174  }
1175  else if (rvsdg::is<jlm::llvm::IntegerSgtOperation>(operation))
1176  {
1177  return Builder_->create<::mlir::arith::CmpIOp>(
1178  Builder_->getUnknownLoc(),
1179  ::mlir::arith::CmpIPredicate::sgt,
1180  inputs[0],
1181  inputs[1]);
1182  }
1183  else if (rvsdg::is<jlm::llvm::IntegerSleOperation>(operation))
1184  {
1185  return Builder_->create<::mlir::arith::CmpIOp>(
1186  Builder_->getUnknownLoc(),
1187  ::mlir::arith::CmpIPredicate::sle,
1188  inputs[0],
1189  inputs[1]);
1190  }
1191  else if (rvsdg::is<jlm::llvm::IntegerSltOperation>(operation))
1192  {
1193  return Builder_->create<::mlir::arith::CmpIOp>(
1194  Builder_->getUnknownLoc(),
1195  ::mlir::arith::CmpIPredicate::slt,
1196  inputs[0],
1197  inputs[1]);
1198  }
1199  else if (rvsdg::is<jlm::llvm::IntegerUgeOperation>(operation))
1200  {
1201  return Builder_->create<::mlir::arith::CmpIOp>(
1202  Builder_->getUnknownLoc(),
1203  ::mlir::arith::CmpIPredicate::uge,
1204  inputs[0],
1205  inputs[1]);
1206  }
1207  else if (rvsdg::is<jlm::llvm::IntegerUgtOperation>(operation))
1208  {
1209  return Builder_->create<::mlir::arith::CmpIOp>(
1210  Builder_->getUnknownLoc(),
1211  ::mlir::arith::CmpIPredicate::ugt,
1212  inputs[0],
1213  inputs[1]);
1214  }
1215  else if (rvsdg::is<jlm::llvm::IntegerUleOperation>(operation))
1216  {
1217  return Builder_->create<::mlir::arith::CmpIOp>(
1218  Builder_->getUnknownLoc(),
1219  ::mlir::arith::CmpIPredicate::ule,
1220  inputs[0],
1221  inputs[1]);
1222  }
1223  else if (rvsdg::is<jlm::llvm::IntegerUltOperation>(operation))
1224  {
1225  return Builder_->create<::mlir::arith::CmpIOp>(
1226  Builder_->getUnknownLoc(),
1227  ::mlir::arith::CmpIPredicate::ult,
1228  inputs[0],
1229  inputs[1]);
1230  }
1231  else
1232  {
1233  auto message =
1234  util::strfmt("Unimplemented integer binary operation: ", operation.debug_string());
1235  JLM_UNREACHABLE(message.c_str());
1236  }
1237 }
1238 
1239 } // namespace jlm::mlir
Call operation class.
Definition: call.hpp:251
ConstantPointerNullOperation class.
Definition: operators.hpp:432
const llvm::fpop & fpop() const noexcept
Definition: operators.hpp:1254
const fpcmp & cmp() const noexcept
Definition: operators.hpp:992
Lambda operation.
Definition: lambda.hpp:30
const jlm::llvm::Linkage & linkage() const noexcept
Definition: lambda.hpp:48
const std::string & name() const noexcept
Definition: lambda.hpp:42
ICmpPredicate predicate() const noexcept
Definition: operators.hpp:755
StructType class.
Definition: types.hpp:184
UndefValueOperation class.
Definition: operators.hpp:1023
::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)
Delta node.
Definition: delta.hpp:129
rvsdg::Region * subregion() const noexcept
Definition: delta.hpp:234
const DeltaOperation & GetOperation() const noexcept override
Definition: delta.cpp:71
Function type class.
size_t NumArguments() const noexcept
size_t NumResults() const noexcept
const jlm::rvsdg::Type & ArgumentType(size_t index) 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
Lambda node.
Definition: lambda.hpp:83
rvsdg::Region * subregion() const noexcept
Definition: lambda.hpp:138
rvsdg::Output * output() const noexcept
Definition: lambda.cpp:176
LambdaOperation & GetOperation() const noexcept override
Definition: lambda.cpp:51
virtual std::string DebugString() const =0
NodeInput * input(size_t index) const noexcept
Definition: node.hpp:615
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
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:366
virtual std::string debug_string() const
Definition: node.cpp:168
std::string debug_string() const override
Definition: region.cpp:99
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
RegionResult * result(size_t index) const noexcept
Definition: region.hpp:471
size_t nresults() const noexcept
Definition: region.hpp:465
RegionArgument * argument(size_t index) const noexcept
Definition: region.hpp:437
size_t narguments() const noexcept
Definition: region.hpp:431
Graph & Rvsdg() noexcept
Definition: RvsdgModule.hpp:57
const SimpleOperation & GetOperation() const noexcept override
Definition: simple-node.cpp:48
NodeOutput * output(size_t index) const noexcept
Definition: simple-node.hpp:88
StructuralOutput * output(size_t index) const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
rvsdg::Region * subregion() const noexcept
Definition: theta.hpp:79
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)
static std::string strfmt(Args... args)
Definition: strfmt.hpp:35