Jlm
Loading...
Searching...
No Matches
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
19TEST(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(), 1u);
40 auto & omegaBlock = omegaRegion.front();
41 // 1 undef + omegaResult
42 EXPECT_EQ(omegaBlock.getOperations().size(), 2u);
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(), 1u);
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(), 32u);
68 }
69 }
70}
71
72TEST(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;
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(), 1u);
101 auto & omegaBlock = omegaRegion.front();
102
103 // Bit-contant + alloca + omegaResult
104 EXPECT_EQ(omegaBlock.getOperations().size(), 3u);
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(), 4u);
113 EXPECT_EQ(mlirAllocaOp.getNumResults(), 2u);
114
115 auto valueType = mlir::cast<mlir::IntegerType>(mlirAllocaOp.getValueType());
116 EXPECT_NE(valueType, nullptr);
117 EXPECT_EQ(valueType.getWidth(), 64u);
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(), 2u);
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(), 4u);
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(), 64u);
146
147 EXPECT_EQ(allocaOp->narguments(), 1u);
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(), 32u);
153
154 EXPECT_EQ(allocaOp->nresults(), 2u);
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
167TEST(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(
177 { IOStateType::Create(), MemoryStateType::Create(), PointerType::Create() },
178 { IOStateType::Create(), MemoryStateType::Create() });
179 auto lambda = jlm::rvsdg::LambdaNode::Create(
180 graph->GetRootRegion(),
181 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
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());
190 LoadNonVolatileOperation::Create(
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(), 4u);
215 EXPECT_EQ(mlirLoad.getInputMemStates().size(), 1u);
216 EXPECT_EQ(mlirLoad.getNumOperands(), 2u);
217 EXPECT_EQ(mlirLoad.getNumResults(), 2u);
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(), 32u);
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(), 1u);
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(), 1u);
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(), 4u);
247 EXPECT_EQ(loadOperation->NumMemoryStates(), 1u);
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(), 32u);
258 }
259 }
260}
261
262TEST(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(
273 { IOStateType::Create(), MemoryStateType::Create(), PointerType::Create(), bitsType },
274 { IOStateType::Create(), MemoryStateType::Create() });
275 auto lambda = jlm::rvsdg::LambdaNode::Create(
276 graph->GetRootRegion(),
277 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
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(), 4u);
310 EXPECT_EQ(mlirStore.getInputMemStates().size(), 1u);
311 EXPECT_EQ(mlirStore.getNumOperands(), 3u);
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(), 32u);
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(), 1u);
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(), 1u);
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(), 4u);
341 EXPECT_EQ(convertedStoreOperation->NumMemoryStates(), 1u);
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(), 32u);
352 }
353 }
354}
355
356TEST(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(),
369 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
370 auto bitsArgument = lambda->GetFunctionArguments().at(0);
371
372 // Create sext operation
373 auto & sextOp = jlm::llvm::SExtOperation::create((size_t)64, *bitsArgument);
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(), 1u);
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(), 1u);
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(), 64u);
423 EXPECT_EQ(convertedSext->nsrcbits(), 32u);
424 EXPECT_EQ(convertedSext->nresults(), 1u);
425 }
426 }
427}
428
429TEST(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(),
443 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
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(), 1u);
484 auto convertedLambda =
485 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
486 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1u);
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
498TEST(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(),
509 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
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(), 1u);
540 auto convertedLambda =
541 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
542 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1u);
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
553TEST(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(),
567 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
568
569 auto floatArgument1 = lambda->GetFunctionArguments().at(0);
570 auto floatArgument2 = lambda->GetFunctionArguments().at(1);
571
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(), 1u);
618 auto convertedLambda =
619 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
620 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1u);
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(), 1u);
627 EXPECT_EQ(convertedFpbin->narguments(), 2u);
628 }
629 }
630 }
631}
632
633TEST(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(),
646 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
647
648 auto floatArgument1 = lambda->GetFunctionArguments().at(0);
649 auto floatArgument2 = lambda->GetFunctionArguments().at(1);
650 auto floatArgument3 = lambda->GetFunctionArguments().at(2);
651
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(), 1u);
677 auto convertedLambda =
678 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
679 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1u);
680 const auto arguments = convertedLambda->GetFunctionArguments();
681 const auto results = convertedLambda->GetFunctionResults();
682 EXPECT_EQ(arguments.size(), 3u);
683 EXPECT_EQ(results.size(), 1u);
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
694TEST(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(),
708 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
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(), 2u);
739
740 auto indices = mlirGep.getIndices();
741 EXPECT_EQ(indices.size(), 2u);
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(), 32u);
749 EXPECT_EQ(index1.getType().getIntOrFloatBitWidth(), 32u);
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(), 1u);
762 auto convertedLambda =
763 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
764 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1u);
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
778TEST(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(),
790 LlvmDeltaOperation::Create(
791 bitType,
792 "non-constant-delta",
793 Linkage::externalLinkage,
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(),
803 LlvmDeltaOperation::Create(
804 bitType,
805 "constant-delta",
806 Linkage::externalLinkage,
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(), 3u); // 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(), 1u);
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(), 2u);
864 for (auto & node : region->Nodes())
865 {
866 auto convertedDelta = jlm::util::assertedCast<jlm::rvsdg::DeltaNode>(&node);
867 EXPECT_EQ(convertedDelta->subregion()->numNodes(), 1u);
868 auto dop = jlm::util::assertedCast<const LlvmDeltaOperation>(&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
890TEST(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::ConstantDataArrayOperation::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(), 2u);
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(), 2u);
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(), 3u);
945 bool foundConstantDataArray = false;
946 for (auto & node : region->Nodes())
947 {
948 if (auto constantDataArray =
949 dynamic_cast<const ConstantDataArrayOperation *>(&node.GetOperation()))
950 {
951 foundConstantDataArray = true;
952 EXPECT_EQ(constantDataArray->nresults(), 1u);
953 EXPECT_EQ(constantDataArray->narguments(), 2u);
954 auto resultType = constantDataArray->result(0);
955 auto arrayType = dynamic_cast<const jlm::llvm::ArrayType *>(resultType.get());
956 EXPECT_NE(arrayType, nullptr);
957 EXPECT_TRUE(is<jlm::rvsdg::BitType>(arrayType->element_type()));
958 EXPECT_EQ(arrayType->nelements(), 2u);
959 EXPECT_TRUE(is<jlm::rvsdg::BitType>(constantDataArray->argument(0)));
960 EXPECT_TRUE(is<jlm::rvsdg::BitType>(constantDataArray->argument(1)));
961 }
962 }
963 EXPECT_TRUE(foundConstantDataArray);
964 }
965 }
966}
967
968TEST(JlmToMlirToJlmTests, TestConstantAggregateZero)
969{
970 using namespace jlm::llvm;
971 using namespace mlir::rvsdg;
972
973 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
974 auto graph = &rvsdgModule->Rvsdg();
975
976 {
977 auto bitType = jlm::rvsdg::BitType::Create(32);
978 auto arrayType = jlm::llvm::ArrayType::Create(bitType, 2);
979 ConstantAggregateZeroOperation::Create(graph->GetRootRegion(), arrayType);
980
981 // Convert the RVSDG to MLIR
982 std::cout << "Convert to MLIR" << std::endl;
984 auto omega = mlirgen.ConvertModule(*rvsdgModule);
985
986 // Validate the generated MLIR
987 std::cout << "Validate MLIR" << std::endl;
988 auto & omegaRegion = omega.getRegion();
989 auto & omegaBlock = omegaRegion.front();
990 auto mlirConstantAggregateZero = ::mlir::dyn_cast<::mlir::LLVM::ZeroOp>(&omegaBlock.front());
991 EXPECT_NE(mlirConstantAggregateZero, nullptr);
992 auto mlirConstantAggregateZeroResultType =
993 mlirConstantAggregateZero.getType().dyn_cast<mlir::LLVM::LLVMArrayType>();
994 EXPECT_NE(mlirConstantAggregateZeroResultType, nullptr);
995 EXPECT_TRUE(mlirConstantAggregateZeroResultType.getElementType().isa<mlir::IntegerType>());
996 EXPECT_EQ(mlirConstantAggregateZeroResultType.getNumElements(), 2u);
997
998 // // Convert the MLIR to RVSDG and check the result
999 std::cout << "Converting MLIR to RVSDG" << std::endl;
1000 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1001 rootBlock->push_back(omega);
1002 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1003 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1004
1005 {
1006 using namespace jlm::llvm;
1007
1008 EXPECT_EQ(region->numNodes(), 1u);
1009 auto const convertedConstantAggregateZero =
1010 jlm::util::assertedCast<const ConstantAggregateZeroOperation>(
1011 &region->Nodes().begin().ptr()->GetOperation());
1012 EXPECT_EQ(convertedConstantAggregateZero->nresults(), 1u);
1013 EXPECT_EQ(convertedConstantAggregateZero->narguments(), 0u);
1014 auto resultType = convertedConstantAggregateZero->result(0);
1015 auto arrayType = dynamic_cast<const jlm::llvm::ArrayType *>(resultType.get());
1016 EXPECT_NE(arrayType, nullptr);
1017 EXPECT_TRUE(is<jlm::rvsdg::BitType>(arrayType->element_type()));
1018 EXPECT_EQ(arrayType->nelements(), 2u);
1019 }
1020 }
1021}
1022
1023TEST(JlmToMlirToJlmTests, TestVarArgList)
1024{
1025 using namespace jlm::llvm;
1026 using namespace mlir::rvsdg;
1027
1028 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1029 auto graph = &rvsdgModule->Rvsdg();
1030
1031 {
1032 auto bitType = jlm::rvsdg::BitType::Create(32);
1033 auto bits1 = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 32, 1 });
1034 auto bits2 = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 32, 2 });
1035 jlm::llvm::VariadicArgumentListOperation::Create(graph->GetRootRegion(), { bits1, bits2 });
1036
1037 // Convert the RVSDG to MLIR
1038 std::cout << "Convert to MLIR" << std::endl;
1040 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1041
1042 // Validate the generated MLIR
1043 std::cout << "Validate MLIR" << std::endl;
1044 auto & omegaRegion = omega.getRegion();
1045 auto & omegaBlock = omegaRegion.front();
1046 bool foundVarArgOp = false;
1047 for (auto & op : omegaBlock.getOperations())
1048 {
1049 auto mlirVarArgOp = ::mlir::dyn_cast<::mlir::jlm::CreateVarArgList>(&op);
1050 if (mlirVarArgOp)
1051 {
1052 EXPECT_EQ(mlirVarArgOp.getOperands().size(), 2u);
1053 EXPECT_TRUE(mlirVarArgOp.getOperands()[0].getType().isa<mlir::IntegerType>());
1054 EXPECT_TRUE(mlirVarArgOp.getOperands()[1].getType().isa<mlir::IntegerType>());
1055 EXPECT_TRUE(mlirVarArgOp.getResult().getType().isa<mlir::jlm::VarargListType>());
1056 foundVarArgOp = true;
1057 }
1058 }
1059 EXPECT_TRUE(foundVarArgOp);
1060
1061 // // Convert the MLIR to RVSDG and check the result
1062 std::cout << "Converting MLIR to RVSDG" << std::endl;
1063 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1064 rootBlock->push_back(omega);
1065 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1066 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1067
1068 {
1069 using namespace jlm::llvm;
1070
1071 EXPECT_EQ(region->numNodes(), 3u);
1072 bool foundVarArgOp = false;
1073 for (auto & node : region->Nodes())
1074 {
1075 auto convertedVarArgOp =
1076 dynamic_cast<const VariadicArgumentListOperation *>(&node.GetOperation());
1077 if (convertedVarArgOp)
1078 {
1079 EXPECT_EQ(convertedVarArgOp->nresults(), 1u);
1080 EXPECT_EQ(convertedVarArgOp->narguments(), 2u);
1081 auto resultType = convertedVarArgOp->result(0);
1082 EXPECT_TRUE(is<jlm::llvm::VariableArgumentType>(resultType));
1083 EXPECT_TRUE(is<jlm::rvsdg::BitType>(convertedVarArgOp->argument(0)));
1084 EXPECT_TRUE(is<jlm::rvsdg::BitType>(convertedVarArgOp->argument(1)));
1085 foundVarArgOp = true;
1086 }
1087 }
1088 EXPECT_TRUE(foundVarArgOp);
1089 }
1090 }
1091}
1092
1093TEST(JlmToMlirToJlmTests, TestFNeg)
1094{
1095 using namespace jlm::llvm;
1096 using namespace mlir::rvsdg;
1097
1098 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1099 auto graph = &rvsdgModule->Rvsdg();
1100
1101 {
1103 auto & constNode = jlm::rvsdg::CreateOpNode<ConstantFP>(
1104 graph->GetRootRegion(),
1105 floatType,
1106 ::llvm::APFloat(2.0));
1108
1109 // Convert the RVSDG to MLIR
1110 std::cout << "Convert to MLIR" << std::endl;
1112 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1113
1114 // Validate the generated MLIR
1115 std::cout << "Validate MLIR" << std::endl;
1116 auto & omegaRegion = omega.getRegion();
1117 auto & omegaBlock = omegaRegion.front();
1118 bool foundFNegOp = false;
1119 for (auto & op : omegaBlock.getOperations())
1120 {
1121 auto mlirFNegOp = ::mlir::dyn_cast<::mlir::arith::NegFOp>(&op);
1122 if (mlirFNegOp)
1123 {
1124 auto inputFloatType = mlirFNegOp.getOperand().getType().dyn_cast<mlir::FloatType>();
1125 EXPECT_NE(inputFloatType, nullptr);
1126 EXPECT_EQ(inputFloatType.getWidth(), 32u);
1127 auto outputFloatType = mlirFNegOp.getResult().getType().dyn_cast<mlir::FloatType>();
1128 EXPECT_NE(outputFloatType, nullptr);
1129 EXPECT_EQ(outputFloatType.getWidth(), 32u);
1130 foundFNegOp = true;
1131 }
1132 }
1133 EXPECT_TRUE(foundFNegOp);
1134
1135 // // Convert the MLIR to RVSDG and check the result
1136 std::cout << "Converting MLIR to RVSDG" << std::endl;
1137 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1138 rootBlock->push_back(omega);
1139 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1140 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1141
1142 {
1143 using namespace jlm::llvm;
1144
1145 EXPECT_EQ(region->numNodes(), 2u);
1146 bool foundFNegOp = false;
1147 for (auto & node : region->Nodes())
1148 {
1149 auto convertedFNegOp = dynamic_cast<const FNegOperation *>(&node.GetOperation());
1150 if (convertedFNegOp)
1151 {
1152 EXPECT_EQ(convertedFNegOp->nresults(), 1u);
1153 EXPECT_EQ(convertedFNegOp->narguments(), 1u);
1154 auto inputFloatType = jlm::util::assertedCast<const jlm::llvm::FloatingPointType>(
1155 convertedFNegOp->argument(0).get());
1156 EXPECT_EQ(inputFloatType->size(), jlm::llvm::fpsize::flt);
1157 auto outputFloatType = jlm::util::assertedCast<const jlm::llvm::FloatingPointType>(
1158 convertedFNegOp->result(0).get());
1159 EXPECT_EQ(outputFloatType->size(), jlm::llvm::fpsize::flt);
1160 foundFNegOp = true;
1161 }
1162 }
1163 EXPECT_TRUE(foundFNegOp);
1164 }
1165 }
1166}
1167
1168TEST(JlmToMlirToJlmTests, TestFPExt)
1169{
1170 using namespace jlm::llvm;
1171 using namespace mlir::rvsdg;
1172
1173 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1174 auto graph = &rvsdgModule->Rvsdg();
1175
1176 {
1179 auto & constNode = jlm::rvsdg::CreateOpNode<ConstantFP>(
1180 graph->GetRootRegion(),
1181 floatType1,
1182 ::llvm::APFloat(2.0));
1183 jlm::rvsdg::CreateOpNode<FPExtOperation>({ constNode.output(0) }, floatType1, floatType2);
1184
1185 // Convert the RVSDG to MLIR
1186 std::cout << "Convert to MLIR" << std::endl;
1188 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1189
1190 // Validate the generated MLIR
1191 std::cout << "Validate MLIR" << std::endl;
1192 auto & omegaRegion = omega.getRegion();
1193 auto & omegaBlock = omegaRegion.front();
1194 bool foundFPExtOp = false;
1195 for (auto & op : omegaBlock.getOperations())
1196 {
1197 auto mlirFPExtOp = ::mlir::dyn_cast<::mlir::arith::ExtFOp>(&op);
1198 if (mlirFPExtOp)
1199 {
1200 auto inputFloatType = mlirFPExtOp.getOperand().getType().dyn_cast<mlir::FloatType>();
1201 EXPECT_NE(inputFloatType, nullptr);
1202 EXPECT_EQ(inputFloatType.getWidth(), 32u);
1203 auto outputFloatType = mlirFPExtOp.getResult().getType().dyn_cast<mlir::FloatType>();
1204 EXPECT_NE(outputFloatType, nullptr);
1205 EXPECT_EQ(outputFloatType.getWidth(), 64u);
1206 foundFPExtOp = true;
1207 }
1208 }
1209 EXPECT_TRUE(foundFPExtOp);
1210
1211 // // Convert the MLIR to RVSDG and check the result
1212 std::cout << "Converting MLIR to RVSDG" << std::endl;
1213 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1214 rootBlock->push_back(omega);
1215 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1216 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1217
1218 {
1219 using namespace jlm::llvm;
1220
1221 EXPECT_EQ(region->numNodes(), 2u);
1222 bool foundFPExtOp = false;
1223 for (auto & node : region->Nodes())
1224 {
1225 auto convertedFPExtOp = dynamic_cast<const FPExtOperation *>(&node.GetOperation());
1226 if (convertedFPExtOp)
1227 {
1228 EXPECT_EQ(convertedFPExtOp->nresults(), 1u);
1229 EXPECT_EQ(convertedFPExtOp->narguments(), 1u);
1230 auto inputFloatType = jlm::util::assertedCast<const jlm::llvm::FloatingPointType>(
1231 convertedFPExtOp->argument(0).get());
1232 EXPECT_EQ(inputFloatType->size(), jlm::llvm::fpsize::flt);
1233 auto outputFloatType = jlm::util::assertedCast<const jlm::llvm::FloatingPointType>(
1234 convertedFPExtOp->result(0).get());
1235 EXPECT_EQ(outputFloatType->size(), jlm::llvm::fpsize::dbl);
1236 foundFPExtOp = true;
1237 }
1238 }
1239 EXPECT_TRUE(foundFPExtOp);
1240 }
1241 }
1242}
1243
1244TEST(JlmToMlirToJlmTests, TestTrunc)
1245{
1246 using namespace jlm::llvm;
1247 using namespace mlir::rvsdg;
1248
1249 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1250 auto graph = &rvsdgModule->Rvsdg();
1251
1252 {
1253 auto bitType1 = jlm::rvsdg::BitType::Create(64);
1254 auto bitType2 = jlm::rvsdg::BitType::Create(32);
1255 auto constOp = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 64, 2 });
1256 jlm::rvsdg::CreateOpNode<TruncOperation>({ constOp }, bitType1, bitType2);
1257
1258 // Convert the RVSDG to MLIR
1259 std::cout << "Convert to MLIR" << std::endl;
1261 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1262
1263 // Validate the generated MLIR
1264 std::cout << "Validate MLIR" << std::endl;
1265 auto & omegaRegion = omega.getRegion();
1266 auto & omegaBlock = omegaRegion.front();
1267 bool foundTruncOp = false;
1268 for (auto & op : omegaBlock.getOperations())
1269 {
1270 auto mlirTruncOp = ::mlir::dyn_cast<::mlir::arith::TruncIOp>(&op);
1271 if (mlirTruncOp)
1272 {
1273 auto inputBitType = mlirTruncOp.getOperand().getType().dyn_cast<mlir::IntegerType>();
1274 EXPECT_NE(inputBitType, nullptr);
1275 EXPECT_EQ(inputBitType.getWidth(), 64u);
1276 auto outputBitType = mlirTruncOp.getResult().getType().dyn_cast<mlir::IntegerType>();
1277 EXPECT_NE(outputBitType, nullptr);
1278 EXPECT_EQ(outputBitType.getWidth(), 32u);
1279 foundTruncOp = true;
1280 }
1281 }
1282 EXPECT_TRUE(foundTruncOp);
1283
1284 // // Convert the MLIR to RVSDG and check the result
1285 std::cout << "Converting MLIR to RVSDG" << std::endl;
1286 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1287 rootBlock->push_back(omega);
1288 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1289 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1290
1291 {
1292 using namespace jlm::llvm;
1293
1294 EXPECT_EQ(region->numNodes(), 2u);
1295 bool foundTruncOp = false;
1296 for (auto & node : region->Nodes())
1297 {
1298 auto convertedTruncOp = dynamic_cast<const TruncOperation *>(&node.GetOperation());
1299 if (convertedTruncOp)
1300 {
1301 EXPECT_EQ(convertedTruncOp->nresults(), 1u);
1302 EXPECT_EQ(convertedTruncOp->narguments(), 1u);
1303 auto inputBitType = jlm::util::assertedCast<const jlm::rvsdg::BitType>(
1304 convertedTruncOp->argument(0).get());
1305 EXPECT_EQ(inputBitType->nbits(), 64u);
1306 auto outputBitType =
1307 jlm::util::assertedCast<const jlm::rvsdg::BitType>(convertedTruncOp->result(0).get());
1308 EXPECT_EQ(outputBitType->nbits(), 32u);
1309 foundTruncOp = true;
1310 }
1311 }
1312 EXPECT_TRUE(foundTruncOp);
1313 }
1314 }
1315}
1316
1317TEST(JlmToMlirToJlmTests, TestFree)
1318{
1319 using namespace jlm::llvm;
1320 using namespace mlir::rvsdg;
1321
1322 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1323 auto graph = &rvsdgModule->Rvsdg();
1324
1325 {
1326 auto functionType = jlm::rvsdg::FunctionType::Create(
1327 { IOStateType::Create(), MemoryStateType::Create(), PointerType::Create() },
1328 {});
1329 auto lambda = jlm::rvsdg::LambdaNode::Create(
1330 graph->GetRootRegion(),
1331 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
1332 auto iOStateArgument = lambda->GetFunctionArguments().at(0);
1333 auto memoryStateArgument = lambda->GetFunctionArguments().at(1);
1334 auto pointerArgument = lambda->GetFunctionArguments().at(2);
1335
1336 // Create load operation
1337 auto freeOp =
1338 jlm::llvm::FreeOperation::Create(pointerArgument, { memoryStateArgument }, iOStateArgument);
1339 lambda->finalize({});
1340
1341 // Convert the RVSDG to MLIR
1342 std::cout << "Convert to MLIR" << std::endl;
1344 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1345
1346 // Validate the generated MLIR
1347 std::cout << "Validate MLIR" << std::endl;
1348 auto & omegaRegion = omega.getRegion();
1349 auto & omegaBlock = omegaRegion.front();
1350 auto & mlirLambda = omegaBlock.front();
1351 auto & mlirLambdaRegion = mlirLambda.getRegion(0);
1352 auto & mlirLambdaBlock = mlirLambdaRegion.front();
1353 auto & mlirOp = mlirLambdaBlock.front();
1354
1355 EXPECT_TRUE(mlir::isa<mlir::jlm::Free>(mlirOp));
1356
1357 auto mlirFree = mlir::cast<mlir::jlm::Free>(mlirOp);
1358 EXPECT_EQ(mlirFree.getNumOperands(), 3u);
1359 EXPECT_EQ(mlirFree.getNumResults(), 2u);
1360
1361 auto inputType1 = mlirFree.getOperand(0).getType();
1362 auto inputType2 = mlirFree.getOperand(1).getType();
1363 auto inputType3 = mlirFree.getOperand(2).getType();
1364 EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(inputType1));
1365 EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(inputType2));
1366 EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(inputType3));
1367
1368 auto outputType1 = mlirFree.getResult(0).getType();
1369 auto outputType2 = mlirFree.getResult(1).getType();
1370 EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(outputType1));
1371 EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(outputType2));
1372
1373 // // Convert the MLIR to RVSDG and check the result
1374 std::cout << "Converting MLIR to RVSDG" << std::endl;
1375 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1376 rootBlock->push_back(omega);
1377 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1378 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1379
1380 {
1381 using namespace jlm::llvm;
1382
1383 EXPECT_EQ(region->numNodes(), 1u);
1384 auto convertedLambda =
1385 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
1386 EXPECT_TRUE(is<jlm::rvsdg::LambdaOperation>(convertedLambda));
1387
1388 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1u);
1389 EXPECT_TRUE(is<FreeOperation>(convertedLambda->subregion()->Nodes().begin()->GetOperation()));
1390 auto convertedFree = dynamic_cast<const FreeOperation *>(
1391 &convertedLambda->subregion()->Nodes().begin()->GetOperation());
1392
1393 EXPECT_EQ(convertedFree->narguments(), 3u);
1394 EXPECT_EQ(convertedFree->nresults(), 2u);
1395
1396 EXPECT_TRUE(is<jlm::llvm::PointerType>(convertedFree->argument(0)));
1397 EXPECT_TRUE(is<jlm::llvm::MemoryStateType>(convertedFree->argument(1)));
1398 EXPECT_TRUE(is<jlm::llvm::IOStateType>(convertedFree->argument(2)));
1399
1400 EXPECT_TRUE(is<jlm::llvm::MemoryStateType>(convertedFree->result(0)));
1401 EXPECT_TRUE(is<jlm::llvm::IOStateType>(convertedFree->result(1)));
1402 }
1403 }
1404}
1405
1406TEST(JlmToMlirToJlmTests, TestFunctionGraphImport)
1407{
1408 using namespace jlm::llvm;
1409 using namespace mlir::rvsdg;
1410
1411 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1412 auto graph = &rvsdgModule->Rvsdg();
1413
1414 {
1415 auto functionType = jlm::rvsdg::FunctionType::Create(
1416 { IOStateType::Create(), MemoryStateType::Create(), PointerType::Create() },
1417 { IOStateType::Create(), MemoryStateType::Create() });
1418
1419 [[maybe_unused]] auto & testImport = jlm::llvm::LlvmGraphImport::createFunctionImport(
1420 *graph,
1421 functionType,
1422 "test",
1423 Linkage::externalLinkage,
1424 CallingConvention::Default);
1425
1426 // Convert the RVSDG to MLIR
1427 std::cout << "Convert to MLIR" << std::endl;
1429 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1430
1431 // Validate the generated MLIR
1432 std::cout << "Validate MLIR" << std::endl;
1433 auto & omegaRegion = omega.getRegion();
1434 auto & omegaBlock = omegaRegion.front();
1435 auto & mlirOp = omegaBlock.front();
1436
1437 EXPECT_TRUE(mlir::isa<mlir::rvsdg::OmegaArgument>(mlirOp));
1438
1439 auto mlirOmegaArgument = mlir::cast<mlir::rvsdg::OmegaArgument>(mlirOp);
1440
1441 auto valueType = mlirOmegaArgument.getValueType();
1442 auto importedValueType = mlirOmegaArgument.getImportedValue().getType();
1443 auto linkage = mlirOmegaArgument.getLinkage();
1444 auto name = mlirOmegaArgument.getName();
1445
1446 auto mlirFunctionType = valueType.dyn_cast<mlir::FunctionType>();
1447 auto mlirImportedFunctionType = importedValueType.dyn_cast<mlir::FunctionType>();
1448 EXPECT_NE(mlirFunctionType, nullptr);
1449 EXPECT_NE(mlirImportedFunctionType, nullptr);
1450 EXPECT_EQ(mlirFunctionType, mlirImportedFunctionType);
1451 EXPECT_EQ(mlirFunctionType.getNumInputs(), 3u);
1452 EXPECT_EQ(mlirFunctionType.getNumResults(), 2u);
1453 EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(mlirFunctionType.getInput(0)));
1454 EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(mlirFunctionType.getInput(1)));
1455 EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(mlirFunctionType.getInput(2)));
1456 EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(mlirFunctionType.getResult(0)));
1457 EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(mlirFunctionType.getResult(1)));
1458 EXPECT_EQ(linkage, "external_linkage");
1459 EXPECT_EQ(name, "test");
1460
1461 // // Convert the MLIR to RVSDG and check the result
1462 std::cout << "Converting MLIR to RVSDG" << std::endl;
1463 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1464 rootBlock->push_back(omega);
1465 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1466 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1467
1468 {
1469 using namespace jlm::llvm;
1470
1471 EXPECT_EQ(region->numNodes(), 0u);
1472
1473 EXPECT_EQ(region->graph()->GetRootRegion().narguments(), 1u);
1474 auto arg = region->graph()->GetRootRegion().argument(0);
1475 auto imp = dynamic_cast<jlm::llvm::LlvmGraphImport *>(arg);
1476 EXPECT_NE(imp, nullptr);
1477 EXPECT_EQ(imp->Name(), "test");
1478 EXPECT_EQ(imp->linkage(), Linkage::externalLinkage);
1479 EXPECT_EQ(*imp->ValueType(), *functionType);
1480 EXPECT_EQ(*imp->ImportedType(), *functionType);
1481 }
1482 }
1483}
1484
1485TEST(JlmToMlirToJlmTests, TestPointerGraphImport)
1486{
1487 using namespace jlm::llvm;
1488 using namespace mlir::rvsdg;
1489
1490 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1491 auto graph = &rvsdgModule->Rvsdg();
1492
1493 {
1494 [[maybe_unused]] auto & testImport = jlm::llvm::LlvmGraphImport::createGlobalImport(
1495 *graph,
1497 PointerType::Create(),
1498 "test",
1499 Linkage::externalLinkage,
1500 false,
1501 4);
1502
1503 // Convert the RVSDG to MLIR
1504 std::cout << "Convert to MLIR" << std::endl;
1506 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1507
1508 // Validate the generated MLIR
1509 std::cout << "Validate MLIR" << std::endl;
1510 auto & omegaRegion = omega.getRegion();
1511 auto & omegaBlock = omegaRegion.front();
1512 auto & mlirOp = omegaBlock.front();
1513
1514 EXPECT_TRUE(mlir::isa<mlir::rvsdg::OmegaArgument>(mlirOp));
1515
1516 auto mlirOmegaArgument = mlir::cast<mlir::rvsdg::OmegaArgument>(mlirOp);
1517
1518 auto valueType = mlirOmegaArgument.getValueType();
1519 auto importedValueType = mlirOmegaArgument.getImportedValue().getType();
1520 auto linkage = mlirOmegaArgument.getLinkage();
1521 auto name = mlirOmegaArgument.getName();
1522
1523 EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(importedValueType));
1524
1525 auto mlirIntType = valueType.dyn_cast<mlir::IntegerType>();
1526 EXPECT_NE(mlirIntType, nullptr);
1527 EXPECT_EQ(mlirIntType.getWidth(), 32u);
1528 EXPECT_EQ(linkage, "external_linkage");
1529 EXPECT_EQ(name, "test");
1530
1531 // // Convert the MLIR to RVSDG and check the result
1532 std::cout << "Converting MLIR to RVSDG" << std::endl;
1533 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1534 rootBlock->push_back(omega);
1535 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1536 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1537
1538 {
1539 using namespace jlm::llvm;
1540
1541 EXPECT_EQ(region->numNodes(), 0u);
1542
1543 EXPECT_EQ(region->graph()->GetRootRegion().narguments(), 1u);
1544 auto arg = region->graph()->GetRootRegion().argument(0);
1545 auto imp = dynamic_cast<jlm::llvm::LlvmGraphImport *>(arg);
1546 EXPECT_NE(imp, nullptr);
1547 EXPECT_EQ(imp->Name(), "test");
1548 EXPECT_EQ(imp->linkage(), Linkage::externalLinkage);
1549 EXPECT_EQ(*imp->ValueType(), *jlm::rvsdg::BitType::Create(32));
1550 EXPECT_EQ(*imp->ImportedType(), *PointerType::Create());
1551 }
1552 }
1553}
1554
1555// Add IOBarrier test near the end of the file, before the last test registrations
1556TEST(JlmToMlirToJlmTests, TestIOBarrier)
1557{
1558 using namespace jlm::llvm;
1559 using namespace mlir::rvsdg;
1560
1561 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1562 auto graph = &rvsdgModule->Rvsdg();
1563
1564 {
1565 // Create a function to contain the test
1566 auto functionType = jlm::rvsdg::FunctionType::Create({ IOStateType::Create() }, {});
1567
1568 auto lambda = jlm::rvsdg::LambdaNode::Create(
1569 graph->GetRootRegion(),
1570 LlvmLambdaOperation::Create(functionType, "test", Linkage::externalLinkage));
1571 auto ioStateArgument = lambda->GetFunctionArguments()[0];
1572
1573 // Create a value to pass through the barrier
1574 auto value = &jlm::rvsdg::BitConstantOperation::create(*lambda->subregion(), { 32, 42 });
1575
1576 // Create the IOBarrier operation
1578 { value, ioStateArgument },
1580
1581 // Finalize the lambda
1582 lambda->finalize({});
1583
1584 // Convert the RVSDG to MLIR
1585 std::cout << "Convert to MLIR" << std::endl;
1587 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1588
1589 // Validate the generated MLIR
1590 std::cout << "Validate MLIR" << std::endl;
1591 auto & omegaRegion = omega.getRegion();
1592 EXPECT_EQ(omegaRegion.getBlocks().size(), 1u);
1593 auto & omegaBlock = omegaRegion.front();
1594 auto & mlirLambda = omegaBlock.front();
1595 auto & mlirLambdaRegion = mlirLambda.getRegion(0);
1596 auto & mlirLambdaBlock = mlirLambdaRegion.front();
1597
1598 // Check for lambda operation
1599 bool foundIOBarrier = false;
1600 for (auto & lambdaOp : mlirLambdaBlock.getOperations())
1601 {
1602 if (auto ioBarrier = mlir::dyn_cast<mlir::jlm::IOBarrier>(&lambdaOp))
1603 {
1604 foundIOBarrier = true;
1605
1606 // Check that the IOBarrier has 2 operands (value and IO state)
1607 EXPECT_EQ(ioBarrier->getNumOperands(), 2u);
1608
1609 // Check that the first operand is a 32-bit integer
1610 auto valueType = ioBarrier->getOperand(0).getType().dyn_cast<mlir::IntegerType>();
1611 EXPECT_NE(valueType, nullptr);
1612 EXPECT_EQ(valueType.getWidth(), 32u);
1613 EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(ioBarrier->getOperand(1).getType()));
1614
1615 // Check that the result type matches the input value type
1616 auto resultType = ioBarrier->getResult(0).getType().dyn_cast<mlir::IntegerType>();
1617 EXPECT_NE(resultType, nullptr);
1618 EXPECT_EQ(resultType.getWidth(), 32u);
1619 }
1620 }
1621 EXPECT_TRUE(foundIOBarrier);
1622
1623 // Convert the MLIR to RVSDG and check the result
1624 std::cout << "Converting MLIR to RVSDG" << std::endl;
1625 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1626 rootBlock->push_back(omega);
1627 auto convertedRvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1628 auto region = &convertedRvsdgModule->Rvsdg().GetRootRegion();
1629
1630 {
1631 using namespace jlm::llvm;
1632
1633 // Direct access to the lambda node
1634 EXPECT_EQ(region->numNodes(), 1u);
1635 auto & lambdaNode = *region->Nodes().begin();
1636 auto lambdaOperation = dynamic_cast<const jlm::rvsdg::LambdaNode *>(&lambdaNode);
1637 EXPECT_NE(lambdaOperation, nullptr);
1638
1639 // Find the IOBarrier in the lambda subregion
1640 bool foundIOBarrier = false;
1641 for (auto & lambdaNode : lambdaOperation->subregion()->Nodes())
1642 {
1643 auto ioBarrierOp = dynamic_cast<const IOBarrierOperation *>(&lambdaNode.GetOperation());
1644 if (ioBarrierOp)
1645 {
1646 foundIOBarrier = true;
1647
1648 // Check that it has correct number of inputs and outputs
1649 EXPECT_EQ(ioBarrierOp->nresults(), 1u);
1650 EXPECT_EQ(ioBarrierOp->narguments(), 2u);
1651
1652 // Check that the first input is the 32-bit value
1653 auto valueType =
1654 dynamic_cast<const jlm::rvsdg::BitType *>(ioBarrierOp->argument(0).get());
1655 EXPECT_NE(valueType, nullptr);
1656 EXPECT_EQ(valueType->nbits(), 32u);
1657
1658 // Check that the second input is an IO state
1659 auto ioStateType = dynamic_cast<const IOStateType *>(ioBarrierOp->argument(1).get());
1660 EXPECT_NE(ioStateType, nullptr);
1661
1662 // Check that the output type matches the input value type
1663 auto outputType = dynamic_cast<const jlm::rvsdg::BitType *>(ioBarrierOp->result(0).get());
1664 EXPECT_NE(outputType, nullptr);
1665 EXPECT_EQ(outputType->nbits(), 32u);
1666 }
1667 }
1668 EXPECT_TRUE(foundIOBarrier);
1669 }
1670 }
1671}
1672
1673TEST(JlmToMlirToJlmTests, TestMalloc)
1674{
1675 using namespace jlm::llvm;
1676 using namespace mlir::rvsdg;
1677
1678 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
1679 auto graph = &rvsdgModule->Rvsdg();
1680
1681 {
1682 auto constOp = &jlm::rvsdg::BitConstantOperation::create(graph->GetRootRegion(), { 64, 2 });
1683 auto undefIOState = UndefValueOperation::Create(graph->GetRootRegion(), IOStateType::Create());
1684 MallocOperation::createNode(*constOp, *undefIOState);
1685
1686 // Convert the RVSDG to MLIR
1687 std::cout << "Convert to MLIR" << std::endl;
1689 auto omega = mlirgen.ConvertModule(*rvsdgModule);
1690
1691 // Validate the generated MLIR
1692 std::cout << "Validate MLIR" << std::endl;
1693 auto & omegaRegion = omega.getRegion();
1694 auto & omegaBlock = omegaRegion.front();
1695 bool foundMallocOp = false;
1696 for (auto & op : omegaBlock.getOperations())
1697 {
1698 auto mlirMallocOp = ::mlir::dyn_cast<::mlir::jlm::Malloc>(&op);
1699 if (mlirMallocOp)
1700 {
1701 auto inputBitType = mlirMallocOp.getOperand(0).getType().dyn_cast<mlir::IntegerType>();
1702 EXPECT_NE(inputBitType, nullptr);
1703 EXPECT_EQ(inputBitType.getWidth(), 64u);
1704 EXPECT_TRUE(mlir::isa<mlir::LLVM::LLVMPointerType>(mlirMallocOp.getResult(0).getType()));
1705 EXPECT_TRUE(mlir::isa<mlir::rvsdg::IOStateEdgeType>(mlirMallocOp.getResult(1).getType()));
1706 EXPECT_TRUE(mlir::isa<mlir::rvsdg::MemStateEdgeType>(mlirMallocOp.getResult(2).getType()));
1707 foundMallocOp = true;
1708 }
1709 }
1710 EXPECT_TRUE(foundMallocOp);
1711
1712 // // Convert the MLIR to RVSDG and check the result
1713 std::cout << "Converting MLIR to RVSDG" << std::endl;
1714 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1715 rootBlock->push_back(omega);
1716 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1717 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1718
1719 {
1720 using namespace jlm::llvm;
1721
1722 EXPECT_EQ(region->numNodes(), 3u);
1723 bool foundMallocOp = false;
1724 for (auto & node : region->Nodes())
1725 {
1726 auto convertedMallocOp = dynamic_cast<const MallocOperation *>(&node.GetOperation());
1727 if (convertedMallocOp)
1728 {
1729 EXPECT_EQ(convertedMallocOp->nresults(), 3u);
1730 EXPECT_EQ(convertedMallocOp->narguments(), 2u);
1731 auto inputBitType = jlm::util::assertedCast<const jlm::rvsdg::BitType>(
1732 convertedMallocOp->argument(0).get());
1733 EXPECT_EQ(inputBitType->nbits(), 64u);
1734 EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::PointerType>(convertedMallocOp->result(0)));
1735 EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::IOStateType>(convertedMallocOp->result(1)));
1736 EXPECT_TRUE(jlm::rvsdg::is<jlm::llvm::MemoryStateType>(convertedMallocOp->result(2)));
1737 foundMallocOp = true;
1738 }
1739 }
1740 EXPECT_TRUE(foundMallocOp);
1741 }
1742 }
1743}
TEST(JlmToMlirToJlmTests, TestUndef)
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 rvsdg::Output * Create(const std::vector< rvsdg::Output * > &elements)
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)
Input/Output state type.
Definition types.hpp:449
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 rvsdg::Output & create(size_t ndstbits, rvsdg::Output &operand)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
Definition Store.hpp:325
UndefValueOperation class.
static rvsdg::Output * Create(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands)
::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)
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition lambda.cpp:141
Global memory state passed between functions.
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872