17 #include <gtest/gtest.h>
20 std::unordered_map<const jlm::rvsdg::Output *, std::unique_ptr<jlm::llvm::SCEVChainRecurrence>>,
21 std::unordered_map<const jlm::rvsdg::ThetaNode *, size_t>>
30 TEST(ScalarEvolutionTests, NonEvolvingVariable)
38 const auto & graph = rvsdgModule.
Rvsdg();
43 const auto lv1 = theta->AddLoopVar(c0.output(0));
47 lv1.post->divert_to(c1.output(0));
50 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ lv1.pre, c5.output(0) }, 32);
51 const auto matchResult =
54 theta->set_predicate(matchResult);
65 EXPECT_EQ(chrecMap.find(lv1.pre), chrecMap.end());
68 TEST(ScalarEvolutionTests, InductionVariable)
76 const auto & graph = rvsdgModule.
Rvsdg();
82 const auto lv1 = theta->AddLoopVar(c0.output(0));
83 const auto lv2 = theta->AddLoopVar(c2.output(0));
86 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
87 const auto result = addNode.output(0);
90 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ result, c5.output(0) }, 32);
91 const auto matchResult =
94 theta->set_predicate(matchResult);
95 lv1.post->divert_to(result);
103 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
104 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
108 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
109 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
110 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
114 lv2TestChrec.AddOperand(SCEVConstant::Create(2));
115 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
118 TEST(ScalarEvolutionTests, RecursiveInductionVariable)
126 const auto & graph = rvsdgModule.
Rvsdg();
132 const auto lv1 = theta->AddLoopVar(c0.output(0));
133 const auto lv2 = theta->AddLoopVar(c4.output(0));
136 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
137 const auto res1 = addNode.output(0);
140 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
141 const auto matchResult =
144 const auto & c2 = IntegerConstantOperation::Create(*theta->subregion(), 32, 2);
145 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, c2.output(0) }, 32);
146 const auto res2 = addNode2.output(0);
148 const auto & c3 = IntegerConstantOperation::Create(*theta->subregion(), 32, 3);
149 auto & addNode3 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ res2, c3.output(0) }, 32);
150 const auto res3 = addNode3.output(0);
152 theta->set_predicate(matchResult);
153 lv1.post->divert_to(res1);
154 lv2.post->divert_to(res3);
162 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
163 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
167 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
168 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
169 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
173 lv2TestChrec.AddOperand(SCEVConstant::Create(4));
174 lv2TestChrec.AddOperand(SCEVConstant::Create(5));
175 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
178 TEST(ScalarEvolutionTests, PolynomialInductionVariable)
186 const auto & graph = rvsdgModule.
Rvsdg();
192 const auto lv1 = theta->AddLoopVar(c0.output(0));
193 const auto lv2 = theta->AddLoopVar(c2.output(0));
196 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
197 const auto res1 = addNode.output(0);
200 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
201 const auto matchResult =
204 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, res1 }, 32);
205 const auto res2 = addNode2.output(0);
207 theta->set_predicate(matchResult);
208 lv1.post->divert_to(res1);
209 lv2.post->divert_to(res2);
217 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
218 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
222 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
223 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
224 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
229 lv2TestChrec.AddOperand(SCEVConstant::Create(2));
230 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
231 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
232 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
235 TEST(ScalarEvolutionTests, ThirdDegreePolynomialInductionVariable)
243 const auto & graph = rvsdgModule.
Rvsdg();
250 const auto lv1 = theta->AddLoopVar(c2.output(0));
251 const auto lv2 = theta->AddLoopVar(c3.output(0));
252 const auto lv3 = theta->AddLoopVar(c4.output(0));
256 auto & addNode_1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
257 const auto result_1 = addNode_1.output(0);
259 auto & addNode_2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, lv2.pre }, 32);
260 const auto result_2 = addNode_2.output(0);
262 auto & addNode_3 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv3.pre, lv2.pre }, 32);
263 const auto result_3 = addNode_3.output(0);
266 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ result_1, c5.output(0) }, 32);
267 const auto matchResult =
270 theta->set_predicate(matchResult);
271 lv1.post->divert_to(result_1);
272 lv2.post->divert_to(result_2);
273 lv3.post->divert_to(result_3);
281 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
282 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
283 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
287 lv1TestChrec.AddOperand(SCEVConstant::Create(2));
288 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
289 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
293 lv2TestChrec.AddOperand(SCEVConstant::Create(3));
294 lv2TestChrec.AddOperand(SCEVConstant::Create(2));
295 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
296 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
301 lv3TestChrec.AddOperand(SCEVConstant::Create(4));
302 lv3TestChrec.AddOperand(SCEVConstant::Create(3));
303 lv3TestChrec.AddOperand(SCEVConstant::Create(2));
304 lv3TestChrec.AddOperand(SCEVConstant::Create(1));
305 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
308 TEST(ScalarEvolutionTests, InductionVariableWithMultiplication)
316 const auto & graph = rvsdgModule.
Rvsdg();
322 const auto lv1 = theta->AddLoopVar(c0.output(0));
323 const auto lv2 = theta->AddLoopVar(c2.output(0));
326 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
327 auto res1 = addNode1.output(0);
330 auto & mulNode = jlm::rvsdg::CreateOpNode<IntegerMulOperation>({ res1, c3.output(0) }, 32);
333 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, mulNode.output(0) }, 32);
334 auto res2 = addNode2.output(0);
337 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
338 const auto matchResult =
341 theta->set_predicate(matchResult);
342 lv1.post->divert_to(res1);
343 lv2.post->divert_to(res2);
351 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
352 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
356 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
357 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
358 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
363 lv2TestChrec.AddOperand(SCEVConstant::Create(2));
364 lv2TestChrec.AddOperand(SCEVConstant::Create(3));
365 lv2TestChrec.AddOperand(SCEVConstant::Create(3));
366 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
369 TEST(ScalarEvolutionTests, InvalidInductionVariableWithMultiplication)
377 const auto & graph = rvsdgModule.
Rvsdg();
382 const auto lv1 = theta->AddLoopVar(c1.output(0));
385 auto & mulNode = jlm::rvsdg::CreateOpNode<IntegerMulOperation>({ lv1.pre, c2.output(0) }, 32);
386 const auto res1 = mulNode.output(0);
389 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
390 const auto matchResult =
393 theta->set_predicate(matchResult);
394 lv1.post->divert_to(res1);
402 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
407 lv1TestChrec.AddOperand(SCEVUnknown::Create());
408 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
411 TEST(ScalarEvolutionTests, MultiplicationOfTwoAffineChrecs)
419 const auto & graph = rvsdgModule.
Rvsdg();
425 const auto lv1 = theta->AddLoopVar(c0.output(0));
426 const auto lv2 = theta->AddLoopVar(c3.output(0));
429 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
430 auto res1 = addNode1.output(0);
432 auto & mulNode = jlm::rvsdg::CreateOpNode<IntegerMulOperation>({ lv1.pre, lv1.pre }, 32);
435 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, mulNode.output(0) }, 32);
436 auto res2 = addNode2.output(0);
439 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
440 const auto matchResult =
443 theta->set_predicate(matchResult);
444 lv1.post->divert_to(res1);
445 lv2.post->divert_to(res2);
453 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
454 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
458 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
459 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
460 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
465 lv2TestChrec.AddOperand(SCEVConstant::Create(3));
466 lv2TestChrec.AddOperand(SCEVConstant::Create(0));
467 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
468 lv2TestChrec.AddOperand(SCEVConstant::Create(2));
469 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
472 TEST(ScalarEvolutionTests, MultiplicationOfTwoQuadraticChrecs)
480 const auto & graph = rvsdgModule.
Rvsdg();
487 const auto lv1 = theta->AddLoopVar(c0.output(0));
488 const auto lv2 = theta->AddLoopVar(c1_1.output(0));
489 const auto lv3 = theta->AddLoopVar(c2.output(0));
492 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1_2.output(0) }, 32);
493 auto res1 = addNode1.output(0);
495 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, lv1.pre }, 32);
496 auto res2 = addNode2.output(0);
498 auto & mulNode = jlm::rvsdg::CreateOpNode<IntegerMulOperation>({ lv2.pre, lv2.pre }, 32);
500 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv3.pre, mulNode.output(0) }, 32);
501 auto res3 = addNode3.output(0);
504 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
505 const auto matchResult =
508 theta->set_predicate(matchResult);
509 lv1.post->divert_to(res1);
510 lv2.post->divert_to(res2);
511 lv3.post->divert_to(res3);
519 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
520 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
521 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
525 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
526 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
527 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
531 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
532 lv2TestChrec.AddOperand(SCEVConstant::Create(0));
533 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
534 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
539 lv3TestChrec.AddOperand(SCEVConstant::Create(2));
540 lv3TestChrec.AddOperand(SCEVConstant::Create(1));
541 lv3TestChrec.AddOperand(SCEVConstant::Create(0));
542 lv3TestChrec.AddOperand(SCEVConstant::Create(3));
543 lv3TestChrec.AddOperand(SCEVConstant::Create(6));
544 lv3TestChrec.AddOperand(SCEVConstant::Create(6));
545 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
548 TEST(ScalarEvolutionTests, InvalidPolynomialInductionVariableWithMultiplication)
556 const auto & graph = rvsdgModule.
Rvsdg();
562 const auto lv1 = theta->AddLoopVar(c0.output(0));
563 const auto lv2 = theta->AddLoopVar(c3.output(0));
566 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
567 auto res1 = addNode1.output(0);
570 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c2.output(0) }, 32);
572 jlm::rvsdg::CreateOpNode<IntegerMulOperation>({ lv2.pre, addNode2.output(0) }, 32);
573 const auto res2 = mulNode.output(0);
576 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
577 const auto matchResult =
580 theta->set_predicate(matchResult);
581 lv1.post->divert_to(res1);
582 lv2.post->divert_to(res2);
590 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
591 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
595 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
596 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
597 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
602 lv2TestChrec.AddOperand(SCEVUnknown::Create());
603 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
606 TEST(ScalarEvolutionTests, InductionVariableWithSubtraction)
614 const auto & graph = rvsdgModule.
Rvsdg();
619 const auto lv1 = theta->AddLoopVar(c10.output(0));
623 auto & subNode = jlm::rvsdg::CreateOpNode<IntegerSubOperation>({ lv1.pre, c1.output(0) }, 32);
624 const auto & res1 = subNode.output(0);
627 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSgtOperation>({ res1, c5.output(0) }, 32);
628 const auto matchResult =
631 theta->set_predicate(matchResult);
632 lv1.post->divert_to(res1);
640 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
644 lv1TestChrec.AddOperand(SCEVConstant::Create(10));
645 lv1TestChrec.AddOperand(SCEVConstant::Create(-1));
646 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
649 TEST(ScalarEvolutionTests, PolynomialInductionVariableWithSubtraction)
657 const auto & graph = rvsdgModule.
Rvsdg();
663 const auto lv1 = theta->AddLoopVar(c0.output(0));
664 const auto lv2 = theta->AddLoopVar(c3.output(0));
667 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
668 const auto res1 = addNode.output(0);
670 auto & subNode = jlm::rvsdg::CreateOpNode<IntegerSubOperation>({ lv2.pre, res1 }, 32);
671 const auto res2 = subNode.output(0);
674 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
675 const auto matchResult =
678 theta->set_predicate(matchResult);
679 lv1.post->divert_to(res1);
680 lv2.post->divert_to(res2);
688 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
689 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
693 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
694 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
695 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
700 lv2TestChrec.AddOperand(SCEVConstant::Create(3));
701 lv2TestChrec.AddOperand(SCEVConstant::Create(-1));
702 lv2TestChrec.AddOperand(SCEVConstant::Create(-1));
703 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
706 TEST(ScalarEvolutionTests, InductionVariablesWithNonConstantInitialValues)
732 auto cv1 = lambda->AddContextVar(*x).inner;
733 auto cv2 = lambda->AddContextVar(*y).inner;
734 auto cv3 = lambda->AddContextVar(*z).inner;
735 auto cv4 = lambda->AddContextVar(*w).inner;
739 auto lv2 = theta->AddLoopVar(cv2);
740 auto lv3 = theta->AddLoopVar(cv3);
741 auto lv4 = theta->AddLoopVar(cv4);
743 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, lv1.pre }, 32);
744 const auto res1 = addNode1.
output(0);
746 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv3.pre, res1 }, 32);
747 const auto res2 = addNode2.output(0);
749 auto & addNode3 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ res2, res1 }, 32);
750 const auto res3 = addNode3.output(0);
752 auto & addNode4 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv4.pre, res3 }, 32);
753 const auto res4 = addNode4.output(0);
756 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
757 const auto matchResult =
760 theta->set_predicate(matchResult);
761 lv2.post->divert_to(res1);
762 lv3.post->divert_to(res2);
763 lv4.post->divert_to(res4);
771 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
772 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
773 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
774 EXPECT_NE(chrecMap.find(lv4.pre), chrecMap.end());
779 lv1TestChrec.AddOperand(SCEVInit::Create(*lv1.pre));
780 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
786 lv2TestChrec.AddOperand(SCEVInit::Create(*lv2.pre));
787 lv2TestChrec.AddOperand(SCEVInit::Create(*lv1.pre));
788 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
793 lv3TestChrec.AddOperand(SCEVInit::Create(*lv3.pre));
794 lv3TestChrec.AddOperand(
795 SCEVNAryAddExpr::Create(SCEVInit::Create(*lv2.pre), SCEVInit::Create(*lv1.pre)));
796 lv3TestChrec.AddOperand(SCEVInit::Create(*lv1.pre));
797 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
804 lv4TestChrec.AddOperand(SCEVInit::Create(*lv4.pre));
805 lv4TestChrec.AddOperand(SCEVNAryAddExpr::Create(
806 SCEVInit::Create(*lv2.pre),
807 SCEVInit::Create(*lv1.pre),
808 SCEVInit::Create(*lv3.pre),
809 SCEVInit::Create(*lv2.pre),
810 SCEVInit::Create(*lv1.pre)));
811 lv4TestChrec.AddOperand(SCEVNAryAddExpr::Create(
812 SCEVInit::Create(*lv2.pre),
813 SCEVInit::Create(*lv1.pre),
814 SCEVInit::Create(*lv1.pre),
815 SCEVInit::Create(*lv1.pre)));
816 lv4TestChrec.AddOperand(SCEVInit::Create(*lv1.pre));
817 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv4TestChrec, *chrecMap.at(lv4.pre)));
820 TEST(ScalarEvolutionTests, InductionVariablesWithNonConstantInitialValuesAndMultiplication)
841 auto cv1 = lambda->AddContextVar(*x).inner;
842 auto cv2 = lambda->AddContextVar(*y).inner;
843 auto cv3 = lambda->AddContextVar(*z).inner;
844 auto cv4 = lambda->AddContextVar(*w).inner;
848 auto lv2 = theta->AddLoopVar(cv2);
849 auto lv3 = theta->AddLoopVar(cv3);
850 auto lv4 = theta->AddLoopVar(cv4);
853 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, c1.output(0) }, 32);
854 const auto res1 = addNode1.output(0);
856 auto & mulNode1 = jlm::rvsdg::CreateOpNode<IntegerMulOperation>({ lv1.pre, lv2.pre }, 32);
857 const auto res2 = mulNode1.output(0);
859 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv3.pre, res2 }, 32);
860 const auto res3 = addNode2.output(0);
862 auto & mulNode2 = jlm::rvsdg::CreateOpNode<IntegerMulOperation>({ res2, res2 }, 32);
865 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv4.pre, mulNode2.output(0) }, 32);
866 const auto res4 = addNode3.output(0);
869 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
870 const auto matchResult =
873 theta->set_predicate(matchResult);
874 lv2.post->divert_to(res1);
875 lv3.post->divert_to(res3);
876 lv4.post->divert_to(res4);
884 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
885 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
886 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
887 EXPECT_NE(chrecMap.find(lv4.pre), chrecMap.end());
892 lv1TestChrec.AddOperand(SCEVInit::Create(*lv1.pre));
893 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
898 lv2TestChrec.AddOperand(SCEVInit::Create(*lv2.pre));
899 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
900 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
905 lv3TestChrec.AddOperand(SCEVInit::Create(*lv3.pre));
906 lv3TestChrec.AddOperand(
907 SCEVNAryMulExpr::Create(SCEVInit::Create(*lv1.pre), SCEVInit::Create(*lv2.pre)));
908 lv3TestChrec.AddOperand(SCEVInit::Create(*lv1.pre));
910 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
919 lv4TestChrec.AddOperand(SCEVInit::Create(*lv4.pre));
920 lv4TestChrec.AddOperand(SCEVNAryMulExpr::Create(
921 SCEVInit::Create(*lv1.pre),
922 SCEVInit::Create(*lv2.pre),
923 SCEVInit::Create(*lv1.pre),
924 SCEVInit::Create(*lv2.pre)));
925 lv4TestChrec.AddOperand(SCEVNAryAddExpr::Create(
926 SCEVNAryMulExpr::Create(
927 SCEVInit::Create(*lv1.pre),
928 SCEVInit::Create(*lv2.pre),
929 SCEVInit::Create(*lv1.pre)),
930 SCEVNAryMulExpr::Create(SCEVInit::Create(*lv1.pre), SCEVInit::Create(*lv1.pre)),
931 SCEVNAryMulExpr::Create(
932 SCEVInit::Create(*lv1.pre),
933 SCEVInit::Create(*lv2.pre),
934 SCEVInit::Create(*lv1.pre))));
935 lv4TestChrec.AddOperand(SCEVNAryAddExpr::Create(
936 SCEVNAryMulExpr::Create(SCEVInit::Create(*lv1.pre), SCEVInit::Create(*lv1.pre)),
937 SCEVNAryMulExpr::Create(SCEVInit::Create(*lv1.pre), SCEVInit::Create(*lv1.pre))));
939 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv4TestChrec, *chrecMap.at(lv4.pre)));
942 TEST(ScalarEvolutionTests, SelfRecursiveInductionVariable)
950 const auto & graph = rvsdgModule.
Rvsdg();
955 const auto lv1 = theta->AddLoopVar(c0.output(0));
957 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, lv1.pre }, 32);
958 const auto result = addNode.output(0);
961 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ result, c5.output(0) }, 32);
962 const auto matchResult =
965 theta->set_predicate(matchResult);
966 lv1.post->divert_to(result);
974 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
978 lv1TestChrec.AddOperand(SCEVUnknown::Create());
979 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
982 TEST(ScalarEvolutionTests, DependentOnInvalidInductionVariable)
990 const auto & graph = rvsdgModule.
Rvsdg();
996 const auto lv1 = theta->AddLoopVar(c0.output(0));
997 const auto lv2 = theta->AddLoopVar(c1.output(0));
999 auto & addNode_1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, lv1.pre }, 32);
1000 const auto result_1 = addNode_1.output(0);
1002 auto & addNode_2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, lv1.pre }, 32);
1003 const auto result_2 = addNode_2.output(0);
1006 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ result_1, c5.output(0) }, 32);
1007 const auto matchResult =
1010 theta->set_predicate(matchResult);
1011 lv1.post->divert_to(result_1);
1012 lv2.post->divert_to(result_2);
1020 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
1021 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
1025 lv1TestChrec.AddOperand(SCEVUnknown::Create());
1026 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
1030 lv2TestChrec.AddOperand(SCEVConstant::Create(0));
1031 lv2TestChrec.AddOperand(SCEVUnknown::Create());
1032 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
1035 TEST(ScalarEvolutionTests, MutuallyDependentInductionVariables)
1044 const auto & graph = rvsdgModule.
Rvsdg();
1050 const auto lv1 = theta->AddLoopVar(c0.output(0));
1051 const auto lv2 = theta->AddLoopVar(c1.output(0));
1053 auto & addNode_1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, lv2.pre }, 32);
1054 const auto result_1 = addNode_1.output(0);
1056 auto & addNode_2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, lv2.pre }, 32);
1057 const auto result_2 = addNode_2.output(0);
1060 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ result_1, c5.output(0) }, 32);
1061 const auto matchResult =
1064 theta->set_predicate(matchResult);
1065 lv1.post->divert_to(result_1);
1066 lv2.post->divert_to(result_2);
1074 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
1075 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
1079 lv1TestChrec.AddOperand(SCEVUnknown::Create());
1081 lv2TestChrec.AddOperand(SCEVUnknown::Create());
1082 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
1083 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
1086 TEST(ScalarEvolutionTests, MultiLayeredMutuallyDependentInductionVariables)
1095 const auto & graph = rvsdgModule.
Rvsdg();
1103 const auto lv1 = theta->AddLoopVar(c0.output(0));
1104 const auto lv2 = theta->AddLoopVar(c1.output(0));
1105 const auto lv3 = theta->AddLoopVar(c2.output(0));
1106 const auto lv4 = theta->AddLoopVar(c3.output(0));
1108 auto & addNode_1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, lv2.pre }, 32);
1109 const auto result_1 = addNode_1.output(0);
1110 auto & addNode_2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, lv3.pre }, 32);
1111 const auto result_2 = addNode_2.output(0);
1112 auto & addNode_3 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv3.pre, lv4.pre }, 32);
1113 const auto result_3 = addNode_3.output(0);
1114 auto & addNode_4 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv4.pre, lv1.pre }, 32);
1115 const auto result_4 = addNode_4.output(0);
1118 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ result_1, c5.output(0) }, 32);
1119 const auto matchResult =
1122 theta->set_predicate(matchResult);
1123 lv1.post->divert_to(result_1);
1124 lv2.post->divert_to(result_2);
1125 lv3.post->divert_to(result_3);
1126 lv4.post->divert_to(result_4);
1134 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
1135 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
1136 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
1137 EXPECT_NE(chrecMap.find(lv4.pre), chrecMap.end());
1141 lv1TestChrec.AddOperand(SCEVUnknown::Create());
1143 lv2TestChrec.AddOperand(SCEVUnknown::Create());
1145 lv3TestChrec.AddOperand(SCEVUnknown::Create());
1147 lv4TestChrec.AddOperand(SCEVUnknown::Create());
1149 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
1150 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
1151 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
1152 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv4TestChrec, *chrecMap.at(lv4.pre)));
1155 TEST(ScalarEvolutionTests, InductionVariablesInNestedLoops)
1164 const auto & graph = rvsdgModule.
Rvsdg();
1168 const auto lv1 = theta1->AddLoopVar(c0.output(0));
1171 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
1172 const auto res1 = addNode1.output(0);
1175 auto & sltNode1 = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
1176 const auto matchResult1 =
1180 const auto lv2 = theta2->AddLoopVar(c1.output(0));
1181 const auto lv3 = theta2->AddLoopVar(lv1.pre);
1183 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, lv3.pre }, 32);
1184 const auto & res2 = addNode2.output(0);
1186 const auto & c10 = IntegerConstantOperation::Create(*theta2->subregion(), 32, 10);
1187 auto & sltNode2 = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res2, c10.output(0) }, 32);
1189 const auto matchResult2 =
1192 theta1->set_predicate(matchResult1);
1193 lv1.post->divert_to(res1);
1195 theta2->set_predicate(matchResult2);
1196 lv2.post->divert_to(res2);
1204 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
1206 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
1207 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
1211 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
1212 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
1213 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
1218 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
1219 lv2TestChrec.AddOperand(lv1TestChrec.Clone());
1220 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
1224 lv3TestChrec.AddOperand(lv1TestChrec.Clone());
1225 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
1228 TEST(ScalarEvolutionTests, InductionVariablesInNestedLoopsWithFolding)
1236 const auto & graph = rvsdgModule.
Rvsdg();
1243 const auto lv1_1 = theta1->AddLoopVar(c0_1.output(0));
1244 const auto lv2_1 = theta1->AddLoopVar(c2_1.output(0));
1245 const auto lv3_1 = theta1->AddLoopVar(c3_1.output(0));
1252 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1_1.pre, c1_2.output(0) }, 32);
1254 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2_1.pre, c2_2.output(0) }, 32);
1256 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv3_1.pre, c3_2.output(0) }, 32);
1257 const auto res1 = addNode1.output(0);
1258 const auto res2 = addNode2.output(0);
1259 const auto res3 = addNode3.output(0);
1262 auto & sltNode1 = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
1263 const auto matchResult1 =
1267 const auto lv1_2 = theta2->AddLoopVar(res1);
1268 const auto lv2_2 = theta2->AddLoopVar(res2);
1269 const auto lv3_2 = theta2->AddLoopVar(res3);
1270 const auto lv4 = theta2->AddLoopVar(c1_2.output(0));
1271 const auto lv5 = theta2->AddLoopVar(c1_2.output(0));
1273 auto & addNode4 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1_2.pre, lv2_2.pre }, 32);
1275 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ addNode4.output(0), lv3_2.pre }, 32);
1277 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv4.pre, addNode5.output(0) }, 32);
1278 const auto & res4 = addNode6.output(0);
1280 auto & mulNode1 = jlm::rvsdg::CreateOpNode<IntegerMulOperation>({ lv1_2.pre, lv2_2.pre }, 32);
1282 jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv5.pre, mulNode1.output(0) }, 32);
1283 const auto & res5 = addNode7.output(0);
1285 const auto & c10 = IntegerConstantOperation::Create(*theta2->subregion(), 32, 10);
1286 auto & sltNode2 = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res4, c10.output(0) }, 32);
1288 const auto matchResult2 =
1292 theta1->set_predicate(matchResult1);
1293 lv1_1.post->divert_to(res1);
1294 lv2_1.post->divert_to(res2);
1295 lv3_1.post->divert_to(res3);
1298 theta2->set_predicate(matchResult2);
1299 lv4.post->divert_to(res4);
1300 lv5.post->divert_to(res5);
1308 EXPECT_NE(chrecMap.find(lv1_1.pre), chrecMap.end());
1309 EXPECT_NE(chrecMap.find(lv2_1.pre), chrecMap.end());
1310 EXPECT_NE(chrecMap.find(lv3_1.pre), chrecMap.end());
1312 EXPECT_NE(chrecMap.find(lv1_2.pre), chrecMap.end());
1313 EXPECT_NE(chrecMap.find(lv2_2.pre), chrecMap.end());
1314 EXPECT_NE(chrecMap.find(lv3_2.pre), chrecMap.end());
1315 EXPECT_NE(chrecMap.find(lv4.pre), chrecMap.end());
1316 EXPECT_NE(chrecMap.find(lv5.pre), chrecMap.end());
1320 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
1321 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
1322 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1_1.pre)));
1326 lv2TestChrec.AddOperand(SCEVConstant::Create(2));
1327 lv2TestChrec.AddOperand(SCEVConstant::Create(2));
1328 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2_1.pre)));
1332 lv3TestChrec.AddOperand(SCEVConstant::Create(3));
1333 lv3TestChrec.AddOperand(SCEVConstant::Create(3));
1334 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3_1.pre)));
1338 const auto lv1_2InnerChrec = SCEVChainRecurrence::Create(*theta1, *lv1_1.post->origin());
1339 lv1_2InnerChrec->AddOperand(SCEVConstant::Create(1));
1340 lv1_2InnerChrec->AddOperand(SCEVConstant::Create(1));
1341 lv1_2TestChrec.AddOperand(lv1_2InnerChrec->Clone());
1342 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1_2TestChrec, *chrecMap.at(lv1_2.pre)));
1346 const auto lv2_2InnerChrec = SCEVChainRecurrence::Create(*theta1, *lv2_1.post->origin());
1347 lv2_2InnerChrec->AddOperand(SCEVConstant::Create(4));
1348 lv2_2InnerChrec->AddOperand(SCEVConstant::Create(2));
1349 lv2_2TestChrec.AddOperand(lv2_2InnerChrec->Clone());
1350 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2_2TestChrec, *chrecMap.at(lv2_2.pre)));
1354 const auto lv3_2InnerChrec = SCEVChainRecurrence::Create(*theta1, *lv3_1.post->origin());
1355 lv3_2InnerChrec->AddOperand(SCEVConstant::Create(6));
1356 lv3_2InnerChrec->AddOperand(SCEVConstant::Create(3));
1357 lv3_2TestChrec.AddOperand(lv3_2InnerChrec->Clone());
1358 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3_2TestChrec, *chrecMap.at(lv3_2.pre)));
1364 lv4TestChrec.AddOperand(SCEVConstant::Create(1));
1365 const auto lv4InnerChrec = SCEVChainRecurrence::Create(*theta1, *lv4.pre);
1366 lv4InnerChrec->AddOperand(SCEVConstant::Create(11));
1367 lv4InnerChrec->AddOperand(SCEVConstant::Create(6));
1368 lv4TestChrec.AddOperand(lv4InnerChrec->Clone());
1369 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv4TestChrec, *chrecMap.at(lv4.pre)));
1374 lv5TestChrec.AddOperand(SCEVConstant::Create(1));
1375 const auto lv5InnerChrec = SCEVChainRecurrence::Create(*theta1, *lv5.pre);
1376 lv5InnerChrec->AddOperand(SCEVConstant::Create(4));
1377 lv5InnerChrec->AddOperand(SCEVConstant::Create(8));
1378 lv5InnerChrec->AddOperand(SCEVConstant::Create(4));
1379 lv5TestChrec.AddOperand(lv5InnerChrec->Clone());
1380 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv5TestChrec, *chrecMap.at(lv5.pre)));
1383 TEST(ScalarEvolutionTests, InductionVariablesInSisterLoops)
1393 const auto & graph = rvsdgModule.
Rvsdg();
1397 const auto lv1 = theta1->AddLoopVar(c0.output(0));
1400 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
1401 const auto res1 = addNode1.output(0);
1404 auto & sltNode1 = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c5.output(0) }, 32);
1405 const auto matchResult1 =
1408 const auto & c2 = IntegerConstantOperation::Create(graph.GetRootRegion(), 32, 2);
1410 const auto lv2 = theta2->AddLoopVar(c2.output(0));
1411 const auto lv3 = theta2->AddLoopVar(theta1->output(0));
1413 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, lv3.pre }, 32);
1414 const auto & res2 = addNode2.output(0);
1416 const auto & c10 = IntegerConstantOperation::Create(*theta2->subregion(), 32, 10);
1417 auto & sltNode2 = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res2, c10.output(0) }, 32);
1419 const auto matchResult2 =
1422 theta1->set_predicate(matchResult1);
1423 lv1.post->divert_to(res1);
1425 theta2->set_predicate(matchResult2);
1426 lv2.post->divert_to(res2);
1434 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
1436 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
1437 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
1441 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
1442 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
1443 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
1448 lv2TestChrec.AddOperand(SCEVConstant::Create(2));
1450 lv2InnerChrec.AddOperand(SCEVConstant::Create(1));
1451 lv2InnerChrec.AddOperand(SCEVConstant::Create(1));
1452 lv2TestChrec.AddOperand(lv2InnerChrec.Clone());
1453 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
1457 lv3TestChrec.AddOperand(lv2InnerChrec.Clone());
1458 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
1461 TEST(ScalarEvolutionTests, ComputeRecurrenceForArrayGEP)
1472 const auto & graph = rvsdgModule.
Rvsdg();
1475 graph.GetRootRegion(),
1478 { pointerType, memoryStateType },
1479 { intType, memoryStateType }),
1484 &graph.GetRootRegion(),
1497 arrayC5.output(0) });
1498 delta->finalize(constantArray);
1500 const auto cv1 = lambda->AddContextVar(delta->output());
1506 const auto memoryState = theta->AddLoopVar(lambda->GetFunctionArguments()[1]);
1507 const auto lv1 = theta->AddLoopVar(c0_1.output(0));
1508 const auto lv2 = theta->AddLoopVar(c1_1.output(0));
1509 const auto lv3 = theta->AddLoopVar(cv1.inner);
1513 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1_2.output(0) }, 32);
1514 const auto res1 = addNode1.output(0);
1524 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, loadedValue }, 32);
1525 const auto res2 = addNode2.output(0);
1528 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c4.output(0) }, 32);
1529 const auto matchResult =
1532 theta->set_predicate(matchResult);
1534 lv1.post->divert_to(res1);
1535 lv2.post->divert_to(res2);
1543 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
1544 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
1545 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
1546 EXPECT_NE(chrecMap.find(gep), chrecMap.end());
1550 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
1551 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
1552 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
1556 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
1557 lv2TestChrec.AddOperand(SCEVUnknown::Create());
1558 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
1562 lv3TestChrec.AddOperand(SCEVInit::Create(*lv3.pre));
1563 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
1570 gepTestChrec.AddOperand(SCEVInit::Create(*lv3.pre));
1571 gepTestChrec.AddOperand(SCEVConstant::Create(4));
1572 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(gepTestChrec, *chrecMap.at(gep)));
1575 TEST(ScalarEvolutionTests, ComputeRecurrenceForStructGEP)
1581 const auto intStructType =
1587 const auto & graph = rvsdgModule.
Rvsdg();
1590 graph.GetRootRegion(),
1593 { pointerType, memoryStateType },
1594 { intType, memoryStateType }),
1599 &graph.GetRootRegion(),
1609 *delta->subregion(),
1610 { structC1.output(0),
1614 structC5.output(0) },
1616 delta->finalize(&constantStruct);
1618 const auto cv1 = lambda->AddContextVar(delta->output());
1624 const auto memoryState = theta->AddLoopVar(lambda->GetFunctionArguments()[1]);
1625 const auto lv1 = theta->AddLoopVar(c0_1.output(0));
1626 const auto lv2 = theta->AddLoopVar(c1_1.output(0));
1627 const auto lv3 = theta->AddLoopVar(cv1.inner);
1631 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1_2.output(0) }, 32);
1632 const auto res1 = addNode1.output(0);
1639 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, loadedValue }, 32);
1640 const auto res2 = addNode2.output(0);
1643 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res1, c4.output(0) }, 32);
1644 const auto matchResult =
1647 theta->set_predicate(matchResult);
1649 lv1.post->divert_to(res1);
1650 lv2.post->divert_to(res2);
1658 EXPECT_NE(chrecMap.find(lv1.pre), chrecMap.end());
1659 EXPECT_NE(chrecMap.find(lv2.pre), chrecMap.end());
1660 EXPECT_NE(chrecMap.find(lv3.pre), chrecMap.end());
1661 EXPECT_NE(chrecMap.find(gep), chrecMap.end());
1665 lv1TestChrec.AddOperand(SCEVConstant::Create(0));
1666 lv1TestChrec.AddOperand(SCEVConstant::Create(1));
1667 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv1TestChrec, *chrecMap.at(lv1.pre)));
1671 lv2TestChrec.AddOperand(SCEVConstant::Create(1));
1672 lv2TestChrec.AddOperand(SCEVUnknown::Create());
1673 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv2TestChrec, *chrecMap.at(lv2.pre)));
1677 lv3TestChrec.AddOperand(SCEVInit::Create(*lv3.pre));
1678 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(lv3TestChrec, *chrecMap.at(lv3.pre)));
1685 gepTestChrec.AddOperand(SCEVInit::Create(*lv3.pre));
1686 gepTestChrec.AddOperand(SCEVConstant::Create(4));
1687 EXPECT_TRUE(ScalarEvolution::StructurallyEqual(gepTestChrec, *chrecMap.at(gep)));
1690 TEST(ScalarEvolutionTests, ComputeTripCountForSLTComparisonWithAffineRecurrence)
1698 const auto & graph = rvsdgModule.
Rvsdg();
1703 const auto lv1 = theta->AddLoopVar(c0.output(0));
1706 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
1707 const auto result = addNode.output(0);
1710 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ result, c5.output(0) }, 32);
1711 const auto matchResult =
1714 theta->set_predicate(matchResult);
1715 lv1.post->divert_to(result);
1723 EXPECT_NE(tripCountMap.find(theta), tripCountMap.end());
1724 const auto tripCount = tripCountMap.at(theta);
1725 EXPECT_TRUE(tripCount == 5);
1728 TEST(ScalarEvolutionTests, ComputeTripCountForSLEComparisonWithAffineRecurrence)
1736 const auto & graph = rvsdgModule.
Rvsdg();
1741 const auto lv1 = theta->AddLoopVar(c0.output(0));
1744 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
1745 const auto result = addNode.output(0);
1748 auto & sleNode = jlm::rvsdg::CreateOpNode<IntegerSleOperation>({ result, c5.output(0) }, 32);
1749 const auto matchResult =
1752 theta->set_predicate(matchResult);
1753 lv1.post->divert_to(result);
1761 EXPECT_NE(tripCountMap.find(theta), tripCountMap.end());
1763 const auto tripCount = tripCountMap.at(theta);
1765 EXPECT_TRUE(tripCount == 6);
1768 TEST(ScalarEvolutionTests, ComputeTripCountForSGTComparisonWithAffineRecurrence)
1776 const auto & graph = rvsdgModule.
Rvsdg();
1781 const auto lv1 = theta->AddLoopVar(c5.output(0));
1784 auto & subNode = jlm::rvsdg::CreateOpNode<IntegerSubOperation>({ lv1.pre, c1.output(0) }, 32);
1785 const auto result = subNode.output(0);
1788 auto & sgtNode = jlm::rvsdg::CreateOpNode<IntegerSgtOperation>({ result, c0.output(0) }, 32);
1789 const auto matchResult =
1792 theta->set_predicate(matchResult);
1793 lv1.post->divert_to(result);
1801 EXPECT_NE(tripCountMap.find(theta), tripCountMap.end());
1802 const auto tripCount = tripCountMap.at(theta);
1803 EXPECT_TRUE(tripCount == 5);
1806 TEST(ScalarEvolutionTests, ComputeTripCountForSGEComparisonWithAffineRecurrence)
1814 const auto & graph = rvsdgModule.
Rvsdg();
1819 const auto lv1 = theta->AddLoopVar(c5.output(0));
1822 auto & subNode = jlm::rvsdg::CreateOpNode<IntegerSubOperation>({ lv1.pre, c1.output(0) }, 32);
1823 const auto result = subNode.output(0);
1826 auto & sgeNode = jlm::rvsdg::CreateOpNode<IntegerSgeOperation>({ result, c0.output(0) }, 32);
1827 const auto matchResult =
1830 theta->set_predicate(matchResult);
1831 lv1.post->divert_to(result);
1839 EXPECT_NE(tripCountMap.find(theta), tripCountMap.end());
1841 const auto tripCount = tripCountMap.at(theta);
1842 EXPECT_TRUE(tripCount == 6);
1845 TEST(ScalarEvolutionTests, ComputeTripCountForNEComparisonWithAffineRecurrence)
1853 const auto & graph = rvsdgModule.
Rvsdg();
1858 const auto lv1 = theta->AddLoopVar(c0.output(0));
1861 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
1862 const auto result = addNode.output(0);
1865 auto & neNode = jlm::rvsdg::CreateOpNode<IntegerNeOperation>({ result, c5.output(0) }, 32);
1866 const auto matchResult =
1869 theta->set_predicate(matchResult);
1870 lv1.post->divert_to(result);
1878 EXPECT_NE(tripCountMap.find(theta), tripCountMap.end());
1879 const auto tripCount = tripCountMap.at(theta);
1880 EXPECT_TRUE(tripCount == 5);
1883 TEST(ScalarEvolutionTests, ComputeTripCountForEQComparisonWithAffineRecurrence)
1891 const auto & graph = rvsdgModule.
Rvsdg();
1896 const auto lv1 = theta->AddLoopVar(c0.output(0));
1899 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1_1.output(0) }, 32);
1900 const auto result = addNode.output(0);
1903 auto & eqNode = jlm::rvsdg::CreateOpNode<IntegerEqOperation>({ result, c1_2.output(0) }, 32);
1904 const auto matchResult =
1907 theta->set_predicate(matchResult);
1908 lv1.post->divert_to(result);
1916 EXPECT_NE(tripCountMap.find(theta), tripCountMap.end());
1917 const auto tripCount = tripCountMap.at(theta);
1918 EXPECT_TRUE(tripCount == 2);
1921 TEST(ScalarEvolutionTests, ComputeTripCountForInfiniteSLTComparisonWithAffineRecurrence)
1929 const auto & graph = rvsdgModule.
Rvsdg();
1934 const auto lv1 = theta->AddLoopVar(c0.output(0));
1937 auto & subNode = jlm::rvsdg::CreateOpNode<IntegerSubOperation>({ lv1.pre, c1.output(0) }, 32);
1938 const auto result = subNode.output(0);
1941 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ result, c5.output(0) }, 32);
1942 const auto matchResult =
1945 theta->set_predicate(matchResult);
1946 lv1.post->divert_to(result);
1956 EXPECT_EQ(tripCountMap.find(theta), tripCountMap.end());
1959 TEST(ScalarEvolutionTests, ComputeTripCountForInfiniteSGTComparisonWithAffineRecurrence)
1967 const auto & graph = rvsdgModule.
Rvsdg();
1972 const auto lv1 = theta->AddLoopVar(c5.output(0));
1975 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
1976 const auto result = addNode.output(0);
1979 auto & sgeNode = jlm::rvsdg::CreateOpNode<IntegerSgeOperation>({ result, c0.output(0) }, 32);
1980 const auto matchResult =
1983 theta->set_predicate(matchResult);
1984 lv1.post->divert_to(result);
1994 EXPECT_EQ(tripCountMap.find(theta), tripCountMap.end());
1997 TEST(ScalarEvolutionTests, ComputeTripCountForInfiniteNEComparisonWithAffineRecurrence)
2005 const auto & graph = rvsdgModule.
Rvsdg();
2010 const auto lv1 = theta->AddLoopVar(c0.output(0));
2013 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c2.output(0) }, 32);
2014 const auto result = addNode.output(0);
2017 auto & neNode = jlm::rvsdg::CreateOpNode<IntegerNeOperation>({ result, c5.output(0) }, 32);
2018 const auto matchResult =
2021 theta->set_predicate(matchResult);
2022 lv1.post->divert_to(result);
2032 EXPECT_EQ(tripCountMap.find(theta), tripCountMap.end());
2035 TEST(ScalarEvolutionTests, ComputeTripCountForSimpleQuadraticRecurrence)
2043 const auto & graph = rvsdgModule.
Rvsdg();
2049 const auto lv1 = theta->AddLoopVar(c0.output(0));
2050 const auto lv2 = theta->AddLoopVar(c1_1.output(0));
2053 auto & addNode = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1_2.output(0) }, 32);
2054 const auto res1 = addNode.output(0);
2056 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, res1 }, 32);
2057 const auto res2 = addNode2.output(0);
2060 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res2, c10.output(0) }, 32);
2061 const auto matchResult =
2064 theta->set_predicate(matchResult);
2065 lv1.post->divert_to(res1);
2066 lv2.post->divert_to(res2);
2074 EXPECT_NE(tripCountMap.find(theta), tripCountMap.end());
2075 const auto tripCount = tripCountMap.at(theta);
2076 EXPECT_TRUE(tripCount == 4);
2079 TEST(ScalarEvolutionTests, TestTripCountCouldNotCompute)
2087 const auto & graph = rvsdgModule.
Rvsdg();
2094 const auto lv1 = theta->AddLoopVar(c2.output(0));
2095 const auto lv2 = theta->AddLoopVar(c3.output(0));
2096 const auto lv3 = theta->AddLoopVar(c4.output(0));
2099 auto & addNode1 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv1.pre, c1.output(0) }, 32);
2100 const auto res1 = addNode1.output(0);
2102 auto & addNode2 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv2.pre, res1 }, 32);
2103 const auto res2 = addNode2.output(0);
2105 auto & addNode3 = jlm::rvsdg::CreateOpNode<IntegerAddOperation>({ lv3.pre, res2 }, 32);
2106 const auto res3 = addNode3.output(0);
2109 auto & sltNode = jlm::rvsdg::CreateOpNode<IntegerSltOperation>({ res3, c50.output(0) }, 32);
2110 const auto matchResult =
2113 theta->set_predicate(matchResult);
2114 lv1.post->divert_to(res1);
2115 lv2.post->divert_to(res2);
2116 lv3.post->divert_to(res3);
2127 EXPECT_EQ(tripCountMap.find(theta), tripCountMap.end());
static jlm::util::StatisticsCollector statisticsCollector
TEST(ScalarEvolutionTests, NonEvolvingVariable)
static std::pair< std::unordered_map< const jlm::rvsdg::Output *, std::unique_ptr< jlm::llvm::SCEVChainRecurrence > >, std::unordered_map< const jlm::rvsdg::ThetaNode *, size_t > > RunScalarEvolution(jlm::rvsdg::RvsdgModule &rvsdgModule)
static std::shared_ptr< const ArrayType > Create(std::shared_ptr< const Type > type, size_t nelements)
static jlm::rvsdg::Output * Create(const std::vector< jlm::rvsdg::Output * > &elements)
static rvsdg::Output & Create(rvsdg::Region &, const std::vector< rvsdg::Output * > &operands, std::shared_ptr< const rvsdg::Type > resultType)
static std::unique_ptr< DeltaOperation > Create(std::shared_ptr< const rvsdg::Type > type, const std::string &name, const Linkage &linkage, std::string section, bool constant, const size_t alignment)
static rvsdg::Output * create(rvsdg::Output *baseAddress, const std::vector< rvsdg::Output * > &indices, std::shared_ptr< const rvsdg::Type > pointeeType)
static rvsdg::Node & Create(rvsdg::Region ®ion, IntegerValueRepresentation representation)
static std::unique_ptr< LlvmLambdaOperation > Create(std::shared_ptr< const jlm::rvsdg::FunctionType > type, std::string name, const jlm::llvm::Linkage &linkage, jlm::llvm::CallingConvention callingConvention, jlm::llvm::AttributeSet attributes)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *state, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
static std::shared_ptr< const MemoryStateType > Create()
static std::shared_ptr< const PointerType > Create()
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const rvsdg::Type > &type)
std::unordered_map< const rvsdg::Output *, std::unique_ptr< SCEVChainRecurrence > > GetChrecMap() const
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
std::unordered_map< const rvsdg::ThetaNode *, size_t > GetTripCountMap() const noexcept
static std::shared_ptr< const StructType > CreateLiteral(std::vector< std::shared_ptr< const Type >> types, bool isPacked)
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
static DeltaNode * Create(rvsdg::Region *parent, std::unique_ptr< DeltaOperation > op)
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 GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
Region & GetRootRegion() const noexcept
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
static Output * Create(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
static ThetaNode * create(rvsdg::Region *parent)
LoopVar AddLoopVar(rvsdg::Output *origin)
Creates a new loop-carried variable.
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)
rvsdg::Output * output
Variable at loop exit (output of theta).