Jlm
JlmToMlirToJlmTests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2024 Halvor Linder Henriksen <halvorlinder@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #include <gtest/gtest.h>
7 
18 
19 TEST(JlmToMlirToJlmTests, TestUndef)
20 {
21  using namespace jlm::llvm;
22  using namespace mlir::rvsdg;
23 
24  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
25  auto graph = &rvsdgModule->Rvsdg();
26 
27  {
28  // Create an undef operation
29  std::cout << "Undef Operation" << std::endl;
30  UndefValueOperation::Create(graph->GetRootRegion(), jlm::rvsdg::BitType::Create(32));
31 
32  // Convert the RVSDG to MLIR
33  std::cout << "Convert to MLIR" << std::endl;
35  auto omega = mlirgen.ConvertModule(*rvsdgModule);
36 
37  std::cout << "Checking blocks and operations count" << std::endl;
38  auto & omegaRegion = omega.getRegion();
39  EXPECT_EQ(omegaRegion.getBlocks().size(), 1);
40  auto & omegaBlock = omegaRegion.front();
41  // 1 undef + omegaResult
42  EXPECT_EQ(omegaBlock.getOperations().size(), 2);
43  EXPECT_TRUE(mlir::isa<mlir::jlm::Undef>(omegaBlock.front()));
44  auto mlirUndefOp = mlir::dyn_cast<::mlir::jlm::Undef>(&omegaBlock.front());
45  mlirUndefOp.dump();
46 
47  // Convert the MLIR to RVSDG and check the result
48  std::cout << "Converting MLIR to RVSDG" << std::endl;
49  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
50  rootBlock->push_back(omega);
51  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
52  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
53 
54  {
55  using namespace jlm::llvm;
56 
57  EXPECT_EQ(region->numNodes(), 1);
58 
59  // Get the undef op
60  auto convertedUndef =
61  dynamic_cast<const UndefValueOperation *>(&region->Nodes().begin()->GetOperation());
62 
63  EXPECT_NE(convertedUndef, nullptr);
64 
65  auto outputType = convertedUndef->result(0);
66  EXPECT_TRUE(jlm::rvsdg::is<const jlm::rvsdg::BitType>(outputType));
67  EXPECT_EQ(std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(outputType)->nbits(), 32);
68  }
69  }
70 }
71 
72 TEST(JlmToMlirToJlmTests, TestAlloca)
73 {
74  using namespace jlm::llvm;
75  using namespace mlir::rvsdg;
76 
77  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
78  auto graph = &rvsdgModule->Rvsdg();
79 
80  {
81  // Create a bits node for alloc size
82  std::cout << "Bit Constanr" << std::endl;
83  auto bits = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 32, 1 });
84 
85  // Create alloca node
86  std::cout << "Alloca Operation" << std::endl;
87  jlm::rvsdg::CreateOpNode<AllocaOperation>(
88  { bits },
91  4);
92 
93  // Convert the RVSDG to MLIR
94  std::cout << "Convert to MLIR" << std::endl;
96  auto omega = mlirgen.ConvertModule(*rvsdgModule);
97 
98  std::cout << "Checking blocks and operations count" << std::endl;
99  auto & omegaRegion = omega.getRegion();
100  EXPECT_EQ(omegaRegion.getBlocks().size(), 1);
101  auto & omegaBlock = omegaRegion.front();
102 
103  // Bit-contant + alloca + omegaResult
104  EXPECT_EQ(omegaBlock.getOperations().size(), 3);
105 
106  bool foundAlloca = false;
107  for (auto & op : omegaBlock)
108  {
109  if (mlir::isa<mlir::jlm::Alloca>(op))
110  {
111  auto mlirAllocaOp = mlir::cast<mlir::jlm::Alloca>(op);
112  EXPECT_EQ(mlirAllocaOp.getAlignment(), 4);
113  EXPECT_EQ(mlirAllocaOp.getNumResults(), 2);
114 
115  auto valueType = mlir::cast<mlir::IntegerType>(mlirAllocaOp.getValueType());
116  EXPECT_NE(valueType, nullptr);
117  EXPECT_EQ(valueType.getWidth(), 64);
118  foundAlloca = true;
119  }
120  }
121  EXPECT_TRUE(foundAlloca);
122 
123  // // Convert the MLIR to RVSDG and check the result
124  std::cout << "Converting MLIR to RVSDG" << std::endl;
125  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
126  rootBlock->push_back(omega);
127  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
128  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
129 
130  {
131  using namespace jlm::llvm;
132 
133  EXPECT_EQ(region->numNodes(), 2);
134 
135  bool foundAlloca = false;
136  for (auto & node : region->Nodes())
137  {
138  if (auto allocaOp = dynamic_cast<const AllocaOperation *>(&node.GetOperation()))
139  {
140  EXPECT_EQ(allocaOp->alignment(), 4);
141 
142  EXPECT_TRUE(jlm::rvsdg::is<jlm::rvsdg::BitType>(allocaOp->allocatedType()));
143  auto valueBitType =
144  dynamic_cast<const jlm::rvsdg::BitType *>(allocaOp->allocatedType().get());
145  EXPECT_EQ(valueBitType->nbits(), 64);
146 
147  EXPECT_EQ(allocaOp->narguments(), 1);
148 
149  EXPECT_TRUE(jlm::rvsdg::is<jlm::rvsdg::BitType>(allocaOp->argument(0)));
150  auto inputBitType =
151  dynamic_cast<const jlm::rvsdg::BitType *>(allocaOp->argument(0).get());
152  EXPECT_EQ(inputBitType->nbits(), 32);
153 
154  EXPECT_EQ(allocaOp->nresults(), 2);
155 
156  EXPECT_TRUE(jlm::rvsdg::is<PointerType>(allocaOp->result(0)));
157  EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::MemoryStateType>(allocaOp->result(1)));
158 
159  foundAlloca = true;
160  }
161  }
162  EXPECT_TRUE(foundAlloca);
163  }
164  }
165 }
166 
167 TEST(JlmToMlirToJlmTests, TestLoad)
168 {
169  using namespace jlm::llvm;
170  using namespace mlir::rvsdg;
171 
172  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
173  auto graph = &rvsdgModule->Rvsdg();
174 
175  {
176  auto functionType = jlm::rvsdg::FunctionType::Create(
179  auto lambda = jlm::rvsdg::LambdaNode::Create(
180  graph->GetRootRegion(),
182  auto iOStateArgument = lambda->GetFunctionArguments().at(0);
183  auto memoryStateArgument = lambda->GetFunctionArguments().at(1);
184  auto pointerArgument = lambda->GetFunctionArguments().at(2);
185 
186  // Create load operation
187  auto loadType = jlm::rvsdg::BitType::Create(32);
188  auto loadOp = jlm::llvm::LoadNonVolatileOperation(loadType, 1, 4);
189  auto & subregion = *(lambda->subregion());
191  subregion,
192  std::make_unique<LoadNonVolatileOperation>(loadOp),
193  { pointerArgument, memoryStateArgument });
194 
195  lambda->finalize({ iOStateArgument, memoryStateArgument });
196 
197  // Convert the RVSDG to MLIR
198  std::cout << "Convert to MLIR" << std::endl;
200  auto omega = mlirgen.ConvertModule(*rvsdgModule);
201 
202  // Validate the generated MLIR
203  std::cout << "Validate MLIR" << std::endl;
204  auto & omegaRegion = omega.getRegion();
205  auto & omegaBlock = omegaRegion.front();
206  auto & mlirLambda = omegaBlock.front();
207  auto & mlirLambdaRegion = mlirLambda.getRegion(0);
208  auto & mlirLambdaBlock = mlirLambdaRegion.front();
209  auto & mlirOp = mlirLambdaBlock.front();
210 
211  EXPECT_TRUE(mlir::isa<mlir::jlm::Load>(mlirOp));
212 
213  auto mlirLoad = mlir::cast<mlir::jlm::Load>(mlirOp);
214  EXPECT_EQ(mlirLoad.getAlignment(), 4);
215  EXPECT_EQ(mlirLoad.getInputMemStates().size(), 1);
216  EXPECT_EQ(mlirLoad.getNumOperands(), 2);
217  EXPECT_EQ(mlirLoad.getNumResults(), 2);
218 
219  auto outputType = mlirLoad.getOutput().getType();
220  EXPECT_TRUE(mlir::isa<mlir::IntegerType>(outputType));
221  auto integerType = mlir::cast<mlir::IntegerType>(outputType);
222  EXPECT_EQ(integerType.getWidth(), 32);
223 
224  // // Convert the MLIR to RVSDG and check the result
225  std::cout << "Converting MLIR to RVSDG" << std::endl;
226  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
227  rootBlock->push_back(omega);
228  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
229  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
230 
231  {
232  using namespace jlm::llvm;
233 
234  EXPECT_EQ(region->numNodes(), 1);
235  auto convertedLambda =
236  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
237  EXPECT_TRUE(is<jlm::rvsdg::LambdaOperation>(convertedLambda));
238 
239  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
240  EXPECT_TRUE(is<LoadNonVolatileOperation>(
241  convertedLambda->subregion()->Nodes().begin()->GetOperation()));
242  auto convertedLoad = convertedLambda->subregion()->Nodes().begin().ptr();
243  auto loadOperation =
244  dynamic_cast<const LoadNonVolatileOperation *>(&convertedLoad->GetOperation());
245 
246  EXPECT_EQ(loadOperation->GetAlignment(), 4);
247  EXPECT_EQ(loadOperation->NumMemoryStates(), 1);
248 
249  EXPECT_TRUE(is<jlm::llvm::PointerType>(convertedLoad->input(0)->Type()));
250  EXPECT_TRUE(is<jlm::llvm::MemoryStateType>(convertedLoad->input(1)->Type()));
251 
252  EXPECT_TRUE(is<jlm::rvsdg::BitType>(convertedLoad->output(0)->Type()));
253  EXPECT_TRUE(is<jlm::llvm::MemoryStateType>(convertedLoad->output(1)->Type()));
254 
255  auto outputBitType =
256  std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(convertedLoad->output(0)->Type());
257  EXPECT_EQ(outputBitType->nbits(), 32);
258  }
259  }
260 }
261 
262 TEST(JlmToMlirToJlmTests, TestStore)
263 {
264  using namespace jlm::llvm;
265  using namespace mlir::rvsdg;
266 
267  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
268  auto graph = &rvsdgModule->Rvsdg();
269 
270  {
271  auto bitsType = jlm::rvsdg::BitType::Create(32);
272  auto functionType = jlm::rvsdg::FunctionType::Create(
275  auto lambda = jlm::rvsdg::LambdaNode::Create(
276  graph->GetRootRegion(),
278  auto iOStateArgument = lambda->GetFunctionArguments().at(0);
279  auto memoryStateArgument = lambda->GetFunctionArguments().at(1);
280  auto pointerArgument = lambda->GetFunctionArguments().at(2);
281  auto bitsArgument = lambda->GetFunctionArguments().at(3);
282 
283  // Create store operation
284  auto storeOp = jlm::llvm::StoreNonVolatileOperation(bitsType, 1, 4);
286  *lambda->subregion(),
287  std::make_unique<StoreNonVolatileOperation>(storeOp),
288  { pointerArgument, bitsArgument, memoryStateArgument });
289 
290  lambda->finalize({ iOStateArgument, memoryStateArgument });
291 
292  // Convert the RVSDG to MLIR
293  std::cout << "Convert to MLIR" << std::endl;
295  auto omega = mlirgen.ConvertModule(*rvsdgModule);
296 
297  // Validate the generated MLIR
298  std::cout << "Validate MLIR" << std::endl;
299  auto & omegaRegion = omega.getRegion();
300  auto & omegaBlock = omegaRegion.front();
301  auto & mlirLambda = omegaBlock.front();
302  auto & mlirLambdaRegion = mlirLambda.getRegion(0);
303  auto & mlirLambdaBlock = mlirLambdaRegion.front();
304  auto & mlirOp = mlirLambdaBlock.front();
305 
306  EXPECT_TRUE(mlir::isa<mlir::jlm::Store>(mlirOp));
307 
308  auto mlirStore = mlir::cast<mlir::jlm::Store>(mlirOp);
309  EXPECT_EQ(mlirStore.getAlignment(), 4);
310  EXPECT_EQ(mlirStore.getInputMemStates().size(), 1);
311  EXPECT_EQ(mlirStore.getNumOperands(), 3);
312 
313  auto inputType = mlirStore.getValue().getType();
314  EXPECT_TRUE(mlir::isa<mlir::IntegerType>(inputType));
315  auto integerType = mlir::cast<mlir::IntegerType>(inputType);
316  EXPECT_EQ(integerType.getWidth(), 32);
317 
318  // // Convert the MLIR to RVSDG and check the result
319  std::cout << "Converting MLIR to RVSDG" << std::endl;
320  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
321  rootBlock->push_back(omega);
322  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
323  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
324 
325  {
326  using namespace jlm::llvm;
327 
328  EXPECT_EQ(region->numNodes(), 1);
329  auto convertedLambda =
330  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
331  EXPECT_TRUE(is<jlm::rvsdg::LambdaOperation>(convertedLambda));
332 
333  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
334  EXPECT_TRUE(is<StoreNonVolatileOperation>(
335  convertedLambda->subregion()->Nodes().begin()->GetOperation()));
336  auto convertedStore = convertedLambda->subregion()->Nodes().begin().ptr();
337  auto convertedStoreOperation =
338  dynamic_cast<const StoreNonVolatileOperation *>(&convertedStore->GetOperation());
339 
340  EXPECT_EQ(convertedStoreOperation->GetAlignment(), 4);
341  EXPECT_EQ(convertedStoreOperation->NumMemoryStates(), 1);
342 
343  EXPECT_TRUE(is<jlm::llvm::PointerType>(convertedStore->input(0)->Type()));
344  EXPECT_TRUE(is<jlm::rvsdg::BitType>(convertedStore->input(1)->Type()));
345  EXPECT_TRUE(is<jlm::llvm::MemoryStateType>(convertedStore->input(2)->Type()));
346 
347  EXPECT_TRUE(is<jlm::llvm::MemoryStateType>(convertedStore->output(0)->Type()));
348 
349  auto inputBitType =
350  std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(convertedStore->input(1)->Type());
351  EXPECT_EQ(inputBitType->nbits(), 32);
352  }
353  }
354 }
355 
356 TEST(JlmToMlirToJlmTests, TestSext)
357 {
358  using namespace jlm::llvm;
359  using namespace mlir::rvsdg;
360 
361  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
362  auto graph = &rvsdgModule->Rvsdg();
363  {
364 
365  auto bitsType = jlm::rvsdg::BitType::Create(32);
366  auto functionType = jlm::rvsdg::FunctionType::Create({ bitsType }, {});
367  auto lambda = jlm::rvsdg::LambdaNode::Create(
368  graph->GetRootRegion(),
370  auto bitsArgument = lambda->GetFunctionArguments().at(0);
371 
372  // Create sext operation
373  auto sextOp = jlm::llvm::SExtOperation::create((size_t)64, bitsArgument);
374  auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*sextOp);
375  EXPECT_NE(node, nullptr);
376 
377  lambda->finalize({});
378 
379  // Convert the RVSDG to MLIR
380  std::cout << "Convert to MLIR" << std::endl;
382  auto omega = mlirgen.ConvertModule(*rvsdgModule);
383 
384  // Validate the generated MLIR
385  std::cout << "Validate MLIR" << std::endl;
386  auto & omegaRegion = omega.getRegion();
387  auto & omegaBlock = omegaRegion.front();
388  auto & mlirLambda = omegaBlock.front();
389  auto & mlirLambdaRegion = mlirLambda.getRegion(0);
390  auto & mlirLambdaBlock = mlirLambdaRegion.front();
391  auto & mlirOp = mlirLambdaBlock.front();
392 
393  EXPECT_TRUE(mlir::isa<mlir::arith::ExtSIOp>(mlirOp));
394 
395  auto mlirSext = mlir::cast<mlir::arith::ExtSIOp>(mlirOp);
396  auto inputType = mlirSext.getOperand().getType();
397  auto outputType = mlirSext.getType();
398  EXPECT_TRUE(mlir::isa<mlir::IntegerType>(inputType));
399  EXPECT_TRUE(mlir::isa<mlir::IntegerType>(outputType));
400  EXPECT_TRUE(mlir::cast<mlir::IntegerType>(inputType).getWidth() == 32);
401  EXPECT_TRUE(mlir::cast<mlir::IntegerType>(outputType).getWidth() == 64);
402 
403  // // Convert the MLIR to RVSDG and check the result
404  std::cout << "Converting MLIR to RVSDG" << std::endl;
405  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
406  rootBlock->push_back(omega);
407  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
408  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
409  {
410  using namespace jlm::llvm;
411 
412  EXPECT_EQ(region->numNodes(), 1);
413  auto convertedLambda =
414  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
415  EXPECT_TRUE(is<jlm::rvsdg::LambdaOperation>(convertedLambda));
416 
417  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
418  EXPECT_TRUE(is<SExtOperation>(convertedLambda->subregion()->Nodes().begin()->GetOperation()));
419  auto convertedSext = dynamic_cast<const SExtOperation *>(
420  &convertedLambda->subregion()->Nodes().begin()->GetOperation());
421 
422  EXPECT_EQ(convertedSext->ndstbits(), 64);
423  EXPECT_EQ(convertedSext->nsrcbits(), 32);
424  EXPECT_EQ(convertedSext->nresults(), 1);
425  }
426  }
427 }
428 
429 TEST(JlmToMlirToJlmTests, TestSitofp)
430 {
431  using namespace jlm::llvm;
432  using namespace mlir::rvsdg;
433 
434  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
435  auto graph = &rvsdgModule->Rvsdg();
436  {
437 
438  auto bitsType = jlm::rvsdg::BitType::Create(32);
440  auto functionType = jlm::rvsdg::FunctionType::Create({ bitsType }, {});
441  auto lambda = jlm::rvsdg::LambdaNode::Create(
442  graph->GetRootRegion(),
444  auto bitsArgument = lambda->GetFunctionArguments().at(0);
445 
446  // Create sitofp operation
447  jlm::rvsdg::CreateOpNode<SIToFPOperation>({ bitsArgument }, bitsType, floatType);
448 
449  lambda->finalize({});
450 
451  // Convert the RVSDG to MLIR
452  std::cout << "Convert to MLIR" << std::endl;
454  auto omega = mlirgen.ConvertModule(*rvsdgModule);
455 
456  // Validate the generated MLIR
457  std::cout << "Validate MLIR" << std::endl;
458  auto & omegaRegion = omega.getRegion();
459  auto & omegaBlock = omegaRegion.front();
460  auto & mlirLambda = omegaBlock.front();
461  auto & mlirLambdaRegion = mlirLambda.getRegion(0);
462  auto & mlirLambdaBlock = mlirLambdaRegion.front();
463  auto & mlirOp = mlirLambdaBlock.front();
464 
465  EXPECT_TRUE(mlir::isa<mlir::arith::SIToFPOp>(mlirOp));
466 
467  auto mlirSitofp = mlir::cast<mlir::arith::SIToFPOp>(mlirOp);
468  auto inputType = mlirSitofp.getOperand().getType();
469  auto outputType = mlirSitofp.getType();
470  EXPECT_TRUE(mlir::isa<mlir::IntegerType>(inputType));
471  EXPECT_TRUE(mlir::cast<mlir::IntegerType>(inputType).getWidth() == 32);
472  EXPECT_TRUE(mlir::isa<mlir::Float64Type>(outputType));
473 
474  // // Convert the MLIR to RVSDG and check the result
475  std::cout << "Converting MLIR to RVSDG" << std::endl;
476  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
477  rootBlock->push_back(omega);
478  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
479  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
480  {
481  using namespace jlm::llvm;
482 
483  EXPECT_EQ(region->numNodes(), 1);
484  auto convertedLambda =
485  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
486  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
487  EXPECT_TRUE(
488  is<SIToFPOperation>(convertedLambda->subregion()->Nodes().begin()->GetOperation()));
489  auto convertedSitofp = dynamic_cast<const SIToFPOperation *>(
490  &convertedLambda->subregion()->Nodes().begin()->GetOperation());
491 
492  EXPECT_TRUE(jlm::rvsdg::is<jlm::rvsdg::BitType>(*convertedSitofp->argument(0).get()));
493  EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::FloatingPointType>(*convertedSitofp->result(0).get()));
494  }
495  }
496 }
497 
498 TEST(JlmToMlirToJlmTests, TestConstantFP)
499 {
500  using namespace jlm::llvm;
501  using namespace mlir::rvsdg;
502 
503  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
504  auto graph = &rvsdgModule->Rvsdg();
505  {
506  auto functionType = jlm::rvsdg::FunctionType::Create({}, {});
507  auto lambda = jlm::rvsdg::LambdaNode::Create(
508  graph->GetRootRegion(),
510 
511  // Create sitofp operation
512  jlm::rvsdg::CreateOpNode<ConstantFP>(*lambda->subregion(), fpsize::dbl, ::llvm::APFloat(2.0));
513 
514  lambda->finalize({});
515 
516  // Convert the RVSDG to MLIR
517  std::cout << "Convert to MLIR" << std::endl;
519  auto omega = mlirgen.ConvertModule(*rvsdgModule);
520 
521  // Validate the generated MLIR
522  std::cout << "Validate MLIR" << std::endl;
523  auto & mlirOp = omega.getRegion().front().front().getRegion(0).front().front();
524 
525  EXPECT_TRUE(mlir::isa<mlir::arith::ConstantFloatOp>(mlirOp));
526 
527  auto mlirConst = mlir::cast<mlir::arith::ConstantFloatOp>(mlirOp);
528  EXPECT_TRUE(mlirConst.value().isExactlyValue(2.0));
529 
530  // // Convert the MLIR to RVSDG and check the result
531  std::cout << "Converting MLIR to RVSDG" << std::endl;
532  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
533  rootBlock->push_back(omega);
534  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
535  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
536  {
537  using namespace jlm::llvm;
538 
539  EXPECT_EQ(region->numNodes(), 1);
540  auto convertedLambda =
541  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
542  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
543  EXPECT_TRUE(is<ConstantFP>(convertedLambda->subregion()->Nodes().begin()->GetOperation()));
544  auto convertedConst = dynamic_cast<const ConstantFP *>(
545  &convertedLambda->subregion()->Nodes().begin()->GetOperation());
546 
547  EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::FloatingPointType>(*convertedConst->result(0).get()));
548  EXPECT_TRUE(convertedConst->constant().isExactlyValue(2.0));
549  }
550  }
551 }
552 
553 TEST(JlmToMlirToJlmTests, TestFpBinary)
554 {
555  using namespace jlm::llvm;
556  using namespace mlir::rvsdg;
557  auto binOps = std::vector<fpop>{ fpop::add, fpop::sub, fpop::mul, fpop::div, fpop::mod };
558  for (auto binOp : binOps)
559  {
560  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
561  auto graph = &rvsdgModule->Rvsdg();
562  {
564  auto functionType = jlm::rvsdg::FunctionType::Create({ floatType, floatType }, {});
565  auto lambda = jlm::rvsdg::LambdaNode::Create(
566  graph->GetRootRegion(),
568 
569  auto floatArgument1 = lambda->GetFunctionArguments().at(0);
570  auto floatArgument2 = lambda->GetFunctionArguments().at(1);
571 
572  jlm::rvsdg::CreateOpNode<FBinaryOperation>(
573  { floatArgument1, floatArgument2 },
574  binOp,
575  floatType);
576 
577  lambda->finalize({});
578 
579  // Convert the RVSDG to MLIR
580  std::cout << "Convert to MLIR" << std::endl;
582  auto omega = mlirgen.ConvertModule(*rvsdgModule);
583 
584  // Validate the generated MLIR
585  std::cout << "Validate MLIR" << std::endl;
586  auto & mlirOp = omega.getRegion().front().front().getRegion(0).front().front();
587  switch (binOp)
588  {
589  case fpop::add:
590  EXPECT_TRUE(mlir::isa<mlir::arith::AddFOp>(mlirOp));
591  break;
592  case fpop::sub:
593  EXPECT_TRUE(mlir::isa<mlir::arith::SubFOp>(mlirOp));
594  break;
595  case fpop::mul:
596  EXPECT_TRUE(mlir::isa<mlir::arith::MulFOp>(mlirOp));
597  break;
598  case fpop::div:
599  EXPECT_TRUE(mlir::isa<mlir::arith::DivFOp>(mlirOp));
600  break;
601  case fpop::mod:
602  EXPECT_TRUE(mlir::isa<mlir::arith::RemFOp>(mlirOp));
603  break;
604  default:
605  FAIL();
606  }
607 
608  // Convert the MLIR to RVSDG and check the result
609  std::cout << "Converting MLIR to RVSDG" << std::endl;
610  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
611  rootBlock->push_back(omega);
612  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
613  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
614  {
615  using namespace jlm::llvm;
616 
617  EXPECT_EQ(region->numNodes(), 1);
618  auto convertedLambda =
619  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
620  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
621 
622  auto node = convertedLambda->subregion()->Nodes().begin().ptr();
623  auto convertedFpbin =
624  jlm::util::assertedCast<const FBinaryOperation>(&node->GetOperation());
625  EXPECT_EQ(convertedFpbin->fpop(), binOp);
626  EXPECT_EQ(convertedFpbin->nresults(), 1);
627  EXPECT_EQ(convertedFpbin->narguments(), 2);
628  }
629  }
630  }
631 }
632 
633 TEST(JlmToMlirToJlmTests, TestFMulAddOp)
634 {
635  using namespace jlm::llvm;
636  using namespace mlir::rvsdg;
637 
638  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
639  auto graph = &rvsdgModule->Rvsdg();
640  {
642  auto functionType =
643  jlm::rvsdg::FunctionType::Create({ floatType, floatType, floatType }, { floatType });
644  auto lambda = jlm::rvsdg::LambdaNode::Create(
645  graph->GetRootRegion(),
647 
648  auto floatArgument1 = lambda->GetFunctionArguments().at(0);
649  auto floatArgument2 = lambda->GetFunctionArguments().at(1);
650  auto floatArgument3 = lambda->GetFunctionArguments().at(2);
651 
652  auto & node = jlm::rvsdg::CreateOpNode<jlm::llvm::FMulAddIntrinsicOperation>(
653  { floatArgument1, floatArgument2, floatArgument3 },
654  floatType);
655 
656  lambda->finalize({ node.output(0) });
657 
658  // Convert the RVSDG to MLIR
659  std::cout << "Convert to MLIR" << std::endl;
661  auto omega = mlirgen.ConvertModule(*rvsdgModule);
662 
663  // Validate the generated MLIR
664  std::cout << "Validate MLIR" << std::endl;
665  auto & mlirOp = omega.getRegion().front().front().getRegion(0).front().front();
666  EXPECT_TRUE(mlir::isa<mlir::LLVM::FMulAddOp>(mlirOp));
667 
668  // Convert the MLIR to RVSDG and check the result
669  std::cout << "Converting MLIR to RVSDG" << std::endl;
670  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
671  rootBlock->push_back(omega);
672  auto roundTripModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
673 
674  // Assert
675  auto region = &roundTripModule->Rvsdg().GetRootRegion();
676  EXPECT_EQ(region->numNodes(), 1);
677  auto convertedLambda =
678  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
679  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
680  const auto arguments = convertedLambda->GetFunctionArguments();
681  const auto results = convertedLambda->GetFunctionResults();
682  EXPECT_EQ(arguments.size(), 3);
683  EXPECT_EQ(results.size(), 1);
684 
685  auto & convertedNode = *convertedLambda->subregion()->Nodes().begin();
686  EXPECT_TRUE(is<jlm::llvm::FMulAddIntrinsicOperation>(&convertedNode));
687  EXPECT_EQ(convertedNode.input(0)->origin(), arguments[0]);
688  EXPECT_EQ(convertedNode.input(1)->origin(), arguments[1]);
689  EXPECT_EQ(convertedNode.input(2)->origin(), arguments[2]);
690  EXPECT_EQ(results[0]->origin(), convertedNode.output(0));
691  }
692 }
693 
694 TEST(JlmToMlirToJlmTests, TestGetElementPtr)
695 {
696  using namespace jlm::llvm;
697  using namespace mlir::rvsdg;
698 
699  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
700  auto graph = &rvsdgModule->Rvsdg();
701  {
702  auto pointerType = PointerType::Create();
703  auto bitType = jlm::rvsdg::BitType::Create(32);
704 
705  auto functionType = jlm::rvsdg::FunctionType::Create({ pointerType, bitType }, {});
706  auto lambda = jlm::rvsdg::LambdaNode::Create(
707  graph->GetRootRegion(),
709 
710  auto pointerArgument = lambda->GetFunctionArguments().at(0);
711  auto bitArgument = lambda->GetFunctionArguments().at(1);
712 
713  auto arrayType = ArrayType::Create(bitType, 2);
714 
715  GetElementPtrOperation::create(pointerArgument, { bitArgument, bitArgument }, arrayType);
716 
717  lambda->finalize({});
718 
719  // Convert the RVSDG to MLIR
720  std::cout << "Convert to MLIR" << std::endl;
722  auto omega = mlirgen.ConvertModule(*rvsdgModule);
723 
724  // Validate the generated MLIR
725  std::cout << "Validate MLIR" << std::endl;
726  auto & op = omega.getRegion().front().front().getRegion(0).front().front();
727 
728  EXPECT_TRUE(mlir::isa<mlir::LLVM::GEPOp>(op));
729 
730  auto mlirGep = mlir::cast<mlir::LLVM::GEPOp>(op);
731  EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(mlirGep.getBase().getType()));
732  EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(mlirGep.getType()));
733 
734  EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMArrayType>(mlirGep.getElemType()));
735  auto mlirArrayType = mlir::cast<mlir::LLVM::LLVMArrayType>(mlirGep.getElemType());
736 
737  EXPECT_TRUE(mlir::isa<mlir::IntegerType>(mlirArrayType.getElementType()));
738  EXPECT_EQ(mlirArrayType.getNumElements(), 2);
739 
740  auto indices = mlirGep.getIndices();
741  EXPECT_EQ(indices.size(), 2);
742  auto index0 = indices[0].dyn_cast<mlir::Value>();
743  auto index1 = indices[1].dyn_cast<mlir::Value>();
744  EXPECT_NE(index0, nullptr);
745  EXPECT_NE(index1, nullptr);
746  EXPECT_TRUE(index0.getType().isa<mlir::IntegerType>());
747  EXPECT_TRUE(index1.getType().isa<mlir::IntegerType>());
748  EXPECT_EQ(index0.getType().getIntOrFloatBitWidth(), 32);
749  EXPECT_EQ(index1.getType().getIntOrFloatBitWidth(), 32);
750 
751  // // Convert the MLIR to RVSDG and check the result
752  std::cout << "Converting MLIR to RVSDG" << std::endl;
753  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
754  rootBlock->push_back(omega);
755  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
756  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
757 
758  {
759  using namespace jlm::llvm;
760 
761  EXPECT_EQ(region->numNodes(), 1);
762  auto convertedLambda =
763  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
764  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
765 
766  auto op = convertedLambda->subregion()->Nodes().begin();
767  EXPECT_TRUE(is<GetElementPtrOperation>(op->GetOperation()));
768  auto convertedGep = dynamic_cast<const GetElementPtrOperation *>(&op->GetOperation());
769 
770  EXPECT_TRUE(is<ArrayType>(convertedGep->getPointeeType()));
771  EXPECT_TRUE(is<PointerType>(convertedGep->result(0)));
772  EXPECT_TRUE(is<jlm::rvsdg::BitType>(convertedGep->argument(1)));
773  EXPECT_TRUE(is<jlm::rvsdg::BitType>(convertedGep->argument(2)));
774  }
775  }
776 }
777 
778 TEST(JlmToMlirToJlmTests, TestDelta)
779 {
780  using namespace jlm::llvm;
781  using namespace mlir::rvsdg;
782 
783  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
784  auto graph = &rvsdgModule->Rvsdg();
785  {
786  auto bitType = jlm::rvsdg::BitType::Create(32);
787 
788  auto delta1 = jlm::rvsdg::DeltaNode::Create(
789  &graph->GetRootRegion(),
791  bitType,
792  "non-constant-delta",
794  "section",
795  false,
796  4));
797 
798  auto bitConstant = &jlm::rvsdg::BitConstantOperation::create(*delta1->subregion(), { 32, 1 });
799  delta1->finalize(bitConstant);
800 
801  auto delta2 = jlm::rvsdg::DeltaNode::Create(
802  &graph->GetRootRegion(),
804  bitType,
805  "constant-delta",
807  "section",
808  true,
809  4));
810  auto bitConstant2 = &jlm::rvsdg::BitConstantOperation::create(*delta2->subregion(), { 32, 1 });
811  delta2->finalize(bitConstant2);
812 
813  // Convert the RVSDG to MLIR
814  std::cout << "Convert to MLIR" << std::endl;
816  auto omega = mlirgen.ConvertModule(*rvsdgModule);
817 
818  // Validate the generated MLIR
819  std::cout << "Validate MLIR" << std::endl;
820 
821  auto & omegaBlock = omega.getRegion().front();
822  EXPECT_EQ(omegaBlock.getOperations().size(), 3); // 2 delta nodes + 1 omegaresult
823  for (auto & op : omegaBlock.getOperations())
824  {
825  auto mlirDeltaNode = ::mlir::dyn_cast<::mlir::rvsdg::DeltaNode>(&op);
826  auto mlirOmegaResult = ::mlir::dyn_cast<::mlir::rvsdg::OmegaResult>(&op);
827 
828  EXPECT_TRUE(mlirDeltaNode || mlirOmegaResult);
829 
830  if (mlirOmegaResult)
831  {
832  break;
833  }
834 
835  if (mlirDeltaNode.getConstant())
836  {
837  EXPECT_EQ(mlirDeltaNode.getName().str(), "constant-delta");
838  }
839  else
840  {
841  EXPECT_EQ(mlirDeltaNode.getName().str(), "non-constant-delta");
842  }
843 
844  EXPECT_EQ(mlirDeltaNode.getSection(), "section");
845  EXPECT_EQ(mlirDeltaNode.getLinkage(), "external_linkage");
846  EXPECT_TRUE(mlirDeltaNode.getType().isa<mlir::LLVM::LLVMPointerType>());
847  auto terminator = mlirDeltaNode.getRegion().front().getTerminator();
848  EXPECT_NE(terminator, nullptr);
849  EXPECT_EQ(terminator->getNumOperands(), 1);
850  EXPECT_TRUE(terminator->getOperand(0).getType().isa<mlir::IntegerType>());
851  }
852 
853  // Convert the MLIR to RVSDG and check the result
854  std::cout << "Converting MLIR to RVSDG" << std::endl;
855  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
856  rootBlock->push_back(omega);
857  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
858  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
859 
860  {
861  using namespace jlm::llvm;
862 
863  EXPECT_EQ(region->numNodes(), 2);
864  for (auto & node : region->Nodes())
865  {
866  auto convertedDelta = jlm::util::assertedCast<jlm::rvsdg::DeltaNode>(&node);
867  EXPECT_EQ(convertedDelta->subregion()->numNodes(), 1);
868  auto dop = jlm::util::assertedCast<const jlm::llvm::DeltaOperation>(&node.GetOperation());
869 
870  if (convertedDelta->constant())
871  {
872  EXPECT_EQ(dop->name(), "constant-delta");
873  }
874  else
875  {
876  EXPECT_EQ(dop->name(), "non-constant-delta");
877  }
878 
879  EXPECT_TRUE(is<jlm::rvsdg::BitType>(*dop->Type()));
880  EXPECT_EQ(dop->linkage(), Linkage::externalLinkage);
881  EXPECT_EQ(dop->Section(), "section");
882 
883  auto op = convertedDelta->subregion()->Nodes().begin();
884  EXPECT_TRUE(is<jlm::llvm::IntegerConstantOperation>(op->GetOperation()));
885  }
886  }
887  }
888 }
889 
890 TEST(JlmToMlirToJlmTests, TestConstantDataArray)
891 {
892  using namespace jlm::llvm;
893  using namespace mlir::rvsdg;
894 
895  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
896  auto graph = &rvsdgModule->Rvsdg();
897 
898  {
899  auto bitConstant1 =
900  &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 32, 1 });
901  auto bitConstant2 =
902  &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 32, 2 });
903  auto bitType = jlm::rvsdg::BitType::Create(32);
904  jlm::llvm::ConstantDataArray::Create({ bitConstant1, bitConstant2 });
905 
906  // Convert the RVSDG to MLIR
907  std::cout << "Convert to MLIR" << std::endl;
909  auto omega = mlirgen.ConvertModule(*rvsdgModule);
910 
911  // Validate the generated MLIR
912  std::cout << "Validate MLIR" << std::endl;
913  auto & omegaRegion = omega.getRegion();
914  auto & omegaBlock = omegaRegion.front();
915  bool foundConstantDataArray = false;
916  for (auto & op : omegaBlock.getOperations())
917  {
918  auto mlirConstantDataArray = ::mlir::dyn_cast<::mlir::jlm::ConstantDataArray>(&op);
919  if (mlirConstantDataArray)
920  {
921  EXPECT_EQ(mlirConstantDataArray.getNumOperands(), 2);
922  EXPECT_TRUE(mlirConstantDataArray.getOperand(0).getType().isa<mlir::IntegerType>());
923  EXPECT_TRUE(mlirConstantDataArray.getOperand(1).getType().isa<mlir::IntegerType>());
924  auto mlirConstantDataArrayResultType =
925  mlirConstantDataArray.getResult().getType().dyn_cast<mlir::LLVM::LLVMArrayType>();
926  EXPECT_NE(mlirConstantDataArrayResultType, nullptr);
927  EXPECT_TRUE(mlirConstantDataArrayResultType.getElementType().isa<mlir::IntegerType>());
928  EXPECT_EQ(mlirConstantDataArrayResultType.getNumElements(), 2);
929  foundConstantDataArray = true;
930  }
931  }
932  EXPECT_TRUE(foundConstantDataArray);
933 
934  // // Convert the MLIR to RVSDG and check the result
935  std::cout << "Converting MLIR to RVSDG" << std::endl;
936  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
937  rootBlock->push_back(omega);
938  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
939  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
940 
941  {
942  using namespace jlm::llvm;
943 
944  EXPECT_EQ(region->numNodes(), 3);
945  bool foundConstantDataArray = false;
946  for (auto & node : region->Nodes())
947  {
948  if (auto constantDataArray = dynamic_cast<const ConstantDataArray *>(&node.GetOperation()))
949  {
950  foundConstantDataArray = true;
951  EXPECT_EQ(constantDataArray->nresults(), 1);
952  EXPECT_EQ(constantDataArray->narguments(), 2);
953  auto resultType = constantDataArray->result(0);
954  auto arrayType = dynamic_cast<const jlm::llvm::ArrayType *>(resultType.get());
955  EXPECT_NE(arrayType, nullptr);
956  EXPECT_TRUE(is<jlm::rvsdg::BitType>(arrayType->element_type()));
957  EXPECT_EQ(arrayType->nelements(), 2);
958  EXPECT_TRUE(is<jlm::rvsdg::BitType>(constantDataArray->argument(0)));
959  EXPECT_TRUE(is<jlm::rvsdg::BitType>(constantDataArray->argument(1)));
960  }
961  }
962  EXPECT_TRUE(foundConstantDataArray);
963  }
964  }
965 }
966 
967 TEST(JlmToMlirToJlmTests, TestConstantAggregateZero)
968 {
969  using namespace jlm::llvm;
970  using namespace mlir::rvsdg;
971 
972  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
973  auto graph = &rvsdgModule->Rvsdg();
974 
975  {
976  auto bitType = jlm::rvsdg::BitType::Create(32);
977  auto arrayType = jlm::llvm::ArrayType::Create(bitType, 2);
978  ConstantAggregateZeroOperation::Create(graph->GetRootRegion(), arrayType);
979 
980  // Convert the RVSDG to MLIR
981  std::cout << "Convert to MLIR" << std::endl;
983  auto omega = mlirgen.ConvertModule(*rvsdgModule);
984 
985  // Validate the generated MLIR
986  std::cout << "Validate MLIR" << std::endl;
987  auto & omegaRegion = omega.getRegion();
988  auto & omegaBlock = omegaRegion.front();
989  auto mlirConstantAggregateZero = ::mlir::dyn_cast<::mlir::LLVM::ZeroOp>(&omegaBlock.front());
990  EXPECT_NE(mlirConstantAggregateZero, nullptr);
991  auto mlirConstantAggregateZeroResultType =
992  mlirConstantAggregateZero.getType().dyn_cast<mlir::LLVM::LLVMArrayType>();
993  EXPECT_NE(mlirConstantAggregateZeroResultType, nullptr);
994  EXPECT_TRUE(mlirConstantAggregateZeroResultType.getElementType().isa<mlir::IntegerType>());
995  EXPECT_EQ(mlirConstantAggregateZeroResultType.getNumElements(), 2);
996 
997  // // Convert the MLIR to RVSDG and check the result
998  std::cout << "Converting MLIR to RVSDG" << std::endl;
999  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1000  rootBlock->push_back(omega);
1001  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1002  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1003 
1004  {
1005  using namespace jlm::llvm;
1006 
1007  EXPECT_EQ(region->numNodes(), 1);
1008  auto const convertedConstantAggregateZero =
1009  jlm::util::assertedCast<const ConstantAggregateZeroOperation>(
1010  &region->Nodes().begin().ptr()->GetOperation());
1011  EXPECT_EQ(convertedConstantAggregateZero->nresults(), 1);
1012  EXPECT_EQ(convertedConstantAggregateZero->narguments(), 0);
1013  auto resultType = convertedConstantAggregateZero->result(0);
1014  auto arrayType = dynamic_cast<const jlm::llvm::ArrayType *>(resultType.get());
1015  EXPECT_NE(arrayType, nullptr);
1016  EXPECT_TRUE(is<jlm::rvsdg::BitType>(arrayType->element_type()));
1017  EXPECT_EQ(arrayType->nelements(), 2);
1018  }
1019  }
1020 }
1021 
1022 TEST(JlmToMlirToJlmTests, TestVarArgList)
1023 {
1024  using namespace jlm::llvm;
1025  using namespace mlir::rvsdg;
1026 
1027  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1028  auto graph = &rvsdgModule->Rvsdg();
1029 
1030  {
1031  auto bitType = jlm::rvsdg::BitType::Create(32);
1032  auto bits1 = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 32, 1 });
1033  auto bits2 = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 32, 2 });
1034  jlm::llvm::VariadicArgumentListOperation::Create(graph->GetRootRegion(), { bits1, bits2 });
1035 
1036  // Convert the RVSDG to MLIR
1037  std::cout << "Convert to MLIR" << std::endl;
1039  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1040 
1041  // Validate the generated MLIR
1042  std::cout << "Validate MLIR" << std::endl;
1043  auto & omegaRegion = omega.getRegion();
1044  auto & omegaBlock = omegaRegion.front();
1045  bool foundVarArgOp = false;
1046  for (auto & op : omegaBlock.getOperations())
1047  {
1048  auto mlirVarArgOp = ::mlir::dyn_cast<::mlir::jlm::CreateVarArgList>(&op);
1049  if (mlirVarArgOp)
1050  {
1051  EXPECT_EQ(mlirVarArgOp.getOperands().size(), 2);
1052  EXPECT_TRUE(mlirVarArgOp.getOperands()[0].getType().isa<mlir::IntegerType>());
1053  EXPECT_TRUE(mlirVarArgOp.getOperands()[1].getType().isa<mlir::IntegerType>());
1054  EXPECT_TRUE(mlirVarArgOp.getResult().getType().isa<mlir::jlm::VarargListType>());
1055  foundVarArgOp = true;
1056  }
1057  }
1058  EXPECT_TRUE(foundVarArgOp);
1059 
1060  // // Convert the MLIR to RVSDG and check the result
1061  std::cout << "Converting MLIR to RVSDG" << std::endl;
1062  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1063  rootBlock->push_back(omega);
1064  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1065  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1066 
1067  {
1068  using namespace jlm::llvm;
1069 
1070  EXPECT_EQ(region->numNodes(), 3);
1071  bool foundVarArgOp = false;
1072  for (auto & node : region->Nodes())
1073  {
1074  auto convertedVarArgOp =
1075  dynamic_cast<const VariadicArgumentListOperation *>(&node.GetOperation());
1076  if (convertedVarArgOp)
1077  {
1078  EXPECT_EQ(convertedVarArgOp->nresults(), 1);
1079  EXPECT_EQ(convertedVarArgOp->narguments(), 2);
1080  auto resultType = convertedVarArgOp->result(0);
1081  EXPECT_TRUE(is<jlm::llvm::VariableArgumentType>(resultType));
1082  EXPECT_TRUE(is<jlm::rvsdg::BitType>(convertedVarArgOp->argument(0)));
1083  EXPECT_TRUE(is<jlm::rvsdg::BitType>(convertedVarArgOp->argument(1)));
1084  foundVarArgOp = true;
1085  }
1086  }
1087  EXPECT_TRUE(foundVarArgOp);
1088  }
1089  }
1090 }
1091 
1092 TEST(JlmToMlirToJlmTests, TestFNeg)
1093 {
1094  using namespace jlm::llvm;
1095  using namespace mlir::rvsdg;
1096 
1097  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1098  auto graph = &rvsdgModule->Rvsdg();
1099 
1100  {
1102  auto & constNode = jlm::rvsdg::CreateOpNode<ConstantFP>(
1103  graph->GetRootRegion(),
1104  floatType,
1105  ::llvm::APFloat(2.0));
1106  jlm::rvsdg::CreateOpNode<FNegOperation>({ constNode.output(0) }, jlm::llvm::fpsize::flt);
1107 
1108  // Convert the RVSDG to MLIR
1109  std::cout << "Convert to MLIR" << std::endl;
1111  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1112 
1113  // Validate the generated MLIR
1114  std::cout << "Validate MLIR" << std::endl;
1115  auto & omegaRegion = omega.getRegion();
1116  auto & omegaBlock = omegaRegion.front();
1117  bool foundFNegOp = false;
1118  for (auto & op : omegaBlock.getOperations())
1119  {
1120  auto mlirFNegOp = ::mlir::dyn_cast<::mlir::arith::NegFOp>(&op);
1121  if (mlirFNegOp)
1122  {
1123  auto inputFloatType = mlirFNegOp.getOperand().getType().dyn_cast<mlir::FloatType>();
1124  EXPECT_NE(inputFloatType, nullptr);
1125  EXPECT_EQ(inputFloatType.getWidth(), 32);
1126  auto outputFloatType = mlirFNegOp.getResult().getType().dyn_cast<mlir::FloatType>();
1127  EXPECT_NE(outputFloatType, nullptr);
1128  EXPECT_EQ(outputFloatType.getWidth(), 32);
1129  foundFNegOp = true;
1130  }
1131  }
1132  EXPECT_TRUE(foundFNegOp);
1133 
1134  // // Convert the MLIR to RVSDG and check the result
1135  std::cout << "Converting MLIR to RVSDG" << std::endl;
1136  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1137  rootBlock->push_back(omega);
1138  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1139  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1140 
1141  {
1142  using namespace jlm::llvm;
1143 
1144  EXPECT_EQ(region->numNodes(), 2);
1145  bool foundFNegOp = false;
1146  for (auto & node : region->Nodes())
1147  {
1148  auto convertedFNegOp = dynamic_cast<const FNegOperation *>(&node.GetOperation());
1149  if (convertedFNegOp)
1150  {
1151  EXPECT_EQ(convertedFNegOp->nresults(), 1);
1152  EXPECT_EQ(convertedFNegOp->narguments(), 1);
1153  auto inputFloatType = jlm::util::assertedCast<const jlm::llvm::FloatingPointType>(
1154  convertedFNegOp->argument(0).get());
1155  EXPECT_EQ(inputFloatType->size(), jlm::llvm::fpsize::flt);
1156  auto outputFloatType = jlm::util::assertedCast<const jlm::llvm::FloatingPointType>(
1157  convertedFNegOp->result(0).get());
1158  EXPECT_EQ(outputFloatType->size(), jlm::llvm::fpsize::flt);
1159  foundFNegOp = true;
1160  }
1161  }
1162  EXPECT_TRUE(foundFNegOp);
1163  }
1164  }
1165 }
1166 
1167 TEST(JlmToMlirToJlmTests, TestFPExt)
1168 {
1169  using namespace jlm::llvm;
1170  using namespace mlir::rvsdg;
1171 
1172  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1173  auto graph = &rvsdgModule->Rvsdg();
1174 
1175  {
1178  auto & constNode = jlm::rvsdg::CreateOpNode<ConstantFP>(
1179  graph->GetRootRegion(),
1180  floatType1,
1181  ::llvm::APFloat(2.0));
1182  jlm::rvsdg::CreateOpNode<FPExtOperation>({ constNode.output(0) }, floatType1, floatType2);
1183 
1184  // Convert the RVSDG to MLIR
1185  std::cout << "Convert to MLIR" << std::endl;
1187  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1188 
1189  // Validate the generated MLIR
1190  std::cout << "Validate MLIR" << std::endl;
1191  auto & omegaRegion = omega.getRegion();
1192  auto & omegaBlock = omegaRegion.front();
1193  bool foundFPExtOp = false;
1194  for (auto & op : omegaBlock.getOperations())
1195  {
1196  auto mlirFPExtOp = ::mlir::dyn_cast<::mlir::arith::ExtFOp>(&op);
1197  if (mlirFPExtOp)
1198  {
1199  auto inputFloatType = mlirFPExtOp.getOperand().getType().dyn_cast<mlir::FloatType>();
1200  EXPECT_NE(inputFloatType, nullptr);
1201  EXPECT_EQ(inputFloatType.getWidth(), 32);
1202  auto outputFloatType = mlirFPExtOp.getResult().getType().dyn_cast<mlir::FloatType>();
1203  EXPECT_NE(outputFloatType, nullptr);
1204  EXPECT_EQ(outputFloatType.getWidth(), 64);
1205  foundFPExtOp = true;
1206  }
1207  }
1208  EXPECT_TRUE(foundFPExtOp);
1209 
1210  // // Convert the MLIR to RVSDG and check the result
1211  std::cout << "Converting MLIR to RVSDG" << std::endl;
1212  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1213  rootBlock->push_back(omega);
1214  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1215  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1216 
1217  {
1218  using namespace jlm::llvm;
1219 
1220  EXPECT_EQ(region->numNodes(), 2);
1221  bool foundFPExtOp = false;
1222  for (auto & node : region->Nodes())
1223  {
1224  auto convertedFPExtOp = dynamic_cast<const FPExtOperation *>(&node.GetOperation());
1225  if (convertedFPExtOp)
1226  {
1227  EXPECT_EQ(convertedFPExtOp->nresults(), 1);
1228  EXPECT_EQ(convertedFPExtOp->narguments(), 1);
1229  auto inputFloatType = jlm::util::assertedCast<const jlm::llvm::FloatingPointType>(
1230  convertedFPExtOp->argument(0).get());
1231  EXPECT_EQ(inputFloatType->size(), jlm::llvm::fpsize::flt);
1232  auto outputFloatType = jlm::util::assertedCast<const jlm::llvm::FloatingPointType>(
1233  convertedFPExtOp->result(0).get());
1234  EXPECT_EQ(outputFloatType->size(), jlm::llvm::fpsize::dbl);
1235  foundFPExtOp = true;
1236  }
1237  }
1238  EXPECT_TRUE(foundFPExtOp);
1239  }
1240  }
1241 }
1242 
1243 TEST(JlmToMlirToJlmTests, TestTrunc)
1244 {
1245  using namespace jlm::llvm;
1246  using namespace mlir::rvsdg;
1247 
1248  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1249  auto graph = &rvsdgModule->Rvsdg();
1250 
1251  {
1252  auto bitType1 = jlm::rvsdg::BitType::Create(64);
1253  auto bitType2 = jlm::rvsdg::BitType::Create(32);
1254  auto constOp = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 64, 2 });
1255  jlm::rvsdg::CreateOpNode<TruncOperation>({ constOp }, bitType1, bitType2);
1256 
1257  // Convert the RVSDG to MLIR
1258  std::cout << "Convert to MLIR" << std::endl;
1260  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1261 
1262  // Validate the generated MLIR
1263  std::cout << "Validate MLIR" << std::endl;
1264  auto & omegaRegion = omega.getRegion();
1265  auto & omegaBlock = omegaRegion.front();
1266  bool foundTruncOp = false;
1267  for (auto & op : omegaBlock.getOperations())
1268  {
1269  auto mlirTruncOp = ::mlir::dyn_cast<::mlir::arith::TruncIOp>(&op);
1270  if (mlirTruncOp)
1271  {
1272  auto inputBitType = mlirTruncOp.getOperand().getType().dyn_cast<mlir::IntegerType>();
1273  EXPECT_NE(inputBitType, nullptr);
1274  EXPECT_EQ(inputBitType.getWidth(), 64);
1275  auto outputBitType = mlirTruncOp.getResult().getType().dyn_cast<mlir::IntegerType>();
1276  EXPECT_NE(outputBitType, nullptr);
1277  EXPECT_EQ(outputBitType.getWidth(), 32);
1278  foundTruncOp = true;
1279  }
1280  }
1281  EXPECT_TRUE(foundTruncOp);
1282 
1283  // // Convert the MLIR to RVSDG and check the result
1284  std::cout << "Converting MLIR to RVSDG" << std::endl;
1285  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1286  rootBlock->push_back(omega);
1287  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1288  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1289 
1290  {
1291  using namespace jlm::llvm;
1292 
1293  EXPECT_EQ(region->numNodes(), 2);
1294  bool foundTruncOp = false;
1295  for (auto & node : region->Nodes())
1296  {
1297  auto convertedTruncOp = dynamic_cast<const TruncOperation *>(&node.GetOperation());
1298  if (convertedTruncOp)
1299  {
1300  EXPECT_EQ(convertedTruncOp->nresults(), 1);
1301  EXPECT_EQ(convertedTruncOp->narguments(), 1);
1302  auto inputBitType = jlm::util::assertedCast<const jlm::rvsdg::BitType>(
1303  convertedTruncOp->argument(0).get());
1304  EXPECT_EQ(inputBitType->nbits(), 64);
1305  auto outputBitType =
1306  jlm::util::assertedCast<const jlm::rvsdg::BitType>(convertedTruncOp->result(0).get());
1307  EXPECT_EQ(outputBitType->nbits(), 32);
1308  foundTruncOp = true;
1309  }
1310  }
1311  EXPECT_TRUE(foundTruncOp);
1312  }
1313  }
1314 }
1315 
1316 TEST(JlmToMlirToJlmTests, TestFree)
1317 {
1318  using namespace jlm::llvm;
1319  using namespace mlir::rvsdg;
1320 
1321  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1322  auto graph = &rvsdgModule->Rvsdg();
1323 
1324  {
1325  auto functionType = jlm::rvsdg::FunctionType::Create(
1327  {});
1328  auto lambda = jlm::rvsdg::LambdaNode::Create(
1329  graph->GetRootRegion(),
1330  LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
1331  auto iOStateArgument = lambda->GetFunctionArguments().at(0);
1332  auto memoryStateArgument = lambda->GetFunctionArguments().at(1);
1333  auto pointerArgument = lambda->GetFunctionArguments().at(2);
1334 
1335  // Create load operation
1336  auto freeOp =
1337  jlm::llvm::FreeOperation::Create(pointerArgument, { memoryStateArgument }, iOStateArgument);
1338  lambda->finalize({});
1339 
1340  // Convert the RVSDG to MLIR
1341  std::cout << "Convert to MLIR" << std::endl;
1343  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1344 
1345  // Validate the generated MLIR
1346  std::cout << "Validate MLIR" << std::endl;
1347  auto & omegaRegion = omega.getRegion();
1348  auto & omegaBlock = omegaRegion.front();
1349  auto & mlirLambda = omegaBlock.front();
1350  auto & mlirLambdaRegion = mlirLambda.getRegion(0);
1351  auto & mlirLambdaBlock = mlirLambdaRegion.front();
1352  auto & mlirOp = mlirLambdaBlock.front();
1353 
1354  EXPECT_TRUE(mlir::isa<mlir::jlm::Free>(mlirOp));
1355 
1356  auto mlirFree = mlir::cast<mlir::jlm::Free>(mlirOp);
1357  EXPECT_EQ(mlirFree.getNumOperands(), 3);
1358  EXPECT_EQ(mlirFree.getNumResults(), 2);
1359 
1360  auto inputType1 = mlirFree.getOperand(0).getType();
1361  auto inputType2 = mlirFree.getOperand(1).getType();
1362  auto inputType3 = mlirFree.getOperand(2).getType();
1363  EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(inputType1));
1364  EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(inputType2));
1365  EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(inputType3));
1366 
1367  auto outputType1 = mlirFree.getResult(0).getType();
1368  auto outputType2 = mlirFree.getResult(1).getType();
1369  EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(outputType1));
1370  EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(outputType2));
1371 
1372  // // Convert the MLIR to RVSDG and check the result
1373  std::cout << "Converting MLIR to RVSDG" << std::endl;
1374  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1375  rootBlock->push_back(omega);
1376  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1377  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1378 
1379  {
1380  using namespace jlm::llvm;
1381 
1382  EXPECT_EQ(region->numNodes(), 1);
1383  auto convertedLambda =
1384  jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
1385  EXPECT_TRUE(is<jlm::rvsdg::LambdaOperation>(convertedLambda));
1386 
1387  EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1);
1388  EXPECT_TRUE(is<FreeOperation>(convertedLambda->subregion()->Nodes().begin()->GetOperation()));
1389  auto convertedFree = dynamic_cast<const FreeOperation *>(
1390  &convertedLambda->subregion()->Nodes().begin()->GetOperation());
1391 
1392  EXPECT_EQ(convertedFree->narguments(), 3);
1393  EXPECT_EQ(convertedFree->nresults(), 2);
1394 
1395  EXPECT_TRUE(is<jlm::llvm::PointerType>(convertedFree->argument(0)));
1396  EXPECT_TRUE(is<jlm::llvm::MemoryStateType>(convertedFree->argument(1)));
1397  EXPECT_TRUE(is<jlm::llvm::IOStateType>(convertedFree->argument(2)));
1398 
1399  EXPECT_TRUE(is<jlm::llvm::MemoryStateType>(convertedFree->result(0)));
1400  EXPECT_TRUE(is<jlm::llvm::IOStateType>(convertedFree->result(1)));
1401  }
1402  }
1403 }
1404 
1405 TEST(JlmToMlirToJlmTests, TestFunctionGraphImport)
1406 {
1407  using namespace jlm::llvm;
1408  using namespace mlir::rvsdg;
1409 
1410  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1411  auto graph = &rvsdgModule->Rvsdg();
1412 
1413  {
1414  auto functionType = jlm::rvsdg::FunctionType::Create(
1417 
1418  [[maybe_unused]] auto & testImport = jlm::llvm::LlvmGraphImport::createFunctionImport(
1419  *graph,
1420  functionType,
1421  "test",
1424 
1425  // Convert the RVSDG to MLIR
1426  std::cout << "Convert to MLIR" << std::endl;
1428  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1429 
1430  // Validate the generated MLIR
1431  std::cout << "Validate MLIR" << std::endl;
1432  auto & omegaRegion = omega.getRegion();
1433  auto & omegaBlock = omegaRegion.front();
1434  auto & mlirOp = omegaBlock.front();
1435 
1436  EXPECT_TRUE(mlir::isa<mlir::rvsdg::OmegaArgument>(mlirOp));
1437 
1438  auto mlirOmegaArgument = mlir::cast<mlir::rvsdg::OmegaArgument>(mlirOp);
1439 
1440  auto valueType = mlirOmegaArgument.getValueType();
1441  auto importedValueType = mlirOmegaArgument.getImportedValue().getType();
1442  auto linkage = mlirOmegaArgument.getLinkage();
1443  auto name = mlirOmegaArgument.getName();
1444 
1445  auto mlirFunctionType = valueType.dyn_cast<mlir::FunctionType>();
1446  auto mlirImportedFunctionType = importedValueType.dyn_cast<mlir::FunctionType>();
1447  EXPECT_NE(mlirFunctionType, nullptr);
1448  EXPECT_NE(mlirImportedFunctionType, nullptr);
1449  EXPECT_EQ(mlirFunctionType, mlirImportedFunctionType);
1450  EXPECT_EQ(mlirFunctionType.getNumInputs(), 3);
1451  EXPECT_EQ(mlirFunctionType.getNumResults(), 2);
1452  EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(mlirFunctionType.getInput(0)));
1453  EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(mlirFunctionType.getInput(1)));
1454  EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(mlirFunctionType.getInput(2)));
1455  EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(mlirFunctionType.getResult(0)));
1456  EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(mlirFunctionType.getResult(1)));
1457  EXPECT_EQ(linkage, "external_linkage");
1458  EXPECT_EQ(name, "test");
1459 
1460  // // Convert the MLIR to RVSDG and check the result
1461  std::cout << "Converting MLIR to RVSDG" << std::endl;
1462  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1463  rootBlock->push_back(omega);
1464  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1465  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1466 
1467  {
1468  using namespace jlm::llvm;
1469 
1470  EXPECT_EQ(region->numNodes(), 0);
1471 
1472  EXPECT_EQ(region->graph()->GetRootRegion().narguments(), 1);
1473  auto arg = region->graph()->GetRootRegion().argument(0);
1474  auto imp = dynamic_cast<jlm::llvm::LlvmGraphImport *>(arg);
1475  EXPECT_NE(imp, nullptr);
1476  EXPECT_EQ(imp->Name(), "test");
1477  EXPECT_EQ(imp->linkage(), Linkage::externalLinkage);
1478  EXPECT_EQ(*imp->ValueType(), *functionType);
1479  EXPECT_EQ(*imp->ImportedType(), *functionType);
1480  }
1481  }
1482 }
1483 
1484 TEST(JlmToMlirToJlmTests, TestPointerGraphImport)
1485 {
1486  using namespace jlm::llvm;
1487  using namespace mlir::rvsdg;
1488 
1489  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1490  auto graph = &rvsdgModule->Rvsdg();
1491 
1492  {
1493  [[maybe_unused]] auto & testImport = jlm::llvm::LlvmGraphImport::createGlobalImport(
1494  *graph,
1497  "test",
1499  false,
1500  4);
1501 
1502  // Convert the RVSDG to MLIR
1503  std::cout << "Convert to MLIR" << std::endl;
1505  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1506 
1507  // Validate the generated MLIR
1508  std::cout << "Validate MLIR" << std::endl;
1509  auto & omegaRegion = omega.getRegion();
1510  auto & omegaBlock = omegaRegion.front();
1511  auto & mlirOp = omegaBlock.front();
1512 
1513  EXPECT_TRUE(mlir::isa<mlir::rvsdg::OmegaArgument>(mlirOp));
1514 
1515  auto mlirOmegaArgument = mlir::cast<mlir::rvsdg::OmegaArgument>(mlirOp);
1516 
1517  auto valueType = mlirOmegaArgument.getValueType();
1518  auto importedValueType = mlirOmegaArgument.getImportedValue().getType();
1519  auto linkage = mlirOmegaArgument.getLinkage();
1520  auto name = mlirOmegaArgument.getName();
1521 
1522  EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(importedValueType));
1523 
1524  auto mlirIntType = valueType.dyn_cast<mlir::IntegerType>();
1525  EXPECT_NE(mlirIntType, nullptr);
1526  EXPECT_EQ(mlirIntType.getWidth(), 32);
1527  EXPECT_EQ(linkage, "external_linkage");
1528  EXPECT_EQ(name, "test");
1529 
1530  // // Convert the MLIR to RVSDG and check the result
1531  std::cout << "Converting MLIR to RVSDG" << std::endl;
1532  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1533  rootBlock->push_back(omega);
1534  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1535  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1536 
1537  {
1538  using namespace jlm::llvm;
1539 
1540  EXPECT_EQ(region->numNodes(), 0);
1541 
1542  EXPECT_EQ(region->graph()->GetRootRegion().narguments(), 1);
1543  auto arg = region->graph()->GetRootRegion().argument(0);
1544  auto imp = dynamic_cast<jlm::llvm::LlvmGraphImport *>(arg);
1545  EXPECT_NE(imp, nullptr);
1546  EXPECT_EQ(imp->Name(), "test");
1547  EXPECT_EQ(imp->linkage(), Linkage::externalLinkage);
1548  EXPECT_EQ(*imp->ValueType(), *jlm::rvsdg::BitType::Create(32));
1549  EXPECT_EQ(*imp->ImportedType(), *PointerType::Create());
1550  }
1551  }
1552 }
1553 
1554 // Add IOBarrier test near the end of the file, before the last test registrations
1555 TEST(JlmToMlirToJlmTests, TestIOBarrier)
1556 {
1557  using namespace jlm::llvm;
1558  using namespace mlir::rvsdg;
1559 
1560  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1561  auto graph = &rvsdgModule->Rvsdg();
1562 
1563  {
1564  // Create a function to contain the test
1565  auto functionType = jlm::rvsdg::FunctionType::Create({ IOStateType::Create() }, {});
1566 
1567  auto lambda = jlm::rvsdg::LambdaNode::Create(
1568  graph->GetRootRegion(),
1569  LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
1570  auto ioStateArgument = lambda->GetFunctionArguments()[0];
1571 
1572  // Create a value to pass through the barrier
1573  auto value = &jlm::rvsdg::BitConstantOperation::create(*lambda->subregion(), { 32, 42 });
1574 
1575  // Create the IOBarrier operation
1576  jlm::rvsdg::CreateOpNode<jlm::llvm::IOBarrierOperation>(
1577  { value, ioStateArgument },
1579 
1580  // Finalize the lambda
1581  lambda->finalize({});
1582 
1583  // Convert the RVSDG to MLIR
1584  std::cout << "Convert to MLIR" << std::endl;
1586  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1587 
1588  // Validate the generated MLIR
1589  std::cout << "Validate MLIR" << std::endl;
1590  auto & omegaRegion = omega.getRegion();
1591  EXPECT_EQ(omegaRegion.getBlocks().size(), 1);
1592  auto & omegaBlock = omegaRegion.front();
1593  auto & mlirLambda = omegaBlock.front();
1594  auto & mlirLambdaRegion = mlirLambda.getRegion(0);
1595  auto & mlirLambdaBlock = mlirLambdaRegion.front();
1596 
1597  // Check for lambda operation
1598  bool foundIOBarrier = false;
1599  for (auto & lambdaOp : mlirLambdaBlock.getOperations())
1600  {
1601  if (auto ioBarrier = mlir::dyn_cast<mlir::jlm::IOBarrier>(&lambdaOp))
1602  {
1603  foundIOBarrier = true;
1604 
1605  // Check that the IOBarrier has 2 operands (value and IO state)
1606  EXPECT_EQ(ioBarrier->getNumOperands(), 2);
1607 
1608  // Check that the first operand is a 32-bit integer
1609  auto valueType = ioBarrier->getOperand(0).getType().dyn_cast<mlir::IntegerType>();
1610  EXPECT_NE(valueType, nullptr);
1611  EXPECT_EQ(valueType.getWidth(), 32);
1612  EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(ioBarrier->getOperand(1).getType()));
1613 
1614  // Check that the result type matches the input value type
1615  auto resultType = ioBarrier->getResult(0).getType().dyn_cast<mlir::IntegerType>();
1616  EXPECT_NE(resultType, nullptr);
1617  EXPECT_EQ(resultType.getWidth(), 32);
1618  }
1619  }
1620  EXPECT_TRUE(foundIOBarrier);
1621 
1622  // Convert the MLIR to RVSDG and check the result
1623  std::cout << "Converting MLIR to RVSDG" << std::endl;
1624  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1625  rootBlock->push_back(omega);
1626  auto convertedRvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1627  auto region = &convertedRvsdgModule->Rvsdg().GetRootRegion();
1628 
1629  {
1630  using namespace jlm::llvm;
1631 
1632  // Direct access to the lambda node
1633  EXPECT_EQ(region->numNodes(), 1);
1634  auto & lambdaNode = *region->Nodes().begin();
1635  auto lambdaOperation = dynamic_cast<const jlm::rvsdg::LambdaNode *>(&lambdaNode);
1636  EXPECT_NE(lambdaOperation, nullptr);
1637 
1638  // Find the IOBarrier in the lambda subregion
1639  bool foundIOBarrier = false;
1640  for (auto & lambdaNode : lambdaOperation->subregion()->Nodes())
1641  {
1642  auto ioBarrierOp = dynamic_cast<const IOBarrierOperation *>(&lambdaNode.GetOperation());
1643  if (ioBarrierOp)
1644  {
1645  foundIOBarrier = true;
1646 
1647  // Check that it has correct number of inputs and outputs
1648  EXPECT_EQ(ioBarrierOp->nresults(), 1);
1649  EXPECT_EQ(ioBarrierOp->narguments(), 2);
1650 
1651  // Check that the first input is the 32-bit value
1652  auto valueType =
1653  dynamic_cast<const jlm::rvsdg::BitType *>(ioBarrierOp->argument(0).get());
1654  EXPECT_NE(valueType, nullptr);
1655  EXPECT_EQ(valueType->nbits(), 32);
1656 
1657  // Check that the second input is an IO state
1658  auto ioStateType = dynamic_cast<const IOStateType *>(ioBarrierOp->argument(1).get());
1659  EXPECT_NE(ioStateType, nullptr);
1660 
1661  // Check that the output type matches the input value type
1662  auto outputType = dynamic_cast<const jlm::rvsdg::BitType *>(ioBarrierOp->result(0).get());
1663  EXPECT_NE(outputType, nullptr);
1664  EXPECT_EQ(outputType->nbits(), 32);
1665  }
1666  }
1667  EXPECT_TRUE(foundIOBarrier);
1668  }
1669  }
1670 }
1671 
1672 TEST(JlmToMlirToJlmTests, TestMalloc)
1673 {
1674  using namespace jlm::llvm;
1675  using namespace mlir::rvsdg;
1676 
1677  auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1678  auto graph = &rvsdgModule->Rvsdg();
1679 
1680  {
1681  auto constOp = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 64, 2 });
1682  auto undefIOState = UndefValueOperation::Create(graph->GetRootRegion(), IOStateType::Create());
1683  MallocOperation::createNode(*constOp, *undefIOState);
1684 
1685  // Convert the RVSDG to MLIR
1686  std::cout << "Convert to MLIR" << std::endl;
1688  auto omega = mlirgen.ConvertModule(*rvsdgModule);
1689 
1690  // Validate the generated MLIR
1691  std::cout << "Validate MLIR" << std::endl;
1692  auto & omegaRegion = omega.getRegion();
1693  auto & omegaBlock = omegaRegion.front();
1694  bool foundMallocOp = false;
1695  for (auto & op : omegaBlock.getOperations())
1696  {
1697  auto mlirMallocOp = ::mlir::dyn_cast<::mlir::jlm::Malloc>(&op);
1698  if (mlirMallocOp)
1699  {
1700  auto inputBitType = mlirMallocOp.getOperand(0).getType().dyn_cast<mlir::IntegerType>();
1701  EXPECT_NE(inputBitType, nullptr);
1702  EXPECT_EQ(inputBitType.getWidth(), 64);
1703  EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(mlirMallocOp.getResult(0).getType()));
1704  EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(mlirMallocOp.getResult(1).getType()));
1705  EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(mlirMallocOp.getResult(2).getType()));
1706  foundMallocOp = true;
1707  }
1708  }
1709  EXPECT_TRUE(foundMallocOp);
1710 
1711  // // Convert the MLIR to RVSDG and check the result
1712  std::cout << "Converting MLIR to RVSDG" << std::endl;
1713  std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1714  rootBlock->push_back(omega);
1715  auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1716  auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1717 
1718  {
1719  using namespace jlm::llvm;
1720 
1721  EXPECT_EQ(region->numNodes(), 3);
1722  bool foundMallocOp = false;
1723  for (auto & node : region->Nodes())
1724  {
1725  auto convertedMallocOp = dynamic_cast<const MallocOperation *>(&node.GetOperation());
1726  if (convertedMallocOp)
1727  {
1728  EXPECT_EQ(convertedMallocOp->nresults(), 3);
1729  EXPECT_EQ(convertedMallocOp->narguments(), 2);
1730  auto inputBitType = jlm::util::assertedCast<const jlm::rvsdg::BitType>(
1731  convertedMallocOp->argument(0).get());
1732  EXPECT_EQ(inputBitType->nbits(), 64);
1733  EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::PointerType>(convertedMallocOp->result(0)));
1734  EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::IOStateType>(convertedMallocOp->result(1)));
1735  EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::MemoryStateType>(convertedMallocOp->result(2)));
1736  foundMallocOp = true;
1737  }
1738  }
1739  EXPECT_TRUE(foundMallocOp);
1740  }
1741  }
1742 }
TEST(JlmToMlirToJlmTests, TestUndef)
static std::shared_ptr< const ArrayType > Create(std::shared_ptr< const Type > type, size_t nelements)
Definition: types.hpp:98
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< 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 std::shared_ptr< const FloatingPointType > Create(fpsize size)
Definition: types.cpp:117
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *pointer, const std::vector< const Variable * > &memoryStates, const Variable *iOState)
Definition: operators.hpp:2558
static rvsdg::Output * create(rvsdg::Output *baseAddress, const std::vector< rvsdg::Output * > &indices, std::shared_ptr< const rvsdg::Type > pointeeType)
Input/Output state type.
Definition: types.hpp:449
static std::shared_ptr< const IOStateType > Create()
Definition: types.cpp:343
static LlvmGraphImport & createGlobalImport(rvsdg::Graph &graph, std::shared_ptr< const rvsdg::Type > valueType, std::shared_ptr< const rvsdg::Type > importedType, std::string name, Linkage linkage, const bool isConstant, const size_t alignment)
static LlvmGraphImport & createFunctionImport(rvsdg::Graph &graph, std::shared_ptr< const rvsdg::FunctionType > functionType, std::string name, Linkage linkage, CallingConvention callingConvention)
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 std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *state, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
Definition: Load.hpp:444
static rvsdg::SimpleNode & createNode(rvsdg::Output &size, rvsdg::Output &ioState)
Definition: operators.hpp:2493
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 std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
Definition: Store.hpp:304
UndefValueOperation class.
Definition: operators.hpp:1023
static jlm::rvsdg::Output * Create(rvsdg::Region &region, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1055
static rvsdg::Output * Create(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands)
Definition: operators.hpp:1531
::mlir::rvsdg::OmegaNode ConvertModule(const llvm::LlvmRvsdgModule &rvsdgModule)
static std::unique_ptr< llvm::LlvmRvsdgModule > CreateAndConvert(std::unique_ptr<::mlir::Block > &block)
static Output & create(Region &region, BitValueRepresentation value)
Definition: constant.hpp:44
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
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)
Lambda node.
Definition: lambda.hpp:83
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition: lambda.cpp:140
Global memory state passed between functions.