Jlm
MlirToJlmConverter.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 
23 #include <mlir/Parser/Parser.h>
24 #include <mlir/Transforms/TopologicalSortUtils.h>
25 
26 namespace jlm::mlir
27 {
28 
29 std::unique_ptr<llvm::LlvmRvsdgModule>
31 {
32  auto config = ::mlir::ParserConfig(Context_.get());
33  std::unique_ptr<::mlir::Block> block = std::make_unique<::mlir::Block>();
34  auto result = ::mlir::parseSourceFile(filePath.to_str(), block.get(), config);
35  if (result.failed())
36  {
37  JLM_ASSERT("Parsing MLIR input file failed.");
38  }
39  return ConvertMlir(block);
40 }
41 
42 std::unique_ptr<llvm::LlvmRvsdgModule>
43 MlirToJlmConverter::ConvertMlir(std::unique_ptr<::mlir::Block> & block)
44 {
45  auto & topNode = block->front();
46  if (auto module = ::mlir::dyn_cast<::mlir::ModuleOp>(topNode))
47  {
48  auto & newTopNode = module.getBodyRegion().front().front();
49  auto omegaNode = ::mlir::dyn_cast<::mlir::rvsdg::OmegaNode>(newTopNode);
50  if (!omegaNode)
51  {
52  JLM_UNREACHABLE("frontend : Top node in module op is not an OmegaNode.");
53  }
54  return ConvertOmega(omegaNode);
55  }
56  auto omegaNode = ::mlir::dyn_cast<::mlir::rvsdg::OmegaNode>(topNode);
57  if (!omegaNode)
58  {
59  JLM_UNREACHABLE("frontend : Top node is not an OmegaNode.");
60  }
61  return ConvertOmega(omegaNode);
62 }
63 
64 std::unique_ptr<llvm::LlvmRvsdgModule>
65 MlirToJlmConverter::ConvertOmega(::mlir::rvsdg::OmegaNode & omegaNode)
66 {
67  auto rvsdgModule =
68  llvm::LlvmRvsdgModule::Create(util::FilePath(""), std::string(), std::string());
69  auto & graph = rvsdgModule->Rvsdg();
70  auto & root = graph.GetRootRegion();
71  ConvertRegion(omegaNode.getRegion(), root);
72 
73  return rvsdgModule;
74 }
75 
76 ::llvm::SmallVector<jlm::rvsdg::Output *>
77 MlirToJlmConverter::ConvertRegion(::mlir::Region & region, rvsdg::Region & rvsdgRegion)
78 {
79  // MLIR use blocks as the innermost "container"
80  // In the RVSDG Dialect a region should contain one and only one block
81  JLM_ASSERT(region.getBlocks().size() == 1);
82  return ConvertBlock(region.front(), rvsdgRegion);
83 }
84 
85 ::llvm::SmallVector<jlm::rvsdg::Output *>
87  ::mlir::Operation & mlirOp,
88  const std::unordered_map<void *, rvsdg::Output *> & outputMap)
89 {
90  ::llvm::SmallVector<jlm::rvsdg::Output *> inputs;
91  for (::mlir::Value operand : mlirOp.getOperands())
92  {
93  auto key = operand.getAsOpaquePointer();
94  JLM_ASSERT(outputMap.find(key) != outputMap.end());
95  inputs.push_back(outputMap.at(key));
96  }
97  return inputs;
98 }
99 
100 ::llvm::SmallVector<jlm::rvsdg::Output *>
101 MlirToJlmConverter::ConvertBlock(::mlir::Block & block, rvsdg::Region & rvsdgRegion)
102 {
103  ::mlir::sortTopologically(&block);
104 
105  // Create an RVSDG node for each MLIR operation and store the mapping from
106  // MLIR values to RVSDG outputs in a hash map for easy lookup
107  std::unordered_map<void *, rvsdg::Output *> outputMap;
108 
109  for (size_t i = 0; i < block.getNumArguments(); i++)
110  {
111  auto arg = block.getArgument(i);
112  auto key = arg.getAsOpaquePointer();
113  outputMap[key] = rvsdgRegion.argument(i);
114  }
115 
116  for (auto & mlirOp : block.getOperations())
117  {
118  if (auto argument = ::mlir::dyn_cast<::mlir::rvsdg::OmegaArgument>(mlirOp))
119  {
120  auto valueType = argument.getValueType();
121  auto importedType = argument.getImportedValue().getType();
122  auto jlmValueType = ConvertType(valueType);
123  auto jlmImportedType = ConvertType(importedType);
124 
125  auto & jlmArgument = jlm::llvm::LlvmGraphImport::create(
126  *rvsdgRegion.graph(),
127  jlmValueType,
128  jlmImportedType,
129  argument.getNameAttr().cast<::mlir::StringAttr>().str(),
130  llvm::linkageFromString(argument.getLinkageAttr().cast<::mlir::StringAttr>().str()),
131  llvm::CallingConvention::Default, // FIXME: Currently not supported in MLIR dialect
132  false, // FIXME: Currently not supported in MLIR dialect
133  1); // FIXME: Currently not supported in MLIR dialect
134 
135  auto key = argument.getResult().getAsOpaquePointer();
136  outputMap[key] = &jlmArgument;
137  }
138  else
139  {
140  ::llvm::SmallVector<jlm::rvsdg::Output *> inputs = GetConvertedInputs(mlirOp, outputMap);
141 
142  auto outputs = ConvertOperation(mlirOp, rvsdgRegion, inputs);
143  JLM_ASSERT(outputs.size() == mlirOp.getNumResults());
144  for (size_t i = 0; i < mlirOp.getNumResults(); i++)
145  {
146  auto result = mlirOp.getResult(i);
147  auto key = result.getAsOpaquePointer();
148  outputMap[key] = outputs[i];
149  }
150  }
151  }
152 
153  // The results of the region/block are encoded in the terminator operation
154  ::mlir::Operation * terminator = block.getTerminator();
155 
156  return GetConvertedInputs(*terminator, outputMap);
157 }
158 
159 rvsdg::Node *
161  ::mlir::arith::CmpIOp & CompOp,
162  const ::llvm::SmallVector<rvsdg::Output *> & inputs,
163  size_t nbits)
164 {
165  if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::eq)
166  {
167  return &rvsdg::CreateOpNode<jlm::llvm::IntegerEqOperation>({ inputs[0], inputs[1] }, nbits);
168  }
169  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::ne)
170  {
171  return &rvsdg::CreateOpNode<jlm::llvm::IntegerNeOperation>({ inputs[0], inputs[1] }, nbits);
172  }
173  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::sge)
174  {
175  return &rvsdg::CreateOpNode<jlm::llvm::IntegerSgeOperation>({ inputs[0], inputs[1] }, nbits);
176  }
177  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::sgt)
178  {
179  return &rvsdg::CreateOpNode<jlm::llvm::IntegerSgtOperation>({ inputs[0], inputs[1] }, nbits);
180  }
181  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::sle)
182  {
183  return &rvsdg::CreateOpNode<jlm::llvm::IntegerSleOperation>({ inputs[0], inputs[1] }, nbits);
184  }
185  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::slt)
186  {
187  return &rvsdg::CreateOpNode<jlm::llvm::IntegerSltOperation>({ inputs[0], inputs[1] }, nbits);
188  }
189  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::uge)
190  {
191  return &rvsdg::CreateOpNode<jlm::llvm::IntegerUgeOperation>({ inputs[0], inputs[1] }, nbits);
192  }
193  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::ugt)
194  {
195  return &rvsdg::CreateOpNode<jlm::llvm::IntegerUgtOperation>({ inputs[0], inputs[1] }, nbits);
196  }
197  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::ule)
198  {
199  return &rvsdg::CreateOpNode<jlm::llvm::IntegerUleOperation>({ inputs[0], inputs[1] }, nbits);
200  }
201  else if (CompOp.getPredicate() == ::mlir::arith::CmpIPredicate::ult)
202  {
203  return &rvsdg::CreateOpNode<jlm::llvm::IntegerUltOperation>({ inputs[0], inputs[1] }, nbits);
204  }
205  else
206  {
207  JLM_UNREACHABLE("frontend : Unknown comparison predicate.");
208  }
209 }
210 
211 rvsdg::Node *
213  ::mlir::LLVM::ICmpOp & operation,
214  rvsdg::Region & rvsdgRegion,
215  const ::llvm::SmallVector<rvsdg::Output *> & inputs)
216 {
217  if (operation.getPredicate() == ::mlir::LLVM::ICmpPredicate::eq)
218  {
219  auto newOp = std::make_unique<llvm::PtrCmpOperation>(
223  rvsdgRegion,
224  std::move(newOp),
225  std::vector<jlm::rvsdg::Output *>(inputs.begin(), inputs.end()));
226  }
227  else if (operation.getPredicate() == ::mlir::LLVM::ICmpPredicate::ne)
228  {
229  auto newOp = std::make_unique<llvm::PtrCmpOperation>(
233  rvsdgRegion,
234  std::move(newOp),
235  std::vector<jlm::rvsdg::Output *>(inputs.begin(), inputs.end()));
236  }
237  else if (operation.getPredicate() == ::mlir::LLVM::ICmpPredicate::sge)
238  {
239  auto newOp = std::make_unique<llvm::PtrCmpOperation>(
243  rvsdgRegion,
244  std::move(newOp),
245  std::vector<jlm::rvsdg::Output *>(inputs.begin(), inputs.end()));
246  }
247  else if (operation.getPredicate() == ::mlir::LLVM::ICmpPredicate::sgt)
248  {
249  auto newOp = std::make_unique<llvm::PtrCmpOperation>(
253  rvsdgRegion,
254  std::move(newOp),
255  std::vector<jlm::rvsdg::Output *>(inputs.begin(), inputs.end()));
256  }
257  else if (operation.getPredicate() == ::mlir::LLVM::ICmpPredicate::sle)
258  {
259  auto newOp = std::make_unique<llvm::PtrCmpOperation>(
263  rvsdgRegion,
264  std::move(newOp),
265  std::vector<jlm::rvsdg::Output *>(inputs.begin(), inputs.end()));
266  }
267  else if (operation.getPredicate() == ::mlir::LLVM::ICmpPredicate::slt)
268  {
269  auto newOp = std::make_unique<llvm::PtrCmpOperation>(
273  rvsdgRegion,
274  std::move(newOp),
275  std::vector<jlm::rvsdg::Output *>(inputs.begin(), inputs.end()));
276  }
277  else
278  {
279  JLM_UNREACHABLE("MLIR frontend: Unknown pointer compare operation");
280  }
281 }
282 
283 rvsdg::Node *
285  const ::mlir::Operation & mlirOperation,
286  const ::llvm::SmallVector<rvsdg::Output *> & inputs)
287 {
288  if (inputs.size() != 2)
289  return nullptr;
290  auto op = llvm::fpop::add;
291  auto size = llvm::fpsize::half;
292  if (auto castedOp = ::mlir::dyn_cast<::mlir::arith::AddFOp>(&mlirOperation))
293  {
294  op = llvm::fpop::add;
295  size = ConvertFPSize(castedOp.getType().cast<::mlir::FloatType>().getWidth());
296  }
297  else if (auto castedOp = ::mlir::dyn_cast<::mlir::arith::SubFOp>(&mlirOperation))
298  {
299  op = llvm::fpop::sub;
300  size = ConvertFPSize(castedOp.getType().cast<::mlir::FloatType>().getWidth());
301  }
302  else if (auto castedOp = ::mlir::dyn_cast<::mlir::arith::MulFOp>(&mlirOperation))
303  {
304  op = llvm::fpop::mul;
305  size = ConvertFPSize(castedOp.getType().cast<::mlir::FloatType>().getWidth());
306  }
307  else if (auto castedOp = ::mlir::dyn_cast<::mlir::arith::DivFOp>(&mlirOperation))
308  {
309  op = llvm::fpop::div;
310  size = ConvertFPSize(castedOp.getType().cast<::mlir::FloatType>().getWidth());
311  }
312  else if (auto castedOp = ::mlir::dyn_cast<::mlir::arith::RemFOp>(&mlirOperation))
313  {
314  op = llvm::fpop::mod;
315  size = ConvertFPSize(castedOp.getType().cast<::mlir::FloatType>().getWidth());
316  }
317  else
318  {
319  return nullptr;
320  }
321  return &rvsdg::CreateOpNode<llvm::FBinaryOperation>({ inputs[0], inputs[1] }, op, size);
322 }
323 
325 MlirToJlmConverter::TryConvertFPCMP(const ::mlir::arith::CmpFPredicate & op)
326 {
327  const auto & map = GetFpCmpPredicateMap();
328  return map.LookupKey(op);
329 }
330 
331 rvsdg::Node *
333  ::mlir::Operation & mlirOperation,
334  const ::llvm::SmallVector<rvsdg::Output *> & inputs)
335 {
336  if (inputs.size() != 2 || mlirOperation.getNumResults() != 1)
337  return nullptr;
338 
339  auto type = mlirOperation.getResult(0).getType();
340 
341  size_t width = 0;
342  if (type.isa<::mlir::IntegerType>())
343  {
344  auto integerType = type.cast<::mlir::IntegerType>();
345  width = integerType.getWidth();
346  }
347  else if (type.isIndex())
348  {
350  }
351  else
352  {
353  return nullptr;
354  }
355 
356  if (::mlir::isa<::mlir::arith::AddIOp>(mlirOperation))
357  {
358  return &rvsdg::CreateOpNode<jlm::llvm::IntegerAddOperation>({ inputs[0], inputs[1] }, width);
359  }
360  else if (::mlir::isa<::mlir::arith::SubIOp>(mlirOperation))
361  {
362  return &rvsdg::CreateOpNode<jlm::llvm::IntegerSubOperation>({ inputs[0], inputs[1] }, width);
363  }
364  else if (::mlir::isa<::mlir::arith::MulIOp>(mlirOperation))
365  {
366  return &rvsdg::CreateOpNode<jlm::llvm::IntegerMulOperation>({ inputs[0], inputs[1] }, width);
367  }
368  else if (::mlir::isa<::mlir::arith::DivSIOp>(mlirOperation))
369  {
370  return &rvsdg::CreateOpNode<jlm::llvm::IntegerSDivOperation>({ inputs[0], inputs[1] }, width);
371  }
372  else if (::mlir::isa<::mlir::arith::DivUIOp>(mlirOperation))
373  {
374  return &rvsdg::CreateOpNode<jlm::llvm::IntegerUDivOperation>({ inputs[0], inputs[1] }, width);
375  }
376  else if (::mlir::isa<::mlir::arith::RemSIOp>(mlirOperation))
377  {
378  return &rvsdg::CreateOpNode<jlm::llvm::IntegerSRemOperation>({ inputs[0], inputs[1] }, width);
379  }
380  else if (::mlir::isa<::mlir::arith::RemUIOp>(mlirOperation))
381  {
382  return &rvsdg::CreateOpNode<jlm::llvm::IntegerURemOperation>({ inputs[0], inputs[1] }, width);
383  }
384  else if (::mlir::isa<::mlir::LLVM::ShlOp>(mlirOperation))
385  {
386  return &rvsdg::CreateOpNode<jlm::llvm::IntegerShlOperation>({ inputs[0], inputs[1] }, width);
387  }
388  else if (::mlir::isa<::mlir::LLVM::AShrOp>(mlirOperation))
389  {
390  return &rvsdg::CreateOpNode<jlm::llvm::IntegerAShrOperation>({ inputs[0], inputs[1] }, width);
391  }
392  else if (::mlir::isa<::mlir::LLVM::LShrOp>(mlirOperation))
393  {
394  return &rvsdg::CreateOpNode<jlm::llvm::IntegerLShrOperation>({ inputs[0], inputs[1] }, width);
395  }
396  else if (::mlir::isa<::mlir::arith::AndIOp>(mlirOperation))
397  {
398  return &rvsdg::CreateOpNode<jlm::llvm::IntegerAndOperation>({ inputs[0], inputs[1] }, width);
399  }
400  else if (::mlir::isa<::mlir::arith::OrIOp>(mlirOperation))
401  {
402  return &rvsdg::CreateOpNode<jlm::llvm::IntegerOrOperation>({ inputs[0], inputs[1] }, width);
403  }
404  else if (::mlir::isa<::mlir::arith::XOrIOp>(mlirOperation))
405  {
406  return &rvsdg::CreateOpNode<jlm::llvm::IntegerXorOperation>({ inputs[0], inputs[1] }, width);
407  }
408  else
409  {
410  return nullptr;
411  }
412 }
413 
414 static std::vector<llvm::MemoryNodeId>
415 arrayAttrToMemoryNodeIds(::mlir::ArrayAttr arrayAttr)
416 {
417  std::vector<llvm::MemoryNodeId> memoryNodeIds;
418  for (auto memoryNodeId : arrayAttr)
419  {
420  memoryNodeIds.push_back(memoryNodeId.cast<::mlir::IntegerAttr>().getInt());
421  }
422  return memoryNodeIds;
423 }
424 
425 std::vector<jlm::rvsdg::Output *>
427  ::mlir::Operation & mlirOperation,
428  rvsdg::Region & rvsdgRegion,
429  const ::llvm::SmallVector<rvsdg::Output *> & inputs)
430 {
431 
432  // ** region Arithmetic Integer Operation **
433  auto convertedBitBinaryNode = ConvertBitBinaryNode(mlirOperation, inputs);
434  // If the operation was converted it means it has been casted to a bit binary operation
435  if (convertedBitBinaryNode)
436  {
437  return rvsdg::outputs(convertedBitBinaryNode);
438  }
439  // ** endregion Arithmetic Integer Operation **
440 
441  // ** region Arithmetic Float Operation **
442  auto convertedFloatBinaryNode = ConvertFPBinaryNode(mlirOperation, inputs);
443  // If the operation was converted it means it has been casted to a fp binary operation
444  if (convertedFloatBinaryNode)
445  {
446  return rvsdg::outputs(convertedFloatBinaryNode);
447  }
448 
449  if (::mlir::isa<::mlir::LLVM::FMulAddOp>(&mlirOperation))
450  {
451  JLM_ASSERT(inputs.size() == 3);
452  return rvsdg::outputs(
453  &llvm::FMulAddIntrinsicOperation::CreateNode(*inputs[0], *inputs[1], *inputs[2]));
454  }
455  // ** endregion Arithmetic Float Operation **
456 
457  if (auto castedOp = ::mlir::dyn_cast<::mlir::arith::ExtUIOp>(&mlirOperation))
458  {
459  auto st = std::dynamic_pointer_cast<const rvsdg::BitType>(inputs[0]->Type());
460  if (!st)
461  JLM_UNREACHABLE("Expected bitstring type for ExtUIOp operation.");
462  ::mlir::Type type = castedOp.getType();
463  return { &llvm::ZExtOperation::Create(*(inputs[0]), ConvertType(type)) };
464  }
465  else if (auto castedOp = ::mlir::dyn_cast<::mlir::arith::ExtSIOp>(&mlirOperation))
466  {
467  auto outputType = castedOp.getOut().getType();
468  auto convertedOutputType = ConvertType(outputType);
469  if (!::mlir::isa<::mlir::IntegerType>(castedOp.getType()))
470  JLM_UNREACHABLE("Expected IntegerType for ExtSIOp operation output.");
472  castedOp.getType().cast<::mlir::IntegerType>().getWidth(),
473  inputs[0]) };
474  }
475  else if (auto sitofpOp = ::mlir::dyn_cast<::mlir::arith::SIToFPOp>(&mlirOperation))
476  {
477  auto st = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(inputs[0]->Type());
478  if (!st)
479  JLM_UNREACHABLE("Expected bits type for SIToFPOp operation.");
480 
481  auto mlirOutputType = sitofpOp.getType();
482  auto rt = ConvertType(mlirOutputType);
483 
484  return rvsdg::outputs(&rvsdg::CreateOpNode<llvm::SIToFPOperation>(
485  std::vector<jlm::rvsdg::Output *>(inputs.begin(), inputs.end()),
486  std::move(st),
487  std::move(rt)));
488  }
489 
490  else if (::mlir::isa<::mlir::rvsdg::OmegaNode>(&mlirOperation))
491  {
492  // Omega doesn't have a corresponding RVSDG node, so we return an empty vector
493  return {};
494  }
495  else if (::mlir::isa<::mlir::rvsdg::LambdaNode>(&mlirOperation))
496  {
497  return rvsdg::outputs(ConvertLambda(mlirOperation, rvsdgRegion, inputs));
498  }
499  else if (auto callOp = ::mlir::dyn_cast<::mlir::jlm::Call>(&mlirOperation))
500  {
501  std::vector<std::shared_ptr<const rvsdg::Type>> argumentTypes;
502  for (auto arg : callOp.getArgs())
503  {
504  auto type = arg.getType();
505  argumentTypes.push_back(ConvertType(type));
506  }
507  argumentTypes.push_back(llvm::IOStateType::Create());
508  argumentTypes.push_back(llvm::MemoryStateType::Create());
509 
510  std::vector<std::shared_ptr<const rvsdg::Type>> resultTypes;
511  for (auto res : callOp.getResults())
512  {
513  auto type = res.getType();
514  resultTypes.push_back(ConvertType(type));
515  }
516 
517  if (inputs.size() != 1 + argumentTypes.size())
518  throw std::runtime_error("Function call should take target and parameters as input");
519  const auto functionType = rvsdg::FunctionType::Create(argumentTypes, resultTypes);
520 
521  const auto target = inputs[0];
522  const auto arguments = std::vector(std::next(inputs.begin()), inputs.end());
524  target,
525  std::move(functionType),
526  llvm::CallingConvention::Default, // FIXME: MLIR dialect does not support calling
527  // conventions
528  llvm::AttributeList::createEmptyList(), // FIXME: MLIR dialect does not support attributes
529  arguments);
530  }
531  else if (auto constant = ::mlir::dyn_cast<::mlir::arith::ConstantIntOp>(&mlirOperation))
532  {
533  auto type = constant.getType();
534  JLM_ASSERT(type.getTypeID() == ::mlir::IntegerType::getTypeID());
535  auto integerType = ::mlir::cast<::mlir::IntegerType>(type);
536 
538  rvsdgRegion,
539  integerType.getWidth(),
540  constant.value()));
541  }
542  else if (auto constant = ::mlir::dyn_cast<::mlir::arith::ConstantFloatOp>(&mlirOperation))
543  {
544  auto type = constant.getType();
545  if (!::mlir::isa<::mlir::FloatType>(type))
546  JLM_UNREACHABLE("Expected FloatType for ConstantFloatOp operation.");
547  auto floatType = ::mlir::cast<::mlir::FloatType>(type);
548 
549  auto size = ConvertFPSize(floatType.getWidth());
550  return rvsdg::outputs(
551  &rvsdg::CreateOpNode<llvm::ConstantFP>(rvsdgRegion, size, constant.value()));
552  }
553 
554  // RVSDG does not have an index type. Indices are therefore converted to integers.
555 
556  else if (auto constant = ::mlir::dyn_cast<::mlir::arith::ConstantIndexOp>(&mlirOperation))
557  {
558  auto type = constant.getType();
559  JLM_ASSERT(type.getTypeID() == ::mlir::IndexType::getTypeID());
560 
562  rvsdgRegion,
564  constant.value()));
565  }
566  else if (auto indexCast = ::mlir::dyn_cast<::mlir::arith::IndexCastOp>(&mlirOperation))
567  {
568  auto outputType = indexCast.getResult().getType();
569  auto inputType = indexCast.getIn().getType();
570  unsigned inputBits = inputType.getIntOrFloatBitWidth();
571  unsigned outputBits = outputType.getIntOrFloatBitWidth();
572 
573  if (inputType.isIndex())
574  {
575  if (outputBits == MlirToJlmConverter::GetIndexBitWidth())
576  {
577  // Nothing is needed to be done so we simply pass on the inputs
578  return { inputs.begin(), inputs.end() };
579  }
580  else if (outputBits > MlirToJlmConverter::GetIndexBitWidth())
581  {
582  return { llvm::SExtOperation::create(outputBits, inputs[0]) };
583  }
584  else
585  {
586  return { llvm::TruncOperation::create(outputBits, inputs[0]) };
587  }
588  }
589  else
590  {
591  if (inputBits == MlirToJlmConverter::GetIndexBitWidth())
592  {
593  // Nothing to be done as indices are not supported and of default width
594  return { inputs.begin(), inputs.end() };
595  }
596  else if (inputBits > MlirToJlmConverter::GetIndexBitWidth())
597  {
599  }
600  else
601  {
602  return { &llvm::ZExtOperation::Create(
603  *(inputs[0]),
605  }
606  }
607  }
608 
609  else if (auto negOp = ::mlir::dyn_cast<::mlir::arith::NegFOp>(&mlirOperation))
610  {
611  auto type = negOp.getResult().getType();
612  auto floatType = ::mlir::cast<::mlir::FloatType>(type);
613 
614  llvm::fpsize size = ConvertFPSize(floatType.getWidth());
615  return rvsdg::outputs(&rvsdg::CreateOpNode<jlm::llvm::FNegOperation>({ inputs[0] }, size));
616  }
617 
618  else if (auto extOp = ::mlir::dyn_cast<::mlir::arith::ExtFOp>(&mlirOperation))
619  {
620  auto type = extOp.getResult().getType();
621  auto floatType = ::mlir::cast<::mlir::FloatType>(type);
622 
623  llvm::fpsize size = ConvertFPSize(floatType.getWidth());
624  return rvsdg::outputs(&rvsdg::CreateOpNode<jlm::llvm::FPExtOperation>(
625  { inputs[0] },
626  inputs[0]->Type(),
628  }
629 
630  else if (auto truncOp = ::mlir::dyn_cast<::mlir::arith::TruncIOp>(&mlirOperation))
631  {
632  auto type = truncOp.getResult().getType();
633  auto intType = ::mlir::cast<::mlir::IntegerType>(type);
634  return { llvm::TruncOperation::create(intType.getIntOrFloatBitWidth(), inputs[0]) };
635  }
636  else if (auto constant = ::mlir::dyn_cast<::mlir::arith::ConstantFloatOp>(&mlirOperation))
637  {
638  auto type = constant.getType();
639  auto floatType = ::mlir::cast<::mlir::FloatType>(type);
640 
641  llvm::fpsize size = ConvertFPSize(floatType.getWidth());
642  return rvsdg::outputs(&rvsdg::CreateOpNode<jlm::llvm::ConstantFP>({}, size, constant.value()));
643  }
644 
645  // Binary Integer Comparision operations
646  else if (auto ComOp = ::mlir::dyn_cast<::mlir::arith::CmpIOp>(&mlirOperation))
647  {
648  auto type = ComOp.getOperandTypes()[0];
649  if (type.isa<::mlir::IntegerType>())
650  {
651  auto integerType = ::mlir::cast<::mlir::IntegerType>(type);
652  return rvsdg::outputs(ConvertCmpIOp(ComOp, inputs, integerType.getWidth()));
653  }
654  else if (type.isIndex())
655  {
657  }
658  else
659  {
660  JLM_UNREACHABLE("Wrong type given to CmpIOp.");
661  }
662  }
663 
664  else if (auto ComOp = ::mlir::dyn_cast<::mlir::arith::CmpFOp>(&mlirOperation))
665  {
666  auto type = ComOp.getOperandTypes()[0];
667  auto floatType = ::mlir::cast<::mlir::FloatType>(type);
668  return rvsdg::outputs(&rvsdg::CreateOpNode<llvm::FCmpOperation>(
669  std::vector(inputs.begin(), inputs.end()),
670  TryConvertFPCMP(ComOp.getPredicate()),
671  ConvertFPSize(floatType.getWidth())));
672  }
673 
674  // Pointer compare is mapped to LLVM::ICmpOp
675  else if (auto iComOp = ::mlir::dyn_cast<::mlir::LLVM::ICmpOp>(&mlirOperation))
676  {
677  return rvsdg::outputs(ConvertICmpOp(iComOp, rvsdgRegion, inputs));
678  }
679 
680  else if (auto UndefOp = ::mlir::dyn_cast<::mlir::jlm::Undef>(&mlirOperation))
681  {
682  auto type = UndefOp.getResult().getType();
683  auto jlmType = ConvertType(type);
684  return { jlm::llvm::UndefValueOperation::Create(rvsdgRegion, jlmType) };
685  }
686 
687  else if (auto ArrayOp = ::mlir::dyn_cast<::mlir::jlm::ConstantDataArray>(&mlirOperation))
688  {
689  return { llvm::ConstantDataArray::Create(std::vector(inputs.begin(), inputs.end())) };
690  }
691 
692  else if (auto ZeroOp = ::mlir::dyn_cast<::mlir::LLVM::ZeroOp>(&mlirOperation))
693  {
694  auto type = ZeroOp.getType();
695  // NULL pointers are a special case of ZeroOp
696  if (::mlir::isa<::mlir::LLVM::LLVMPointerType>(type))
697  {
698  return { llvm::ConstantPointerNullOperation::Create(&rvsdgRegion, ConvertType(type)) };
699  }
700  return { llvm::ConstantAggregateZeroOperation::Create(rvsdgRegion, ConvertType(type)) };
701  }
702 
703  else if (auto VarArgOp = ::mlir::dyn_cast<::mlir::jlm::CreateVarArgList>(&mlirOperation))
704  {
706  rvsdgRegion,
707  std::vector(inputs.begin(), inputs.end())) };
708  }
709 
710  // Memory operations
711 
712  else if (auto FreeOp = ::mlir::dyn_cast<::mlir::jlm::Free>(&mlirOperation))
713  {
714  return rvsdg::outputs(&rvsdg::CreateOpNode<llvm::FreeOperation>(
715  std::vector(inputs.begin(), inputs.end()),
716  inputs.size() - 2));
717  }
718 
719  else if (auto AllocaOp = ::mlir::dyn_cast<::mlir::jlm::Alloca>(&mlirOperation))
720  {
721  auto outputType = AllocaOp.getValueType();
722 
723  auto jlmType = ConvertType(outputType);
724  if (jlmType->Kind() != rvsdg::TypeKind::Value)
725  JLM_UNREACHABLE("Expected ValueType for AllocaOp operation.");
726 
727  if (!rvsdg::is<const rvsdg::BitType>(inputs[0]->Type()))
728  JLM_UNREACHABLE("Expected BitType for AllocaOp operation.");
729 
730  auto jlmBitType = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(inputs[0]->Type());
731 
732  return rvsdg::outputs(&rvsdg::CreateOpNode<llvm::AllocaOperation>(
733  std::vector(inputs.begin(), inputs.end()),
734  jlmType,
735  jlmBitType,
736  AllocaOp.getAlignment()));
737  }
738  else if (auto MemstateMergeOp = ::mlir::dyn_cast<::mlir::rvsdg::MemStateMerge>(&mlirOperation))
739  {
740  auto operands = std::vector(inputs.begin(), inputs.end());
742  }
743  else if (
744  auto LambdaEntryMemstateSplitOp =
745  ::mlir::dyn_cast<::mlir::rvsdg::LambdaEntryMemoryStateSplit>(&mlirOperation))
746  {
747  auto memoryNodeIds =
748  arrayAttrToMemoryNodeIds(LambdaEntryMemstateSplitOp.getMemoryStateIndices());
749 
750  auto operands = std::vector(inputs.begin(), inputs.end());
752  *operands.front(),
753  std::move(memoryNodeIds)));
754  }
755  if (auto LambdaExitMemstateMergeOp =
756  ::mlir::dyn_cast<::mlir::rvsdg::LambdaExitMemoryStateMerge>(&mlirOperation))
757  {
758  auto memoryNodeIds =
759  arrayAttrToMemoryNodeIds(LambdaExitMemstateMergeOp.getMemoryStateIndices());
760 
761  auto operands = std::vector(inputs.begin(), inputs.end());
763  rvsdgRegion,
764  operands,
765  std::move(memoryNodeIds)));
766  }
767  else if (
768  auto CallEntryMemstateMergeOp =
769  ::mlir::dyn_cast<::mlir::rvsdg::CallEntryMemoryStateMerge>(&mlirOperation))
770  {
771  auto memoryNodeIds = arrayAttrToMemoryNodeIds(CallEntryMemstateMergeOp.getMemoryStateIndices());
772 
773  auto operands = std::vector(inputs.begin(), inputs.end());
775  rvsdgRegion,
776  operands,
777  std::move(memoryNodeIds)));
778  }
779  else if (
780  auto CallExitMemstateSplitOp =
781  ::mlir::dyn_cast<::mlir::rvsdg::CallExitMemoryStateSplit>(&mlirOperation))
782  {
783  auto memoryNodeIds = arrayAttrToMemoryNodeIds(CallExitMemstateSplitOp.getMemoryStateIndices());
784 
785  auto operands = std::vector(inputs.begin(), inputs.end());
787  *operands.front(),
788  std::move(memoryNodeIds)));
789  }
790  else if (::mlir::isa<::mlir::rvsdg::MemoryStateJoin>(&mlirOperation))
791  {
792  std::vector operands(inputs.begin(), inputs.end());
794  }
795  else if (auto IOBarrierOp = ::mlir::dyn_cast<::mlir::jlm::IOBarrier>(&mlirOperation))
796  {
797  auto type = IOBarrierOp.getResult().getType();
798  return rvsdg::outputs(&rvsdg::CreateOpNode<llvm::IOBarrierOperation>(
799  std::vector(inputs.begin(), inputs.end()),
800  ConvertType(type)));
801  }
802  else if (auto MallocOp = ::mlir::dyn_cast<::mlir::jlm::Malloc>(&mlirOperation))
803  {
804  return outputs(&llvm::MallocOperation::createNode(*inputs[0], *inputs[1]));
805  }
806  else if (auto StoreOp = ::mlir::dyn_cast<::mlir::jlm::Store>(&mlirOperation))
807  {
808  auto address = inputs[0];
809  auto value = inputs[1];
810  auto memoryStateInputs = std::vector(std::next(inputs.begin(), 2), inputs.end());
812  *address,
813  *value,
814  memoryStateInputs,
815  StoreOp.getAlignment()));
816  }
817  else if (auto LoadOp = ::mlir::dyn_cast<::mlir::jlm::Load>(&mlirOperation))
818  {
819  auto address = inputs[0];
820  auto memoryStateInputs = std::vector(std::next(inputs.begin()), inputs.end());
821  auto outputType = LoadOp.getOutput().getType();
822  auto jlmType = ConvertType(outputType);
823  if (jlmType->Kind() != rvsdg::TypeKind::Value)
824  JLM_UNREACHABLE("Expected ValueType for LoadOp operation output.");
826  *address,
827  memoryStateInputs,
828  jlmType,
829  LoadOp.getAlignment()));
830  }
831  else if (auto GepOp = ::mlir::dyn_cast<::mlir::LLVM::GEPOp>(&mlirOperation))
832  {
833  auto elemType = GepOp.getElemType();
834  auto pointeeType = ConvertType(elemType);
835  if (pointeeType->Kind() != rvsdg::TypeKind::Value)
836  JLM_UNREACHABLE("Expected ValueType for GepOp operation pointee.");
837 
838  std::vector<rvsdg::Output *> indices;
839  // The first input is the base pointer
840  size_t dynamicInput = 1;
841  for (int32_t constant : GepOp.getRawConstantIndices())
842  {
843  // If magic number then its a dynamic index
844  if (constant == ::mlir::LLVM::GEPOp::kDynamicIndex)
845  {
846  indices.push_back(inputs[dynamicInput++]);
847  }
848  else
849  {
850  // Constant indices are not part of the inputs to a GEPOp,
851  // but they are required as explicit nodes in RVSDG
852  indices.push_back(
853  jlm::llvm::IntegerConstantOperation::Create(rvsdgRegion, 32, constant).output(0));
854  }
855  }
856 
857  return { llvm::GetElementPtrOperation::create(inputs[0], indices, pointeeType) };
858  }
859  // * region Structural nodes **
860  else if (auto MlirCtrlConst = ::mlir::dyn_cast<::mlir::rvsdg::ConstantCtrl>(&mlirOperation))
861  {
862  JLM_ASSERT(::mlir::isa<::mlir::rvsdg::RVSDG_CTRLType>(MlirCtrlConst.getType()));
864  rvsdgRegion,
865  ::mlir::cast<::mlir::rvsdg::RVSDG_CTRLType>(MlirCtrlConst.getType()).getNumOptions(),
866  MlirCtrlConst.getValue()) };
867  }
868  else if (auto mlirGammaNode = ::mlir::dyn_cast<::mlir::rvsdg::GammaNode>(&mlirOperation))
869  {
870  auto rvsdgGammaNode = rvsdg::GammaNode::create(
871  inputs[0], // predicate
872  mlirGammaNode.getNumRegions() // nalternatives
873  );
874 
875  // Add inputs to the gamma node and to all it's subregions
876  for (size_t i = 1; i < inputs.size(); i++)
877  {
878  rvsdgGammaNode->AddEntryVar(inputs[i]);
879  }
880 
881  ::llvm::SmallVector<::llvm::SmallVector<jlm::rvsdg::Output *>> regionResults;
882  for (size_t i = 0; i < mlirGammaNode.getNumRegions(); i++)
883  {
884  regionResults.push_back(
885  ConvertRegion(mlirGammaNode.getRegion(i), *rvsdgGammaNode->subregion(i)));
886  }
887 
888  // Connect the outputs
890  for (size_t exitvarIndex = 0; exitvarIndex < regionResults[0].size(); exitvarIndex++)
891  {
892  std::vector<rvsdg::Output *> exitvars;
893  for (size_t regionIndex = 0; regionIndex < mlirGammaNode.getNumRegions(); regionIndex++)
894  {
895  JLM_ASSERT(regionResults[regionIndex].size() == regionResults[0].size());
896  exitvars.push_back(regionResults[regionIndex][exitvarIndex]);
897  }
898  rvsdgGammaNode->AddExitVar(exitvars);
899  }
900 
901  return rvsdg::outputs(rvsdgGammaNode);
902  }
903  else if (auto mlirThetaNode = ::mlir::dyn_cast<::mlir::rvsdg::ThetaNode>(&mlirOperation))
904  {
905  auto rvsdgThetaNode = rvsdg::ThetaNode::create(&rvsdgRegion);
906 
907  // Add loop vars to the theta node
908  for (size_t i = 0; i < inputs.size(); i++)
909  {
910  rvsdgThetaNode->AddLoopVar(inputs[i]);
911  }
912 
913  auto regionResults = ConvertRegion(mlirThetaNode.getRegion(), *rvsdgThetaNode->subregion());
914 
915  rvsdgThetaNode->set_predicate(regionResults[0]);
916 
917  auto loopvars = rvsdgThetaNode->GetLoopVars();
918  for (size_t i = 1; i < regionResults.size(); i++)
919  {
920  loopvars[i - 1].post->divert_to(regionResults[i]);
921  }
922 
923  return rvsdg::outputs(rvsdgThetaNode);
924  }
925  else if (auto mlirDeltaNode = ::mlir::dyn_cast<::mlir::rvsdg::DeltaNode>(&mlirOperation))
926  {
927  auto & deltaRegion = mlirDeltaNode.getRegion();
928  auto & deltaBlock = deltaRegion.front();
929  auto terminator = deltaBlock.getTerminator();
930 
931  auto mlirOutputType = terminator->getOperand(0).getType();
932  auto outputType = ConvertType(mlirOutputType);
933  auto linakgeString = mlirDeltaNode.getLinkage().str();
934  auto rvsdgDeltaNode = rvsdg::DeltaNode::Create(
935  &rvsdgRegion,
937  outputType,
938  mlirDeltaNode.getName().str(),
939  ConvertLinkage(linakgeString),
940  mlirDeltaNode.getSection().str(),
941  mlirDeltaNode.getConstant(),
942  4)); // FIXME: the MLIR delta node does not support the alignment attribute
943 
944  auto outputVector = ConvertRegion(mlirDeltaNode.getRegion(), *rvsdgDeltaNode->subregion());
945 
946  if (outputVector.size() != 1)
947  JLM_UNREACHABLE("Expected 1 output for Delta operation.");
948 
949  rvsdgDeltaNode->finalize(outputVector[0]);
950 
951  return rvsdg::outputs(rvsdgDeltaNode);
952  }
953  else if (auto mlirMatch = ::mlir::dyn_cast<::mlir::rvsdg::Match>(&mlirOperation))
954  {
955  std::unordered_map<uint64_t, uint64_t> mapping;
956  uint64_t defaultAlternative = 0;
957  for (auto & attr : mlirMatch.getMapping())
958  {
959  JLM_ASSERT(attr.isa<::mlir::rvsdg::MatchRuleAttr>());
960  auto matchRuleAttr = attr.cast<::mlir::rvsdg::MatchRuleAttr>();
961  if (matchRuleAttr.isDefault())
962  {
963  defaultAlternative = matchRuleAttr.getIndex();
964  continue;
965  }
966  // In our Mlir implementation, an index is associated with a single value
967  mapping[matchRuleAttr.getValues().front()] = matchRuleAttr.getIndex();
968  }
969 
971  *(inputs[0]), // predicate
972  mapping, // mapping
973  defaultAlternative, // defaultAlternative
974  mlirMatch.getMapping().size() // numAlternatives
975  ) };
976  }
977  else if (auto selectOp = ::mlir::dyn_cast<::mlir::arith::SelectOp>(&mlirOperation))
978  {
979  auto type = selectOp.getType();
980  auto jlmType = ConvertType(type);
981  return rvsdg::outputs(&rvsdg::CreateOpNode<jlm::llvm::SelectOperation>(
982  std::vector(inputs.begin(), inputs.end()),
983  jlmType));
984  }
985  else if (auto mlirOmegaResult = ::mlir::dyn_cast<::mlir::rvsdg::OmegaResult>(&mlirOperation))
986  {
987  for (auto input : inputs)
988  {
989  auto origin = rvsdg::TryGetOwnerNode<rvsdg::Node>(*input);
990  if (auto lambda = dynamic_cast<rvsdg::LambdaNode *>(origin))
991  {
992  auto op = dynamic_cast<llvm::LlvmLambdaOperation *>(&lambda->GetOperation());
993  jlm::rvsdg::GraphExport::Create(*input, op->name());
994  }
995  else if (auto delta = dynamic_cast<rvsdg::DeltaNode *>(origin))
996  {
997  auto op = util::assertedCast<const llvm::DeltaOperation>(&delta->GetOperation());
998  jlm::rvsdg::GraphExport::Create(*input, op->name());
999  }
1000  }
1001  return {};
1002  }
1003  // ** endregion Structural nodes **
1004 
1005  else if (
1006  ::mlir::isa<::mlir::rvsdg::LambdaResult>(&mlirOperation)
1007  || ::mlir::isa<::mlir::rvsdg::GammaResult>(&mlirOperation)
1008  || ::mlir::isa<::mlir::rvsdg::ThetaResult>(&mlirOperation)
1009  || ::mlir::isa<::mlir::rvsdg::DeltaResult>(&mlirOperation)
1010  // This is a terminating operation that doesn't have a corresponding RVSDG node
1011  || ::mlir::isa<::mlir::rvsdg::OmegaArgument>(&mlirOperation)) // Handled at the top level
1012  {
1013  return {};
1014  }
1015  else
1016  {
1017  mlirOperation.dump();
1018  auto message = util::strfmt(
1019  "Operation not implemented: ",
1020  mlirOperation.getName().getStringRef().str(),
1021  "\n");
1022  JLM_UNREACHABLE(message.c_str());
1023  }
1024 }
1025 
1028 {
1029  switch (size)
1030  {
1031  case 16:
1032  return llvm::fpsize::half;
1033  case 32:
1034  return llvm::fpsize::flt;
1035  case 64:
1036  return llvm::fpsize::dbl;
1037  case 80:
1038  return llvm::fpsize::x86fp80;
1039  case 128:
1040  return llvm::fpsize::fp128;
1041  default:
1042  auto message = util::strfmt("Unsupported floating point size: ", size, "\n");
1043  JLM_UNREACHABLE(message.c_str());
1044  break;
1045  }
1046 }
1047 
1049 MlirToJlmConverter::ConvertLinkage(std::string stringValue)
1050 {
1051  if (!stringValue.compare("external_linkage"))
1052  {
1054  }
1055  else if (!stringValue.compare("available_externally_linkage"))
1056  {
1058  }
1059  else if (!stringValue.compare("link_once_any_linkage"))
1060  {
1062  }
1063  else if (!stringValue.compare("link_once_odr_linkage"))
1064  {
1066  }
1067  else if (!stringValue.compare("weak_any_linkage"))
1068  {
1070  }
1071  else if (!stringValue.compare("weak_odr_linkage"))
1072  {
1074  }
1075  else if (!stringValue.compare("appending_linkage"))
1076  {
1078  }
1079  else if (!stringValue.compare("internal_linkage"))
1080  {
1082  }
1083  else if (!stringValue.compare("private_linkage"))
1084  {
1086  }
1087  else if (!stringValue.compare("external_weak_linkage"))
1088  {
1090  }
1091  else if (!stringValue.compare("common_linkage"))
1092  {
1094  }
1095  auto message = util::strfmt("Unsupported linkage: ", stringValue, "\n");
1096  JLM_UNREACHABLE(message.c_str());
1097 }
1098 
1101  ::mlir::Operation & mlirOperation,
1102  rvsdg::Region & rvsdgRegion,
1103  const ::llvm::SmallVector<rvsdg::Output *> & inputs)
1104 {
1105  // Get the name of the function
1106  auto functionNameAttribute = mlirOperation.getAttr(::llvm::StringRef("sym_name"));
1107  JLM_ASSERT(functionNameAttribute != nullptr);
1108  auto functionName = ::mlir::cast<::mlir::StringAttr>(functionNameAttribute);
1109 
1110  auto lambdaOp = ::mlir::dyn_cast<::mlir::rvsdg::LambdaNode>(&mlirOperation);
1111  auto & lambdaRegion = lambdaOp.getRegion();
1112  auto numNonContextVars = lambdaRegion.getNumArguments() - lambdaOp.getNumOperands();
1113  auto & lambdaBlock = lambdaRegion.front();
1114  auto lamdbaTerminator = lambdaBlock.getTerminator();
1115 
1116  // Create the RVSDG function signature
1117  std::vector<std::shared_ptr<const rvsdg::Type>> argumentTypes;
1118  for (size_t argumentIndex = 0; argumentIndex < numNonContextVars; argumentIndex++)
1119  {
1120  auto type = lambdaRegion.getArgument(argumentIndex).getType();
1121  argumentTypes.push_back(ConvertType(type));
1122  }
1123  std::vector<std::shared_ptr<const rvsdg::Type>> resultTypes;
1124  for (auto returnType : lamdbaTerminator->getOperandTypes())
1125  {
1126  resultTypes.push_back(ConvertType(returnType));
1127  }
1128  auto functionType = rvsdg::FunctionType::Create(std::move(argumentTypes), std::move(resultTypes));
1129 
1130  // FIXME
1131  // The linkage should be part of the MLIR attributes so it can be extracted here
1132  auto rvsdgLambda = rvsdg::LambdaNode::Create(
1133  rvsdgRegion,
1135  functionType,
1136  functionName.getValue().str(),
1138 
1139  for (auto input : inputs)
1140  {
1141  rvsdgLambda->AddContextVar(*input);
1142  }
1143 
1144  auto jlmLambdaRegion = rvsdgLambda->subregion();
1145  auto regionResults = ConvertRegion(lambdaRegion, *jlmLambdaRegion);
1146 
1147  rvsdgLambda->finalize(std::vector<rvsdg::Output *>(regionResults.begin(), regionResults.end()));
1148 
1149  return rvsdgLambda;
1150 }
1151 
1152 std::shared_ptr<const rvsdg::Type>
1153 MlirToJlmConverter::ConvertType(const ::mlir::Type & type)
1154 {
1155  if (auto ctrlType = ::mlir::dyn_cast<::mlir::rvsdg::RVSDG_CTRLType>(type))
1156  {
1157  return rvsdg::ControlType::Create(ctrlType.getNumOptions());
1158  }
1159  else if (auto intType = ::mlir::dyn_cast<::mlir::IntegerType>(type))
1160  {
1161  return rvsdg::BitType::Create(intType.getWidth());
1162  }
1163  else if (::mlir::isa<::mlir::Float16Type>(type))
1164  {
1166  }
1167  else if (::mlir::isa<::mlir::Float32Type>(type))
1168  {
1170  }
1171  else if (::mlir::isa<::mlir::Float64Type>(type))
1172  {
1174  }
1175  else if (::mlir::isa<::mlir::Float80Type>(type))
1176  {
1178  }
1179  else if (::mlir::isa<::mlir::Float128Type>(type))
1180  {
1182  }
1183  else if (::mlir::isa<::mlir::rvsdg::MemStateEdgeType>(type))
1184  {
1186  }
1187  else if (::mlir::isa<::mlir::rvsdg::IOStateEdgeType>(type))
1188  {
1189  return llvm::IOStateType::Create();
1190  }
1191  else if (::mlir::isa<::mlir::LLVM::LLVMPointerType>(type))
1192  {
1193  return llvm::PointerType::Create();
1194  }
1195  else if (::mlir::isa<::mlir::jlm::VarargListType>(type))
1196  {
1198  }
1199  else if (auto arrayType = ::mlir::dyn_cast<::mlir::LLVM::LLVMArrayType>(type))
1200  {
1201  auto mlirElementType = arrayType.getElementType();
1202  std::shared_ptr<const rvsdg::Type> elementType = ConvertType(mlirElementType);
1203  return llvm::ArrayType::Create(elementType, arrayType.getNumElements());
1204  }
1205  else if (auto functionType = ::mlir::dyn_cast<::mlir::FunctionType>(type))
1206  {
1207  std::vector<std::shared_ptr<const rvsdg::Type>> argumentTypes;
1208  for (auto argumentType : functionType.getInputs())
1209  {
1210  argumentTypes.push_back(ConvertType(argumentType));
1211  }
1212  std::vector<std::shared_ptr<const rvsdg::Type>> resultTypes;
1213  for (auto resultType : functionType.getResults())
1214  {
1215  resultTypes.push_back(ConvertType(resultType));
1216  }
1217  return rvsdg::FunctionType::Create(argumentTypes, resultTypes);
1218  }
1219  else if (type.isIndex())
1220  {
1221  // RVSDG does not support indices, which are modeled as integers
1223  }
1224  else if (auto structType = ::mlir::dyn_cast<::mlir::LLVM::LLVMStructType>(type))
1225  {
1226  if (StructTypeMap_.HasKey(&structType))
1227  {
1228  return StructTypeMap_.LookupKey(&structType);
1229  }
1230 
1231  std::vector<std::shared_ptr<const rvsdg::Type>> types;
1232  for (auto element : structType.getBody())
1233  {
1234  types.push_back(ConvertType(element));
1235  }
1236 
1237  std::shared_ptr<const llvm::StructType> jlmStructType;
1238  if (structType.isIdentified())
1239  {
1241  structType.getName().str(),
1242  types,
1243  structType.isPacked());
1244  }
1245  else
1246  {
1247  jlmStructType = jlm::llvm::StructType::CreateLiteral(types, structType.isPacked());
1248  }
1249 
1250  StructTypeMap_.Insert(&structType, jlmStructType);
1251  return jlmStructType;
1252  }
1253  else
1254  {
1255  type.dump();
1256  JLM_UNREACHABLE("Type conversion not implemented\n");
1257  }
1258 }
1259 
1260 } // jlm::mlirrvsdg
static std::shared_ptr< const ArrayType > Create(std::shared_ptr< const Type > type, size_t nelements)
Definition: types.hpp:98
static AttributeList createEmptyList()
Definition: attribute.hpp:427
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands, std::vector< MemoryNodeId > memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, std::vector< MemoryNodeId > memoryNodeIds)
static std::vector< rvsdg::Output * > Create(rvsdg::Output *function, std::shared_ptr< const rvsdg::FunctionType > functionType, const std::vector< rvsdg::Output * > &arguments)
Definition: call.hpp:464
static jlm::rvsdg::Output * Create(rvsdg::Region &region, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1984
static jlm::rvsdg::Output * Create(const std::vector< jlm::rvsdg::Output * > &elements)
Definition: operators.hpp:670
static std::unique_ptr< llvm::ThreeAddressCode > Create(std::shared_ptr< const rvsdg::Type > type)
Definition: operators.hpp:456
static std::unique_ptr< DeltaOperation > Create(std::shared_ptr< const rvsdg::Type > type, const std::string &name, const Linkage &linkage, std::string section, bool constant, const size_t alignment)
Definition: delta.hpp:84
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &multiplier, rvsdg::Output &multiplicand, rvsdg::Output &summand)
static std::shared_ptr< const FloatingPointType > Create(fpsize size)
Definition: types.cpp:117
static rvsdg::Output * create(rvsdg::Output *baseAddress, const std::vector< rvsdg::Output * > &indices, std::shared_ptr< const rvsdg::Type > pointeeType)
static std::shared_ptr< const IOStateType > Create()
Definition: types.cpp:343
static rvsdg::Node & Create(rvsdg::Region &region, IntegerValueRepresentation representation)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, std::vector< MemoryNodeId > memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands, const std::vector< MemoryNodeId > &memoryNodeIds)
static LlvmGraphImport & create(rvsdg::Graph &graph, std::shared_ptr< const rvsdg::Type > valueType, std::shared_ptr< const rvsdg::Type > importedType, std::string name, Linkage linkage, CallingConvention callingConvention, const bool isConstant, const size_t alignment)
Lambda operation.
Definition: lambda.hpp:30
static std::unique_ptr< LlvmLambdaOperation > Create(std::shared_ptr< const jlm::rvsdg::FunctionType > type, std::string name, const jlm::llvm::Linkage &linkage, jlm::llvm::CallingConvention callingConvention, jlm::llvm::AttributeSet attributes)
Definition: lambda.hpp:84
static std::unique_ptr< LlvmRvsdgModule > Create(const util::FilePath &sourceFileName, const std::string &targetTriple, const std::string &dataLayout)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, std::unique_ptr< LoadNonVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
Definition: Load.hpp:466
static rvsdg::SimpleNode & createNode(rvsdg::Output &size, rvsdg::Output &ioState)
Definition: operators.hpp:2493
static rvsdg::SimpleNode & CreateNode(const std::vector< rvsdg::Output * > &operands)
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static std::shared_ptr< const MemoryStateType > Create()
Definition: types.cpp:379
static std::shared_ptr< const PointerType > Create()
Definition: types.cpp:45
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const rvsdg::Type > &type)
Definition: sext.hpp:75
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &address, rvsdg::Output &value, const std::vector< rvsdg::Output * > &memoryStates, size_t alignment)
Definition: Store.hpp:323
static std::shared_ptr< const StructType > CreateIdentified(const std::string &name, std::vector< std::shared_ptr< const Type >> types, bool isPacked)
Definition: types.hpp:307
static std::shared_ptr< const StructType > CreateLiteral(std::vector< std::shared_ptr< const Type >> types, bool isPacked)
Definition: types.hpp:334
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1745
static jlm::rvsdg::Output * Create(rvsdg::Region &region, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1055
static std::shared_ptr< const VariableArgumentType > Create()
Definition: types.cpp:180
static rvsdg::Output * Create(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands)
Definition: operators.hpp:1531
static rvsdg::Output & Create(rvsdg::Output &operand, const std::shared_ptr< const rvsdg::Type > &resultType)
Definition: operators.hpp:853
static ::llvm::SmallVector< jlm::rvsdg::Output * > GetConvertedInputs(::mlir::Operation &mlirOp, const std::unordered_map< void *, rvsdg::Output * > &outputMap)
std::unique_ptr<::mlir::MLIRContext > Context_
std::vector< jlm::rvsdg::Output * > ConvertOperation(::mlir::Operation &mlirOperation, rvsdg::Region &rvsdgRegion, const ::llvm::SmallVector< rvsdg::Output * > &inputs)
rvsdg::Node * ConvertFPBinaryNode(const ::mlir::Operation &mlirOperation, const ::llvm::SmallVector< rvsdg::Output * > &inputs)
rvsdg::Node * ConvertICmpOp(::mlir::LLVM::ICmpOp &operation, rvsdg::Region &rvsdgRegion, const ::llvm::SmallVector< rvsdg::Output * > &inputs)
rvsdg::Node * ConvertLambda(::mlir::Operation &mlirLambda, rvsdg::Region &rvsdgRegion, const ::llvm::SmallVector< rvsdg::Output * > &inputs)
llvm::fpsize ConvertFPSize(unsigned int size)
llvm::Linkage ConvertLinkage(std::string stringValue)
util::BijectiveMap<::mlir::LLVM::LLVMStructType *, std::shared_ptr< const llvm::StructType > > StructTypeMap_
std::unique_ptr< llvm::LlvmRvsdgModule > ReadAndConvertMlir(const util::FilePath &filePath)
jlm::llvm::fpcmp TryConvertFPCMP(const ::mlir::arith::CmpFPredicate &op)
rvsdg::Node * ConvertCmpIOp(::mlir::arith::CmpIOp &CompOp, const ::llvm::SmallVector< rvsdg::Output * > &inputs, size_t nbits)
::llvm::SmallVector< jlm::rvsdg::Output * > ConvertBlock(::mlir::Block &block, rvsdg::Region &rvsdgRegion)
std::unique_ptr< llvm::LlvmRvsdgModule > ConvertOmega(::mlir::rvsdg::OmegaNode &omegaNode)
::llvm::SmallVector< jlm::rvsdg::Output * > ConvertRegion(::mlir::Region &region, rvsdg::Region &rvsdgRegion)
std::shared_ptr< const rvsdg::Type > ConvertType(const ::mlir::Type &type)
std::unique_ptr< llvm::LlvmRvsdgModule > ConvertMlir(std::unique_ptr<::mlir::Block > &block)
rvsdg::Node * ConvertBitBinaryNode(::mlir::Operation &mlirOperation, const ::llvm::SmallVector< rvsdg::Output * > &inputs)
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
static Output & create(Region &region, ControlValueRepresentation value)
Definition: control.hpp:122
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
Definition: control.cpp:50
Delta node.
Definition: delta.hpp:129
static DeltaNode * Create(rvsdg::Region *parent, std::unique_ptr< DeltaOperation > op)
Definition: delta.hpp:313
static std::shared_ptr< const FunctionType > Create(std::vector< std::shared_ptr< const jlm::rvsdg::Type >> argumentTypes, std::vector< std::shared_ptr< const jlm::rvsdg::Type >> resultTypes)
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
Definition: gamma.hpp:161
static GraphExport & Create(Output &origin, std::string name)
Definition: graph.cpp:62
Lambda node.
Definition: lambda.hpp:83
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition: lambda.cpp:140
static Output * Create(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
Definition: control.hpp:242
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
Graph * graph() const noexcept
Definition: region.hpp:363
RegionArgument * argument(size_t index) const noexcept
Definition: region.hpp:437
static SimpleNode & Create(Region &region, std::unique_ptr< Operation > operation, const std::vector< rvsdg::Output * > &operands)
Definition: simple-node.hpp:49
static ThetaNode * create(rvsdg::Region *parent)
Definition: theta.hpp:73
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
Linkage linkageFromString(const std::string_view stringValue)
Definition: Linkage.cpp:42
const util::BijectiveMap<::mlir::arith::CmpFPredicate, llvm::fpcmp > & GetFpCmpPredicateMap()
static std::vector< llvm::MemoryNodeId > arrayAttrToMemoryNodeIds(::mlir::ArrayAttr arrayAttr)
@ Value
Designate a value type.
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition: node.hpp:1058
static std::string strfmt(Args... args)
Definition: strfmt.hpp:35