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