Jlm
Loading...
Searching...
No Matches
MlirToJlmConverterTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2024 Louis Maurin <louis7maurin@gmail.com>
3 * Copyright 2024 Magnus Själander <work@sjalander.com>
4 * See COPYING for terms of redistribution.
5 */
6
7#include <gtest/gtest.h>
8
15
16#include <jlm/rvsdg/view.hpp>
17
18TEST(MlirToJlmConverterTests, TestLambda)
19{
20 {
21 using namespace mlir::rvsdg;
22 using namespace mlir::jlm;
23
24 // Setup MLIR Context and load dialects
25 std::cout << "Creating MLIR context" << std::endl;
26 auto context = std::make_unique<mlir::MLIRContext>();
27 context->getOrLoadDialect<RVSDGDialect>();
28 context->getOrLoadDialect<JLMDialect>();
29 context->getOrLoadDialect<mlir::arith::ArithDialect>();
30 context->getOrLoadDialect<mlir::LLVM::LLVMDialect>();
31 auto Builder_ = std::make_unique<mlir::OpBuilder>(context.get());
32
33 auto omega = Builder_->create<OmegaNode>(Builder_->getUnknownLoc());
34 auto & omegaRegion = omega.getRegion();
35 auto * omegaBlock = new mlir::Block;
36 omegaRegion.push_back(omegaBlock);
37
38 // Handle function arguments
39 std::cout << "Creating function arguments" << std::endl;
40 ::llvm::SmallVector<mlir::Type> arguments;
41 arguments.push_back(Builder_->getType<IOStateEdgeType>());
42 arguments.push_back(Builder_->getType<MemStateEdgeType>());
43 ::llvm::ArrayRef argumentsArray(arguments);
44
45 // Handle function results
46 std::cout << "Creating function results" << std::endl;
47 ::llvm::SmallVector<mlir::Type> results;
48 results.push_back(Builder_->getIntegerType(32));
49 results.push_back(Builder_->getType<IOStateEdgeType>());
50 results.push_back(Builder_->getType<MemStateEdgeType>());
51 ::llvm::ArrayRef resultsArray(results);
52
53 // Add function attributes
54 std::cout << "Creating function attributes" << std::endl;
55 ::llvm::SmallVector<mlir::NamedAttribute> attributes;
56 auto attributeName = Builder_->getStringAttr("sym_name");
57 auto attributeValue = Builder_->getStringAttr("test");
58 auto symbolName = Builder_->getNamedAttr(attributeName, attributeValue);
59 attributes.push_back(symbolName);
60 auto linkageName = Builder_->getStringAttr("linkage");
61 auto linkageValue = Builder_->getStringAttr("external_linkage");
62 auto linkage = Builder_->getNamedAttr(linkageName, linkageValue);
63 attributes.push_back(linkage);
64 ::llvm::ArrayRef<::mlir::NamedAttribute> attributesRef(attributes);
65
66 // Add inputs to the function
67 ::llvm::SmallVector<mlir::Value> inputs;
68
69 // Create the lambda node and add it to the region/block it resides in
70 std::cout << "Creating LambdaNode" << std::endl;
71 auto lambda = Builder_->create<LambdaNode>(
72 Builder_->getUnknownLoc(),
73 Builder_->getType<mlir::FunctionType>(arguments, results),
74 inputs,
75 attributesRef);
76 omegaBlock->push_back(lambda);
77 auto & lambdaRegion = lambda.getRegion();
78 auto * lambdaBlock = new mlir::Block;
79 lambdaRegion.push_back(lambdaBlock);
80
81 // Add arguments to the region
82 std::cout << "Adding arguments to the region" << std::endl;
83 lambdaBlock->addArgument(Builder_->getType<IOStateEdgeType>(), Builder_->getUnknownLoc());
84 lambdaBlock->addArgument(Builder_->getType<MemStateEdgeType>(), Builder_->getUnknownLoc());
85
86 auto constOp = Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), 1, 32);
87 lambdaBlock->push_back(constOp);
88
89 ::llvm::SmallVector<mlir::Value> regionResults;
90 regionResults.push_back(constOp);
91 regionResults.push_back(lambdaBlock->getArgument(0));
92 regionResults.push_back(lambdaBlock->getArgument(1));
93
94 // Handle the result of the lambda
95 std::cout << "Creating LambdaResult" << std::endl;
96 auto lambdaResult = Builder_->create<LambdaResult>(Builder_->getUnknownLoc(), regionResults);
97 lambdaBlock->push_back(lambdaResult);
98
99 // Handle the result of the omega
100 std::cout << "Creating OmegaResult" << std::endl;
101 ::llvm::SmallVector<mlir::Value> omegaRegionResults;
102 omegaRegionResults.push_back(lambda.getResult());
103 ::llvm::SmallVector<mlir::Type> omegaResultTypes;
104 omegaResultTypes.push_back(lambda.getResult().getType());
105
106 // Create exportNames ArrayAttr
107 ::llvm::SmallVector<::mlir::Attribute> exportNamesList;
108 exportNamesList.push_back(Builder_->getStringAttr("test"));
109 auto exportNamesAttr = ::mlir::ArrayAttr::get(Builder_->getContext(), exportNamesList);
110 ::llvm::SmallVector<::mlir::NamedAttribute> namedAttrs;
111 namedAttrs.push_back({ Builder_->getStringAttr("exportNames"), exportNamesAttr });
112
113 auto omegaResult = Builder_->create<OmegaResult>(
114 Builder_->getUnknownLoc(),
115 omegaResultTypes,
116 omegaRegionResults,
117 namedAttrs);
118 omegaBlock->push_back(omegaResult);
119
120 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
121 rootBlock->push_back(omega);
122
123 // Convert the MLIR to RVSDG and check the result
124 std::cout << "Converting MLIR to RVSDG" << std::endl;
125 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
126 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
127 {
128 using namespace jlm::rvsdg;
129 std::cout << "Checking the result" << std::endl;
130
131 EXPECT_EQ(region->numNodes(), 1u);
132 auto convertedLambda =
133 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
134 EXPECT_TRUE(is<jlm::llvm::LlvmLambdaOperation>(convertedLambda->GetOperation()));
135
136 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 1u);
137 EXPECT_TRUE(is<jlm::llvm::IntegerConstantOperation>(
138 convertedLambda->subregion()->Nodes().begin().ptr()));
139 }
140 }
141}
142
149TEST(MlirToJlmConverterTests, TestDivOperation)
150{
151 {
152 using namespace mlir::rvsdg;
153 using namespace mlir::jlm;
154
155 // Setup MLIR Context and load dialects
156 std::cout << "Creating MLIR context" << std::endl;
157 auto context = std::make_unique<mlir::MLIRContext>();
158 context->getOrLoadDialect<RVSDGDialect>();
159 context->getOrLoadDialect<JLMDialect>();
160 context->getOrLoadDialect<mlir::arith::ArithDialect>();
161 context->getOrLoadDialect<mlir::LLVM::LLVMDialect>();
162 auto Builder_ = std::make_unique<mlir::OpBuilder>(context.get());
163
164 auto omega = Builder_->create<OmegaNode>(Builder_->getUnknownLoc());
165 auto & omegaRegion = omega.getRegion();
166 auto * omegaBlock = new mlir::Block;
167 omegaRegion.push_back(omegaBlock);
168
169 // Handle function arguments
170 std::cout << "Creating function arguments" << std::endl;
171 ::llvm::SmallVector<mlir::Type> arguments;
172 arguments.push_back(Builder_->getIntegerType(32));
173 arguments.push_back(Builder_->getType<IOStateEdgeType>());
174 arguments.push_back(Builder_->getType<MemStateEdgeType>());
175 ::llvm::ArrayRef argumentsArray(arguments);
176
177 // Handle function results
178 std::cout << "Creating function results" << std::endl;
179 ::llvm::SmallVector<mlir::Type> results;
180 results.push_back(Builder_->getIntegerType(32));
181 results.push_back(Builder_->getType<IOStateEdgeType>());
182 results.push_back(Builder_->getType<MemStateEdgeType>());
183 ::llvm::ArrayRef resultsArray(results);
184
185 // Add function attributes
186 std::cout << "Creating function attributes" << std::endl;
187 ::llvm::SmallVector<mlir::NamedAttribute> attributes;
188 auto attributeName = Builder_->getStringAttr("sym_name");
189 auto attributeValue = Builder_->getStringAttr("test");
190 auto symbolName = Builder_->getNamedAttr(attributeName, attributeValue);
191 attributes.push_back(symbolName);
192 auto linkageName = Builder_->getStringAttr("linkage");
193 auto linkageValue = Builder_->getStringAttr("external_linkage");
194 auto linkage = Builder_->getNamedAttr(linkageName, linkageValue);
195 attributes.push_back(linkage);
196 ::llvm::ArrayRef<::mlir::NamedAttribute> attributesRef(attributes);
197
198 // Add inputs to the function
199 ::llvm::SmallVector<mlir::Value> inputs;
200
201 // Create the lambda node and add it to the region/block it resides in
202 std::cout << "Creating LambdaNode" << std::endl;
203 auto lambda = Builder_->create<LambdaNode>(
204 Builder_->getUnknownLoc(),
205 Builder_->getType<mlir::FunctionType>(arguments, results),
206 inputs,
207 attributesRef);
208 omegaBlock->push_back(lambda);
209 auto & lambdaRegion = lambda.getRegion();
210 auto * lambdaBlock = new mlir::Block;
211 lambdaRegion.push_back(lambdaBlock);
212
213 // Add arguments to the region
214 std::cout << "Adding arguments to the region" << std::endl;
215 lambdaBlock->addArgument(Builder_->getIntegerType(32), Builder_->getUnknownLoc());
216 lambdaBlock->addArgument(Builder_->getType<IOStateEdgeType>(), Builder_->getUnknownLoc());
217 lambdaBlock->addArgument(Builder_->getType<MemStateEdgeType>(), Builder_->getUnknownLoc());
218
219 // ConstOp1 is not connected to anything
220 auto constOp1 = Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), 20, 32);
221 lambdaBlock->push_back(constOp1);
222
223 // ConstOp2 is connected as second argument of the divide operation
224 auto constOp2 = Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), 5, 32);
225 lambdaBlock->push_back(constOp2);
226
227 // lambdaBlock->getArguments();
228 for (unsigned int i = 0; i < lambdaBlock->getNumArguments(); ++i)
229 {
230 auto arg = lambdaBlock->getArgument(i);
231 if (arg.getType().isa<IOStateEdgeType>())
232 {
233 std::cout << "Argument " << i << " is an IOStateEdgeType" << std::endl;
234 }
235 else if (arg.getType().isa<MemStateEdgeType>())
236 {
237 std::cout << "Argument " << i << " is a MemStateEdgeType" << std::endl;
238 }
239 else if (arg.getType().isa<mlir::IntegerType>())
240 {
241 std::cout << "Argument " << i << " is an IntegerType" << std::endl;
242 }
243 }
244
247 auto divideOp = Builder_->create<mlir::arith::DivUIOp>(
248 Builder_->getUnknownLoc(),
249 lambdaBlock->getArgument(0),
250 constOp2);
251 lambdaBlock->push_back(divideOp);
252
253 ::llvm::SmallVector<mlir::Value> regionResults;
254 regionResults.push_back(divideOp->getResult(0));
255 regionResults.push_back(lambdaBlock->getArgument(1));
256 regionResults.push_back(lambdaBlock->getArgument(2));
257
258 // Handle the result of the lambda
259 std::cout << "Creating LambdaResult" << std::endl;
260 auto lambdaResult = Builder_->create<LambdaResult>(Builder_->getUnknownLoc(), regionResults);
261 lambdaBlock->push_back(lambdaResult);
262
263 // Handle the result of the omega
264 std::cout << "Creating OmegaResult" << std::endl;
265 ::llvm::SmallVector<mlir::Value> omegaRegionResults;
266 omegaRegionResults.push_back(lambda.getResult());
267 ::llvm::SmallVector<mlir::Type> omegaResultTypes;
268 omegaResultTypes.push_back(lambda.getResult().getType());
269
270 // Create exportNames ArrayAttr
271 ::llvm::SmallVector<::mlir::Attribute> exportNamesList;
272 exportNamesList.push_back(Builder_->getStringAttr("test"));
273 auto exportNamesAttr = ::mlir::ArrayAttr::get(Builder_->getContext(), exportNamesList);
274 ::llvm::SmallVector<::mlir::NamedAttribute> namedAttrs;
275 namedAttrs.push_back({ Builder_->getStringAttr("exportNames"), exportNamesAttr });
276
277 auto omegaResult = Builder_->create<OmegaResult>(
278 Builder_->getUnknownLoc(),
279 omegaResultTypes,
280 omegaRegionResults,
281 namedAttrs);
282 omegaBlock->push_back(omegaResult);
283
284 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
285 rootBlock->push_back(omega);
286
287 // Convert the MLIR to RVSDG and check the result
288 std::cout << "Converting MLIR to RVSDG" << std::endl;
289 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
290 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
291
292 jlm::rvsdg::view(region, stdout);
293
294 {
295 using namespace jlm::rvsdg;
296
297 EXPECT_EQ(region->numNodes(), 1u);
298
299 // Get the lambda block
300 auto convertedLambda =
301 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
302 EXPECT_TRUE(is<jlm::llvm::LlvmLambdaOperation>(convertedLambda));
303
304 // 2 Constants + 1 DivUIOp
305 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 3u);
306
307 // Traverse the rvsgd graph upwards to check connections
308 NodeOutput * lambdaResultOriginNodeOutput =
309 dynamic_cast<jlm::rvsdg::NodeOutput *>(convertedLambda->subregion()->result(0)->origin());
310 EXPECT_NE(lambdaResultOriginNodeOutput, nullptr);
311 Node * lambdaResultOriginNode = lambdaResultOriginNodeOutput->node();
312 EXPECT_TRUE(is<jlm::llvm::IntegerUDivOperation>(lambdaResultOriginNode->GetOperation()));
313 EXPECT_EQ(lambdaResultOriginNode->ninputs(), 2u);
314
315 // Check first input
316 RegionArgument * DivInput0 =
317 dynamic_cast<jlm::rvsdg::RegionArgument *>(lambdaResultOriginNode->input(0)->origin());
318 EXPECT_NE(DivInput0, nullptr);
319 EXPECT_TRUE(jlm::rvsdg::is<BitType>(DivInput0->Type()));
320 EXPECT_EQ(std::dynamic_pointer_cast<const BitType>(DivInput0->Type())->nbits(), 32u);
321
322 // Check second input
324 *lambdaResultOriginNode->input(1)->origin());
325 EXPECT_NE(DivInput1Node, nullptr);
326 EXPECT_TRUE(is<jlm::llvm::IntegerConstantOperation>(DivInput1Node->GetOperation()));
327 auto DivInput1Constant =
328 dynamic_cast<const jlm::llvm::IntegerConstantOperation *>(&DivInput1Node->GetOperation());
329 EXPECT_EQ(DivInput1Constant->Representation().to_int(), 5u);
330 EXPECT_TRUE(is<const BitType>(DivInput1Constant->result(0)));
331 EXPECT_EQ(
332 std::dynamic_pointer_cast<const BitType>(DivInput1Constant->result(0))->nbits(),
333 32u);
334 }
335 }
336}
337
345TEST(MlirToJlmConverterTests, TestCompZeroExt)
346{
347 {
348 using namespace mlir::rvsdg;
349 using namespace mlir::jlm;
350
351 // Setup MLIR Context and load dialects
352 std::cout << "Creating MLIR context" << std::endl;
353 auto context = std::make_unique<mlir::MLIRContext>();
354 context->getOrLoadDialect<RVSDGDialect>();
355 context->getOrLoadDialect<JLMDialect>();
356 context->getOrLoadDialect<mlir::arith::ArithDialect>();
357 context->getOrLoadDialect<mlir::LLVM::LLVMDialect>();
358 auto Builder_ = std::make_unique<mlir::OpBuilder>(context.get());
359
360 auto omega = Builder_->create<OmegaNode>(Builder_->getUnknownLoc());
361 auto & omegaRegion = omega.getRegion();
362 auto * omegaBlock = new mlir::Block;
363 omegaRegion.push_back(omegaBlock);
364
365 // Handle function arguments
366 std::cout << "Creating function arguments" << std::endl;
367 ::llvm::SmallVector<mlir::Type> arguments;
368 arguments.push_back(Builder_->getIntegerType(32));
369 arguments.push_back(Builder_->getType<IOStateEdgeType>());
370 arguments.push_back(Builder_->getType<MemStateEdgeType>());
371 ::llvm::ArrayRef argumentsArray(arguments);
372
373 // Handle function results
374 std::cout << "Creating function results" << std::endl;
375 ::llvm::SmallVector<mlir::Type> results;
376 results.push_back(Builder_->getIntegerType(32));
377 results.push_back(Builder_->getType<IOStateEdgeType>());
378 results.push_back(Builder_->getType<MemStateEdgeType>());
379 ::llvm::ArrayRef resultsArray(results);
380
381 // Add function attributes
382 std::cout << "Creating function attributes" << std::endl;
383 ::llvm::SmallVector<mlir::NamedAttribute> attributes;
384 auto attributeName = Builder_->getStringAttr("sym_name");
385 auto attributeValue = Builder_->getStringAttr("test");
386 auto symbolName = Builder_->getNamedAttr(attributeName, attributeValue);
387 attributes.push_back(symbolName);
388 auto linkageName = Builder_->getStringAttr("linkage");
389 auto linkageValue = Builder_->getStringAttr("external_linkage");
390 auto linkage = Builder_->getNamedAttr(linkageName, linkageValue);
391 attributes.push_back(linkage);
392 ::llvm::ArrayRef<::mlir::NamedAttribute> attributesRef(attributes);
393
394 // Add inputs to the function
395 ::llvm::SmallVector<mlir::Value> inputs;
396
397 // Create the lambda node and add it to the region/block it resides in
398 std::cout << "Creating LambdaNode" << std::endl;
399 auto lambda = Builder_->create<LambdaNode>(
400 Builder_->getUnknownLoc(),
401 Builder_->getType<mlir::FunctionType>(arguments, results),
402 inputs,
403 attributesRef);
404 omegaBlock->push_back(lambda);
405 auto & lambdaRegion = lambda.getRegion();
406 auto * lambdaBlock = new mlir::Block;
407 lambdaRegion.push_back(lambdaBlock);
408
409 // Add arguments to the region
410 std::cout << "Adding arguments to the region" << std::endl;
411 lambdaBlock->addArgument(Builder_->getIntegerType(32), Builder_->getUnknownLoc());
412 lambdaBlock->addArgument(Builder_->getType<IOStateEdgeType>(), Builder_->getUnknownLoc());
413 lambdaBlock->addArgument(Builder_->getType<MemStateEdgeType>(), Builder_->getUnknownLoc());
414
415 // ConstOp1 is connected to the second argument of the add operation
416 auto constOp1 = Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), 20, 32);
417 lambdaBlock->push_back(constOp1);
418
419 // ConstOp2 is connected as second argument of the compare operation
420 auto constOp2 = Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), 5, 32);
421 lambdaBlock->push_back(constOp2);
422
425 auto AddOp = Builder_->create<mlir::arith::AddIOp>(
426 Builder_->getUnknownLoc(),
427 lambdaBlock->getArgument(0),
428 constOp1);
429 lambdaBlock->push_back(AddOp);
430
431 auto compOp = Builder_->create<mlir::arith::CmpIOp>(
432 Builder_->getUnknownLoc(),
433 mlir::arith::CmpIPredicate::eq,
434 AddOp.getResult(),
435 constOp2);
436 lambdaBlock->push_back(compOp);
437
438 auto zeroExtOp = Builder_->create<mlir::arith::ExtUIOp>(
439 Builder_->getUnknownLoc(),
440 Builder_->getIntegerType(32),
441 compOp.getResult());
442 lambdaBlock->push_back(zeroExtOp);
443
444 // Handle the result of the lambda
445 ::llvm::SmallVector<mlir::Value> regionResults;
446 regionResults.push_back(zeroExtOp->getResult(0));
447 regionResults.push_back(lambdaBlock->getArgument(1));
448 regionResults.push_back(lambdaBlock->getArgument(2));
449 std::cout << "Creating LambdaResult" << std::endl;
450 auto lambdaResult = Builder_->create<LambdaResult>(Builder_->getUnknownLoc(), regionResults);
451 lambdaBlock->push_back(lambdaResult);
452
453 // Handle the result of the omega
454 std::cout << "Creating OmegaResult" << std::endl;
455 ::llvm::SmallVector<mlir::Value> omegaRegionResults;
456 omegaRegionResults.push_back(lambda.getResult());
457 ::llvm::SmallVector<mlir::Type> omegaResultTypes;
458 omegaResultTypes.push_back(lambda.getResult().getType());
459
460 // Create exportNames ArrayAttr
461 ::llvm::SmallVector<::mlir::Attribute> exportNamesList;
462 exportNamesList.push_back(Builder_->getStringAttr("test"));
463 auto exportNamesAttr = ::mlir::ArrayAttr::get(Builder_->getContext(), exportNamesList);
464 ::llvm::SmallVector<::mlir::NamedAttribute> namedAttrs;
465 namedAttrs.push_back({ Builder_->getStringAttr("exportNames"), exportNamesAttr });
466
467 auto omegaResult = Builder_->create<OmegaResult>(
468 Builder_->getUnknownLoc(),
469 omegaResultTypes,
470 omegaRegionResults,
471 namedAttrs);
472 omegaBlock->push_back(omegaResult);
473
474 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
475 rootBlock->push_back(omega);
476
477 // Convert the MLIR to RVSDG and check the result
478 std::cout << "Converting MLIR to RVSDG" << std::endl;
479 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
480 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
481
482 {
483 using namespace jlm::rvsdg;
484
485 std::cout << "Checking the result" << std::endl;
486
487 EXPECT_EQ(region->numNodes(), 1u);
488
489 // Get the lambda block
490 auto convertedLambda =
491 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
492 EXPECT_TRUE(is<jlm::llvm::LlvmLambdaOperation>(convertedLambda));
493
494 // 2 Constants + AddOp + CompOp + ZeroExtOp
495 EXPECT_EQ(convertedLambda->subregion()->numNodes(), 5u);
496
497 // Traverse the rvsgd graph upwards to check connections
498 std::cout << "Testing lambdaResultOriginNodeOuput\n";
500 *convertedLambda->subregion()->result(0)->origin());
501 EXPECT_NE(ZExtNode, nullptr);
502 EXPECT_TRUE(is<jlm::llvm::ZExtOperation>(ZExtNode->GetOperation()));
503 EXPECT_EQ(ZExtNode->ninputs(), 1u);
504
505 // Check ZExt
506 auto ZExtOp = dynamic_cast<const jlm::llvm::ZExtOperation *>(&ZExtNode->GetOperation());
507 EXPECT_EQ(ZExtOp->nsrcbits(), 1u);
508 EXPECT_EQ(ZExtOp->ndstbits(), 32u);
509
510 // Check ZExt input
511 std::cout << "Testing input 0\n";
512 auto BitEqNode =
513 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*ZExtNode->input(0)->origin());
514 EXPECT_TRUE(is<jlm::llvm::IntegerEqOperation>(BitEqNode->GetOperation()));
515
516 // Check BitEq
517 EXPECT_EQ(
518 dynamic_cast<const jlm::llvm::IntegerEqOperation *>(&BitEqNode->GetOperation())
519 ->Type()
520 .nbits(),
521 32u);
522 EXPECT_EQ(BitEqNode->ninputs(), 2u);
523
524 // Check BitEq input 0
525 auto AddNode =
526 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*BitEqNode->input(0)->origin());
527 EXPECT_TRUE(is<jlm::llvm::IntegerAddOperation>(AddNode->GetOperation()));
528 EXPECT_EQ(AddNode->ninputs(), 2u);
529
530 // Check BitEq input 1
531 auto Const2Node =
532 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*BitEqNode->input(1)->origin());
533 EXPECT_TRUE(is<jlm::llvm::IntegerConstantOperation>(Const2Node->GetOperation()));
534
535 // Check Const2
536 auto Const2Op =
537 dynamic_cast<const jlm::llvm::IntegerConstantOperation *>(&Const2Node->GetOperation());
538 EXPECT_EQ(Const2Op->Representation().to_int(), 5u);
539 EXPECT_TRUE(is<const BitType>(Const2Op->result(0)));
540 EXPECT_EQ(std::dynamic_pointer_cast<const BitType>(Const2Op->result(0))->nbits(), 32u);
541
542 // Check add op
543 auto AddOp = dynamic_cast<const jlm::llvm::IntegerAddOperation *>(&AddNode->GetOperation());
544 EXPECT_EQ(AddOp->Type().nbits(), 32u);
545
546 // Check add input0
547 RegionArgument * AddInput0 =
548 dynamic_cast<jlm::rvsdg::RegionArgument *>(AddNode->input(0)->origin());
549 EXPECT_NE(AddInput0, nullptr);
550 EXPECT_TRUE(jlm::rvsdg::is<BitType>(AddInput0->Type()));
551 EXPECT_EQ(std::dynamic_pointer_cast<const BitType>(AddInput0->Type())->nbits(), 32u);
552
553 // Check add input1
554 auto Const1Node =
555 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*AddNode->input(1)->origin());
556 EXPECT_TRUE(is<jlm::llvm::IntegerConstantOperation>(Const1Node->GetOperation()));
557
558 // Check Const1
559 auto Const1Op =
560 dynamic_cast<const jlm::llvm::IntegerConstantOperation *>(&Const1Node->GetOperation());
561 EXPECT_EQ(Const1Op->Representation().to_int(), 20u);
562 EXPECT_TRUE(is<const BitType>(Const1Op->result(0)));
563 EXPECT_EQ(std::dynamic_pointer_cast<const BitType>(Const1Op->result(0))->nbits(), 32u);
564 }
565 }
566}
567
573TEST(MlirToJlmConverterTests, TestMatchOp)
574{
575 {
576 using namespace mlir::rvsdg;
577 using namespace mlir::jlm;
578
579 // Setup MLIR Context and load dialects
580 std::cout << "Creating MLIR context" << std::endl;
581 auto context = std::make_unique<mlir::MLIRContext>();
582 context->getOrLoadDialect<RVSDGDialect>();
583 context->getOrLoadDialect<JLMDialect>();
584 context->getOrLoadDialect<mlir::arith::ArithDialect>();
585 context->getOrLoadDialect<mlir::LLVM::LLVMDialect>();
586 auto Builder_ = std::make_unique<mlir::OpBuilder>(context.get());
587
588 auto omega = Builder_->create<OmegaNode>(Builder_->getUnknownLoc());
589 auto & omegaRegion = omega.getRegion();
590 auto * omegaBlock = new mlir::Block;
591 omegaRegion.push_back(omegaBlock);
592
593 // Handle function arguments
594 std::cout << "Creating function arguments" << std::endl;
595 ::llvm::SmallVector<mlir::Type> arguments;
596 arguments.push_back(Builder_->getIntegerType(32));
597 arguments.push_back(Builder_->getType<IOStateEdgeType>());
598 arguments.push_back(Builder_->getType<MemStateEdgeType>());
599 ::llvm::ArrayRef argumentsArray(arguments);
600
601 // Handle function results
602 std::cout << "Creating function results" << std::endl;
603 ::llvm::SmallVector<mlir::Type> results;
604 results.push_back(::mlir::rvsdg::RVSDG_CTRLType::get(Builder_->getContext(), 4));
605 results.push_back(Builder_->getType<IOStateEdgeType>());
606 results.push_back(Builder_->getType<MemStateEdgeType>());
607 ::llvm::ArrayRef resultsArray(results);
608
609 // Add function attributes
610 std::cout << "Creating function attributes" << std::endl;
611 ::llvm::SmallVector<mlir::NamedAttribute> attributes;
612 auto attributeName = Builder_->getStringAttr("sym_name");
613 auto attributeValue = Builder_->getStringAttr("test");
614 auto symbolName = Builder_->getNamedAttr(attributeName, attributeValue);
615 attributes.push_back(symbolName);
616 auto linkageName = Builder_->getStringAttr("linkage");
617 auto linkageValue = Builder_->getStringAttr("external_linkage");
618 auto linkage = Builder_->getNamedAttr(linkageName, linkageValue);
619 attributes.push_back(linkage);
620 ::llvm::ArrayRef<::mlir::NamedAttribute> attributesRef(attributes);
621
622 // Add inputs to the function
623 ::llvm::SmallVector<mlir::Value> inputs;
624
625 // Create the lambda node and add it to the region/block it resides in
626 std::cout << "Creating LambdaNode" << std::endl;
627 auto lambda = Builder_->create<LambdaNode>(
628 Builder_->getUnknownLoc(),
629 Builder_->getType<mlir::FunctionType>(arguments, results),
630 inputs,
631 attributesRef);
632 omegaBlock->push_back(lambda);
633 auto & lambdaRegion = lambda.getRegion();
634 auto * lambdaBlock = new mlir::Block;
635 lambdaRegion.push_back(lambdaBlock);
636
637 // Add arguments to the region
638 std::cout << "Adding arguments to the region" << std::endl;
639 lambdaBlock->addArgument(Builder_->getIntegerType(32), Builder_->getUnknownLoc());
640 lambdaBlock->addArgument(Builder_->getType<IOStateEdgeType>(), Builder_->getUnknownLoc());
641 lambdaBlock->addArgument(Builder_->getType<MemStateEdgeType>(), Builder_->getUnknownLoc());
642
643 ::llvm::SmallVector<::mlir::Attribute> mappingVector;
644
645 mappingVector.push_back(::mlir::rvsdg::MatchRuleAttr::get(
646 Builder_->getContext(),
647 ::llvm::ArrayRef(static_cast<int64_t>(0)),
648 4));
649 mappingVector.push_back(::mlir::rvsdg::MatchRuleAttr::get(
650 Builder_->getContext(),
651 ::llvm::ArrayRef(static_cast<int64_t>(1)),
652 5));
653 mappingVector.push_back(::mlir::rvsdg::MatchRuleAttr::get(
654 Builder_->getContext(),
655 ::llvm::ArrayRef(static_cast<int64_t>(1)),
656 6));
658 mappingVector.push_back(
659 ::mlir::rvsdg::MatchRuleAttr::get(Builder_->getContext(), ::llvm::ArrayRef<int64_t>(), 2));
660
661 auto Match = Builder_->create<::mlir::rvsdg::Match>(
662 Builder_->getUnknownLoc(),
663 ::mlir::rvsdg::RVSDG_CTRLType::get(
664 Builder_->getContext(),
665 mappingVector.size()), // Control, ouput type
666 // omegaBlock->getArgument(0), // input
667 lambdaBlock->getArgument(0), // input
668 ::mlir::ArrayAttr::get(Builder_->getContext(), ::llvm::ArrayRef(mappingVector)));
669 lambdaBlock->push_back(Match);
670
671 // Handle the result of the lambda
672 ::llvm::SmallVector<mlir::Value> regionResults;
673 regionResults.push_back(Match->getResult(0));
674 regionResults.push_back(lambdaBlock->getArgument(1));
675 regionResults.push_back(lambdaBlock->getArgument(2));
676 std::cout << "Creating LambdaResult" << std::endl;
677 auto lambdaResult = Builder_->create<LambdaResult>(Builder_->getUnknownLoc(), regionResults);
678 lambdaBlock->push_back(lambdaResult);
679
680 // Handle the result of the omega
681 std::cout << "Creating OmegaResult" << std::endl;
682 ::llvm::SmallVector<mlir::Value> omegaRegionResults;
683 omegaRegionResults.push_back(lambda.getResult());
684 ::llvm::SmallVector<mlir::Type> omegaResultTypes;
685 omegaResultTypes.push_back(lambda.getResult().getType());
686
687 // Create exportNames ArrayAttr
688 ::llvm::SmallVector<::mlir::Attribute> exportNamesList;
689 exportNamesList.push_back(Builder_->getStringAttr("test"));
690 auto exportNamesAttr = ::mlir::ArrayAttr::get(Builder_->getContext(), exportNamesList);
691 ::llvm::SmallVector<::mlir::NamedAttribute> namedAttrs;
692 namedAttrs.push_back({ Builder_->getStringAttr("exportNames"), exportNamesAttr });
693
694 auto omegaResult = Builder_->create<OmegaResult>(
695 Builder_->getUnknownLoc(),
696 omegaResultTypes,
697 omegaRegionResults,
698 namedAttrs);
699 omegaBlock->push_back(omegaResult);
700
701 // Convert the MLIR to RVSDG and check the result
702 std::cout << "Converting MLIR to RVSDG" << std::endl;
703 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
704 rootBlock->push_back(omega);
705 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
706 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
707
708 {
709 using namespace jlm::rvsdg;
710
711 // Get the lambda block
712 auto convertedLambda =
713 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
714 EXPECT_TRUE(is<jlm::llvm::LlvmLambdaOperation>(convertedLambda));
715
716 auto lambdaRegion = convertedLambda->subregion();
717
718 auto matchNode =
719 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*lambdaRegion->result(0)->origin());
720 EXPECT_TRUE(is<MatchOperation>(matchNode->GetOperation()));
721
722 auto matchOp = dynamic_cast<const MatchOperation *>(&matchNode->GetOperation());
723 EXPECT_EQ(matchOp->narguments(), 1u);
724 EXPECT_TRUE(is<const BitType>(matchOp->argument(0)));
725 EXPECT_EQ(std::dynamic_pointer_cast<const BitType>(matchOp->argument(0))->nbits(), 32u);
726
727 // 3 alternatives + default
728 EXPECT_EQ(matchOp->nalternatives(), 4u);
729
730 EXPECT_EQ(matchOp->default_alternative(), 2u);
731
732 for (auto mapping : *matchOp)
733 {
734 EXPECT_TRUE(
735 (mapping.first == 0 && mapping.second == 4)
736 || (mapping.first == 1 && mapping.second == 5)
737 || (mapping.first == 1 && mapping.second == 6));
738 }
739 }
740 }
741}
742
748TEST(MlirToJlmConverterTests, TestGammaOp)
749{
750 {
751 using namespace mlir::rvsdg;
752 using namespace mlir::jlm;
753
754 // Setup MLIR Context and load dialects
755 std::cout << "Creating MLIR context" << std::endl;
756 auto context = std::make_unique<mlir::MLIRContext>();
757 context->getOrLoadDialect<RVSDGDialect>();
758 context->getOrLoadDialect<JLMDialect>();
759 context->getOrLoadDialect<mlir::arith::ArithDialect>();
760 context->getOrLoadDialect<mlir::LLVM::LLVMDialect>();
761 auto Builder_ = std::make_unique<mlir::OpBuilder>(context.get());
762
763 auto omega = Builder_->create<OmegaNode>(Builder_->getUnknownLoc());
764 auto & omegaRegion = omega.getRegion();
765 auto * omegaBlock = new mlir::Block;
766 omegaRegion.push_back(omegaBlock);
767
768 // Handle function arguments
769 std::cout << "Creating function arguments" << std::endl;
770 ::llvm::SmallVector<mlir::Type> arguments;
771 arguments.push_back(::mlir::rvsdg::RVSDG_CTRLType::get(Builder_->getContext(), 3));
772 arguments.push_back(Builder_->getType<IOStateEdgeType>());
773 arguments.push_back(Builder_->getType<MemStateEdgeType>());
774 ::llvm::ArrayRef argumentsArray(arguments);
775
776 // Handle function results
777 std::cout << "Creating function results" << std::endl;
778 ::llvm::SmallVector<mlir::Type> results;
779 results.push_back(Builder_->getIntegerType(32));
780 results.push_back(Builder_->getIntegerType(32));
781 results.push_back(Builder_->getType<IOStateEdgeType>());
782 results.push_back(Builder_->getType<MemStateEdgeType>());
783 ::llvm::ArrayRef resultsArray(results);
784
785 // Add function attributes
786 std::cout << "Creating function attributes" << std::endl;
787 ::llvm::SmallVector<mlir::NamedAttribute> attributes;
788 auto attributeName = Builder_->getStringAttr("sym_name");
789 auto attributeValue = Builder_->getStringAttr("test");
790 auto symbolName = Builder_->getNamedAttr(attributeName, attributeValue);
791 attributes.push_back(symbolName);
792 auto linkageName = Builder_->getStringAttr("linkage");
793 auto linkageValue = Builder_->getStringAttr("external_linkage");
794 auto linkage = Builder_->getNamedAttr(linkageName, linkageValue);
795 attributes.push_back(linkage);
796 ::llvm::ArrayRef<::mlir::NamedAttribute> attributesRef(attributes);
797
798 // Add inputs to the function
799 ::llvm::SmallVector<mlir::Value> inputs;
800
801 // Create the lambda node and add it to the region/block it resides in
802 std::cout << "Creating LambdaNode" << std::endl;
803 auto lambda = Builder_->create<LambdaNode>(
804 Builder_->getUnknownLoc(),
805 Builder_->getType<mlir::FunctionType>(arguments, results),
806 inputs,
807 attributesRef);
808 omegaBlock->push_back(lambda);
809 auto & lambdaRegion = lambda.getRegion();
810 auto * lambdaBlock = new mlir::Block;
811 lambdaRegion.push_back(lambdaBlock);
812
813 // Add arguments to the region
814 std::cout << "Adding arguments to the region" << std::endl;
815 lambdaBlock->addArgument(
816 ::mlir::rvsdg::RVSDG_CTRLType::get(Builder_->getContext(), 3),
817 Builder_->getUnknownLoc());
818 lambdaBlock->addArgument(Builder_->getType<IOStateEdgeType>(), Builder_->getUnknownLoc());
819 lambdaBlock->addArgument(Builder_->getType<MemStateEdgeType>(), Builder_->getUnknownLoc());
820
821 auto entryVar1 = Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), 5, 32);
822 lambdaBlock->push_back(entryVar1);
823 auto entryVar2 = Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), 6, 32);
824 lambdaBlock->push_back(entryVar2);
825
826 ::llvm::SmallVector<::mlir::Type> typeRangeOuput;
827 typeRangeOuput.push_back(::mlir::IntegerType::get(Builder_->getContext(), 32));
828 typeRangeOuput.push_back(::mlir::IntegerType::get(Builder_->getContext(), 32));
829 ::mlir::rvsdg::GammaNode gamma = Builder_->create<::mlir::rvsdg::GammaNode>(
830 Builder_->getUnknownLoc(),
831 ::mlir::TypeRange(::llvm::ArrayRef(typeRangeOuput)), // Ouputs types
832 lambdaBlock->getArgument(0), // predicate
833 ::mlir::ValueRange(::llvm::ArrayRef<::mlir::Value>({ entryVar1, entryVar2 })), // Inputs
834 static_cast<unsigned>(3) // regionsCount
835 );
836 lambdaBlock->push_back(gamma);
837
838 for (size_t i = 0; i < gamma.getNumRegions(); ++i)
839 {
840 auto & gammaBlock = gamma.getRegion(i).emplaceBlock();
841 auto exitvar1 =
842 Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), i + 1, 32);
843 gammaBlock.push_back(exitvar1);
844 auto exitvar2 =
845 Builder_->create<mlir::arith::ConstantIntOp>(Builder_->getUnknownLoc(), 10 * (i + 1), 32);
846 gammaBlock.push_back(exitvar2);
847 auto gammaResult = Builder_->create<::mlir::rvsdg::GammaResult>(
848 Builder_->getUnknownLoc(),
849 ::llvm::SmallVector<mlir::Value>({ exitvar1, exitvar2 }));
850 gammaBlock.push_back(gammaResult);
851 }
852
853 // Handle the result of the lambda
854 ::llvm::SmallVector<mlir::Value> regionResults;
855 regionResults.push_back(gamma->getResult(0));
856 regionResults.push_back(gamma->getResult(1));
857 regionResults.push_back(lambdaBlock->getArgument(1));
858 regionResults.push_back(lambdaBlock->getArgument(2));
859 std::cout << "Creating LambdaResult" << std::endl;
860 auto lambdaResult = Builder_->create<LambdaResult>(Builder_->getUnknownLoc(), regionResults);
861 lambdaBlock->push_back(lambdaResult);
862
863 // Handle the result of the omega
864 std::cout << "Creating OmegaResult" << std::endl;
865 ::llvm::SmallVector<mlir::Value> omegaRegionResults;
866 omegaRegionResults.push_back(lambda.getResult());
867 ::llvm::SmallVector<mlir::Type> omegaResultTypes;
868 omegaResultTypes.push_back(lambda.getResult().getType());
869
870 // Create exportNames ArrayAttr
871 ::llvm::SmallVector<::mlir::Attribute> exportNamesList;
872 exportNamesList.push_back(Builder_->getStringAttr("test"));
873 auto exportNamesAttr = ::mlir::ArrayAttr::get(Builder_->getContext(), exportNamesList);
874 ::llvm::SmallVector<::mlir::NamedAttribute> namedAttrs;
875 namedAttrs.push_back({ Builder_->getStringAttr("exportNames"), exportNamesAttr });
876
877 auto omegaResult = Builder_->create<OmegaResult>(
878 Builder_->getUnknownLoc(),
879 omegaResultTypes,
880 omegaRegionResults,
881 namedAttrs);
882 omegaBlock->push_back(omegaResult);
883
884 // Convert the MLIR to RVSDG and check the result
885 std::cout << "Converting MLIR to RVSDG" << std::endl;
886 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
887 rootBlock->push_back(omega);
888 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
889 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
890
891 {
892 using namespace jlm::rvsdg;
893
894 EXPECT_EQ(region->numNodes(), 1u);
895
896 // Get the lambda block
897 auto convertedLambda =
898 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
899 EXPECT_TRUE(is<jlm::llvm::LlvmLambdaOperation>(convertedLambda->GetOperation()));
900
901 auto lambdaRegion = convertedLambda->subregion();
902
903 // 2 constants + gamma
904 EXPECT_EQ(lambdaRegion->numNodes(), 3u);
905
907 *lambdaRegion->result(0)->origin());
908
909 std::cout << "Checking gamma operation" << std::endl;
910 auto gammaOp = dynamic_cast<const GammaOperation *>(&gammaNode->GetOperation());
911 EXPECT_EQ(gammaNode->ninputs(), 3u);
912 EXPECT_EQ(gammaOp->nalternatives(), 3u);
913 EXPECT_EQ(gammaNode->noutputs(), 2u);
914 }
915 }
916}
917
923TEST(MlirToJlmConverterTests, TestThetaOp)
924{
925 {
926 using namespace mlir::rvsdg;
927 using namespace mlir::jlm;
928
929 // Setup MLIR Context and load dialects
930 std::cout << "Creating MLIR context" << std::endl;
931 auto context = std::make_unique<mlir::MLIRContext>();
932 context->getOrLoadDialect<RVSDGDialect>();
933 context->getOrLoadDialect<JLMDialect>();
934 context->getOrLoadDialect<mlir::arith::ArithDialect>();
935 context->getOrLoadDialect<mlir::LLVM::LLVMDialect>();
936 auto Builder_ = std::make_unique<mlir::OpBuilder>(context.get());
937
938 auto omega = Builder_->create<OmegaNode>(Builder_->getUnknownLoc());
939 auto & omegaRegion = omega.getRegion();
940 auto * omegaBlock = new mlir::Block;
941 omegaRegion.push_back(omegaBlock);
942
943 // Add function attributes
944 std::cout << "Creating function attributes" << std::endl;
945 auto attributeName = Builder_->getStringAttr("sym_name");
946 auto attributeValue = Builder_->getStringAttr("test");
947 auto symbolName = Builder_->getNamedAttr(attributeName, attributeValue);
948 auto linkageName = Builder_->getStringAttr("linkage");
949 auto linkageValue = Builder_->getStringAttr("external_linkage");
950 auto linkage = Builder_->getNamedAttr(linkageName, linkageValue);
951
952 auto iotype = Builder_->getType<IOStateEdgeType>();
953 auto memtype = Builder_->getType<MemStateEdgeType>();
954
955 // Create the lambda node and add it to the region/block it resides in
956 std::cout << "Creating LambdaNode" << std::endl;
957 auto lambda = Builder_->create<LambdaNode>(
958 Builder_->getUnknownLoc(),
959 Builder_->getType<mlir::FunctionType>(
960 ::mlir::TypeRange({ iotype, memtype }),
961 ::mlir::TypeRange({ iotype, memtype })),
962 ::llvm::SmallVector<mlir::Value>(),
963 ::llvm::ArrayRef<::mlir::NamedAttribute>({ symbolName, linkage }));
964 omegaBlock->push_back(lambda);
965 auto & lambdaRegion = lambda.getRegion();
966 auto * lambdaBlock = new mlir::Block;
967 lambdaRegion.push_back(lambdaBlock);
968
969 // Add arguments to the region
970 std::cout << "Adding arguments to the region" << std::endl;
971 lambdaBlock->addArgument(iotype, Builder_->getUnknownLoc());
972 lambdaBlock->addArgument(memtype, Builder_->getUnknownLoc());
973
974 auto theta = Builder_->create<::mlir::rvsdg::ThetaNode>(
975 Builder_->getUnknownLoc(),
976 ::mlir::TypeRange({ iotype, memtype }), // Ouputs types
977 ::mlir::ValueRange({ lambdaBlock->getArgument(0), lambdaBlock->getArgument(1) }), // Inputs
978 ::llvm::SmallVector<::mlir::NamedAttribute>({}));
979 lambdaBlock->push_back(theta);
980
981 auto & thetaBlock = theta.getRegion().emplaceBlock();
982 thetaBlock.addArgument(iotype, Builder_->getUnknownLoc());
983 thetaBlock.addArgument(memtype, Builder_->getUnknownLoc());
984 auto predicate = Builder_->create<mlir::rvsdg::ConstantCtrl>(
985 Builder_->getUnknownLoc(),
986 Builder_->getType<::mlir::rvsdg::RVSDG_CTRLType>(2),
987 0);
988 thetaBlock.push_back(predicate);
989
990 auto thetaResult = Builder_->create<::mlir::rvsdg::ThetaResult>(
991 Builder_->getUnknownLoc(),
992 predicate,
993 ::llvm::SmallVector<mlir::Value>(thetaBlock.getArguments()));
994 thetaBlock.push_back(thetaResult);
995
996 // Handle the result of the lambda
997 ::llvm::SmallVector<mlir::Value> regionResults;
998 regionResults.push_back(theta->getResult(0));
999 regionResults.push_back(theta->getResult(1));
1000 std::cout << "Creating LambdaResult" << std::endl;
1001 auto lambdaResult = Builder_->create<LambdaResult>(Builder_->getUnknownLoc(), regionResults);
1002 lambdaBlock->push_back(lambdaResult);
1003
1004 // Handle the result of the omega
1005 std::cout << "Creating OmegaResult" << std::endl;
1006 ::llvm::SmallVector<mlir::Value> omegaRegionResults;
1007 omegaRegionResults.push_back(lambda.getResult());
1008 ::llvm::SmallVector<mlir::Type> omegaResultTypes;
1009 omegaResultTypes.push_back(lambda.getResult().getType());
1010
1011 // Create exportNames ArrayAttr
1012 ::llvm::SmallVector<::mlir::Attribute> exportNamesList;
1013 exportNamesList.push_back(Builder_->getStringAttr("test"));
1014 auto exportNamesAttr = ::mlir::ArrayAttr::get(Builder_->getContext(), exportNamesList);
1015 ::llvm::SmallVector<::mlir::NamedAttribute> namedAttrs;
1016 namedAttrs.push_back({ Builder_->getStringAttr("exportNames"), exportNamesAttr });
1017
1018 auto omegaResult = Builder_->create<OmegaResult>(
1019 Builder_->getUnknownLoc(),
1020 omegaResultTypes,
1021 omegaRegionResults,
1022 namedAttrs);
1023 omegaBlock->push_back(omegaResult);
1024
1025 // Convert the MLIR to RVSDG and check the result
1026 std::cout << "Converting MLIR to RVSDG" << std::endl;
1027 std::unique_ptr<mlir::Block> rootBlock = std::make_unique<mlir::Block>();
1028 rootBlock->push_back(omega);
1029 auto rvsdgModule = jlm::mlir::MlirToJlmConverter::CreateAndConvert(rootBlock);
1030 auto region = &rvsdgModule->Rvsdg().GetRootRegion();
1031
1032 {
1033 using namespace jlm::rvsdg;
1034
1035 EXPECT_EQ(region->numNodes(), 1u);
1036
1037 // Get the lambda block
1038 auto convertedLambda =
1039 jlm::util::assertedCast<jlm::rvsdg::LambdaNode>(region->Nodes().begin().ptr());
1040 EXPECT_TRUE(is<jlm::llvm::LlvmLambdaOperation>(convertedLambda->GetOperation()));
1041
1042 auto lambdaRegion = convertedLambda->subregion();
1043
1044 // Just the theta node
1045 EXPECT_EQ(lambdaRegion->numNodes(), 1u);
1046
1048 *lambdaRegion->result(0)->origin());
1049
1050 std::cout << "Checking theta node" << std::endl;
1051 EXPECT_EQ(thetaNode->ninputs(), 2u);
1052 EXPECT_EQ(thetaNode->GetLoopVars().size(), 2u);
1053 EXPECT_EQ(thetaNode->noutputs(), 2u);
1054 EXPECT_EQ(thetaNode->nsubregions(), 1u);
1055 EXPECT_TRUE(is<jlm::rvsdg::ControlType>(thetaNode->predicate()->Type()));
1056 auto predicateType =
1057 std::dynamic_pointer_cast<const ControlType>(thetaNode->predicate()->Type());
1058 EXPECT_EQ(predicateType->nalternatives(), 2u);
1059 std::cout << predicate.getValue() << std::endl;
1060 }
1061 }
1062}
TEST(MlirToJlmConverterTests, TestLambda)
util::HashSet< rvsdg::Output * > arguments
const rvsdg::BitType & Type() const noexcept
static std::unique_ptr< llvm::LlvmRvsdgModule > CreateAndConvert(std::unique_ptr<::mlir::Block > &block)
size_t nbits() const noexcept
Definition type.hpp:26
Output * origin() const noexcept
Definition node.hpp:58
Node * node() const noexcept
Definition node.hpp:572
NodeInput * input(size_t index) const noexcept
Definition node.hpp:615
virtual const Operation & GetOperation() const noexcept=0
size_t ninputs() const noexcept
Definition node.hpp:609
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:366
Represents the argument of a region.
Definition region.hpp:41
std::string view(const rvsdg::Region *region)
Definition view.cpp:142
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872