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