21TEST(TraceTests, TestTraceOutputIntraProcedural_Gamma)
26 const auto controlType = ControlType::Create(2);
27 const auto valueType = TestType::createValueType();
30 auto & i0 = GraphImport::Create(rvsdg, controlType,
"i0");
31 auto & i1 = GraphImport::Create(rvsdg, valueType,
"i1");
32 auto & i2 = GraphImport::Create(rvsdg, valueType,
"i2");
34 const auto gammaNode = GammaNode::create(&i0, 2);
35 auto entryVar1 = gammaNode->AddEntryVar(&i1);
36 auto entryVar1Copy = gammaNode->AddEntryVar(&i1);
37 auto entryVar2 = gammaNode->AddEntryVar(&i2);
39 auto node = TestOperation::createNode(
40 gammaNode->subregion(1),
41 { entryVar2.branchArgument[1] },
45 gammaNode->AddExitVar({ entryVar1.branchArgument[0], entryVar1Copy.branchArgument[1] });
47 gammaNode->AddExitVar({ entryVar1.branchArgument[0], entryVar2.branchArgument[1] });
48 auto exitVar2 = gammaNode->AddExitVar({ entryVar2.branchArgument[0], node->output(0) });
50 auto & x0 = GraphExport::Create(*exitVar0.output,
"x0");
51 auto & x1 = GraphExport::Create(*exitVar1.output,
"x1");
52 auto & x2 = GraphExport::Create(*exitVar2.output,
"x2");
57 const auto & tracedX0 = traceOutputIntraProcedurally(*x0.origin(),
false);
58 const auto & tracedX1 = traceOutputIntraProcedurally(*x1.origin(),
false);
59 const auto & tracedX2 = traceOutputIntraProcedurally(*x2.origin(),
false);
61 const auto & traceGammaEntry = traceOutputIntraProcedurally(*entryVar1.branchArgument[0],
false);
62 const auto & tracedNodeInput = traceOutputIntraProcedurally(*node->input(0)->origin(),
false);
65 EXPECT_EQ(&tracedX0, &i1);
66 EXPECT_EQ(&tracedX1, x1.origin());
67 EXPECT_EQ(&tracedX2, x2.origin());
68 EXPECT_EQ(&traceGammaEntry, &i1);
69 EXPECT_EQ(&tracedNodeInput, &i2);
75TEST(TraceTests, TestTraceOutputIntraProcedural_Theta)
80 const auto valueType = TestType::createValueType();
83 auto & i0 = GraphImport::Create(rvsdg, valueType,
"i0");
84 auto & i1 = GraphImport::Create(rvsdg, valueType,
"i1");
86 const auto thetaNode = ThetaNode::create(&rvsdg.
GetRootRegion());
88 auto loopVar0 = thetaNode->AddLoopVar(&i0);
89 auto loopVar1 = thetaNode->AddLoopVar(&i1);
91 auto node = TestOperation::createNode(thetaNode->subregion(), { loopVar1.pre }, { valueType });
92 loopVar1.post->divert_to(node->output(0));
94 auto & x0 = GraphExport::Create(*loopVar0.output,
"x0");
95 auto & x1 = GraphExport::Create(*loopVar1.output,
"x1");
100 const auto & tracedX0 = traceOutputIntraProcedurally(*x0.origin(),
false);
101 const auto & tracedX1 = traceOutputIntraProcedurally(*x1.origin(),
false);
102 const auto & traceLoopVar0Pre = traceOutputIntraProcedurally(*loopVar0.pre,
false);
103 const auto & traceLoopVar1Pre = traceOutputIntraProcedurally(*loopVar1.pre,
false);
104 const auto & tracedNodeInput = traceOutputIntraProcedurally(*node->input(0)->origin(),
false);
107 EXPECT_EQ(&tracedX0, &i0);
108 EXPECT_EQ(&tracedX1, x1.origin());
109 EXPECT_EQ(&traceLoopVar0Pre, &i0);
110 EXPECT_EQ(&traceLoopVar1Pre, loopVar1.pre);
111 EXPECT_EQ(&tracedNodeInput, loopVar1.pre);
117TEST(TraceTests, TestTraceNestedStructuralNodes)
122 const auto controlType = ControlType::Create(2);
123 const auto valueType = TestType::createValueType();
126 auto & i0 = GraphImport::Create(rvsdg, valueType,
"i0");
127 auto & i1 = GraphImport::Create(rvsdg, valueType,
"i1");
128 auto & i2 = GraphImport::Create(rvsdg, valueType,
"i2");
130 const auto thetaNode = ThetaNode::create(&rvsdg.
GetRootRegion());
132 auto loopVar0 = thetaNode->AddLoopVar(&i0);
133 auto loopVar1 = thetaNode->AddLoopVar(&i1);
134 auto loopVar2 = thetaNode->AddLoopVar(&i2);
139 const auto gammaNode = GammaNode::create(undefNode.output(0), 2);
140 auto entryVar0 = gammaNode->AddEntryVar(loopVar0.pre);
141 auto entryVar1 = gammaNode->AddEntryVar(loopVar1.pre);
143 gammaNode->AddExitVar({ entryVar0.branchArgument[0], entryVar0.branchArgument[1] });
145 gammaNode->AddExitVar({ entryVar1.branchArgument[0], entryVar1.branchArgument[1] });
149 loopVar0.post->divert_to(exitVar0.output);
150 loopVar1.post->divert_to(exitVar0.output);
152 auto & x0 = GraphExport::Create(*loopVar0.output,
"x0");
153 auto & x1 = GraphExport::Create(*loopVar1.output,
"x1");
154 auto & x2 = GraphExport::Create(*loopVar2.output,
"x2");
160 const auto & tracedX0 = traceOutputIntraProcedurally(*x0.origin(),
false);
161 const auto & tracedX1 = traceOutputIntraProcedurally(*x1.origin(),
false);
162 const auto & tracedX2 = traceOutputIntraProcedurally(*x2.origin(),
false);
163 const auto & traceExitVar0 = traceOutputIntraProcedurally(*exitVar0.output,
false);
164 const auto & traceExitVar1 = traceOutputIntraProcedurally(*exitVar1.output,
false);
165 const auto & traceBranchArgument0 =
166 traceOutputIntraProcedurally(*entryVar0.branchArgument[0],
false);
167 const auto & traceBranchArgument1 =
168 traceOutputIntraProcedurally(*entryVar1.branchArgument[1],
false);
169 const auto & traceLoopVar0Pre = traceOutputIntraProcedurally(*loopVar0.pre,
false);
170 const auto & traceLoopVar1Pre = traceOutputIntraProcedurally(*loopVar1.pre,
false);
171 const auto & traceLoopVar2Pre = traceOutputIntraProcedurally(*loopVar2.pre,
false);
173 EXPECT_EQ(&tracedX0, &i0);
174 EXPECT_EQ(&tracedX1, loopVar1.output);
175 EXPECT_EQ(&tracedX2, &i2);
176 EXPECT_EQ(&traceExitVar0, &i0);
177 EXPECT_EQ(&traceExitVar1, loopVar1.pre);
178 EXPECT_EQ(&traceBranchArgument0, &i0);
179 EXPECT_EQ(&traceBranchArgument1, loopVar1.pre);
180 EXPECT_EQ(&traceLoopVar0Pre, &i0);
181 EXPECT_EQ(&traceLoopVar1Pre, loopVar1.pre);
182 EXPECT_EQ(&traceLoopVar2Pre, &i2);
190 OutputTracer::StructuralNodePolicy::traceThroughTriviallyInvariant);
192 const auto & tracedX0 = shallowTracer.
trace(*x0.origin());
193 const auto & tracedX1 = shallowTracer.
trace(*x1.origin());
194 const auto & tracedX2 = shallowTracer.
trace(*x2.origin());
195 const auto & traceExitVar0 = shallowTracer.
trace(*exitVar0.output);
196 const auto & traceExitVar1 = shallowTracer.
trace(*exitVar1.output);
197 const auto & traceBranchArgument0 = shallowTracer.
trace(*entryVar0.branchArgument[0]);
198 const auto & traceBranchArgument1 = shallowTracer.
trace(*entryVar1.branchArgument[1]);
199 const auto & traceLoopVar0Pre = shallowTracer.
trace(*loopVar0.pre);
200 const auto & traceLoopVar1Pre = shallowTracer.
trace(*loopVar1.pre);
201 const auto & traceLoopVar2Pre = shallowTracer.
trace(*loopVar2.pre);
203 EXPECT_EQ(&tracedX0, loopVar0.output);
204 EXPECT_EQ(&tracedX1, loopVar1.output);
205 EXPECT_EQ(&tracedX2, &i2);
206 EXPECT_EQ(&traceExitVar0, loopVar0.pre);
207 EXPECT_EQ(&traceExitVar1, loopVar1.pre);
208 EXPECT_EQ(&traceBranchArgument0, loopVar0.pre);
209 EXPECT_EQ(&traceBranchArgument1, loopVar1.pre);
210 EXPECT_EQ(&traceLoopVar0Pre, loopVar0.pre);
211 EXPECT_EQ(&traceLoopVar1Pre, loopVar1.pre);
212 EXPECT_EQ(&traceLoopVar2Pre, &i2);
221TEST(TraceTests, TestIndirectLoopInvariantOutput)
246 auto & c20 = BitConstantOperation::create(rvsdg.
GetRootRegion(), { 32, 20 });
247 auto & c40 = BitConstantOperation::create(rvsdg.
GetRootRegion(), { 32, 40 });
249 const auto thetaNode = ThetaNode::create(&rvsdg.
GetRootRegion());
250 auto invariantLoopVar = thetaNode->AddLoopVar(&c20);
251 auto indirectLoopVar = thetaNode->AddLoopVar(&c40);
254 auto user1 = TestOperation::createNode(thetaNode->subregion(), { indirectLoopVar.pre }, {});
257 indirectLoopVar.post->divert_to(invariantLoopVar.pre);
260 auto user2 = TestOperation::createNode(&rvsdg.
GetRootRegion(), { indirectLoopVar.output }, {});
265 const auto & tracedUser1 = traceOutputIntraProcedurally(*user1->input(0)->origin(),
false);
266 const auto & tracedUser2 = traceOutputIntraProcedurally(*user2->input(0)->origin(),
false);
269 EXPECT_TRUE(ThetaLoopVarIsInvariant(invariantLoopVar));
270 EXPECT_FALSE(ThetaLoopVarIsInvariant(indirectLoopVar));
271 EXPECT_EQ(&tracedUser1, indirectLoopVar.pre);
272 EXPECT_EQ(&tracedUser2, &c20);
279TEST(TraceTests, TestIndirectLoopInvariance)
304 auto & c20 = BitConstantOperation::create(rvsdg.
GetRootRegion(), { 32, 20 });
306 const auto thetaNode = ThetaNode::create(&rvsdg.
GetRootRegion());
307 auto invariantLoopVar = thetaNode->AddLoopVar(&c20);
308 auto indirectLoopVar = thetaNode->AddLoopVar(&c20);
311 auto user1 = TestOperation::createNode(thetaNode->subregion(), { indirectLoopVar.pre }, {});
314 indirectLoopVar.post->divert_to(invariantLoopVar.pre);
317 auto user2 = TestOperation::createNode(&rvsdg.
GetRootRegion(), { indirectLoopVar.output }, {});
322 const auto & tracedUser1 = traceOutputIntraProcedurally(*user1->input(0)->origin(),
false);
323 const auto & tracedUser2 = traceOutputIntraProcedurally(*user2->input(0)->origin(),
false);
326 EXPECT_TRUE(ThetaLoopVarIsInvariant(invariantLoopVar));
327 EXPECT_FALSE(ThetaLoopVarIsInvariant(indirectLoopVar));
328 EXPECT_EQ(&tracedUser1, &c20);
329 EXPECT_EQ(&tracedUser2, &c20);
336TEST(TraceTests, TestEnterThetaSubregion)
364 const auto valueType = TestType::createValueType();
367 auto & i1 = GraphImport::Create(rvsdg, valueType,
"i1");
370 auto loopVar = thetaNode->AddLoopVar(&i1);
372 auto node = TestOperation::createNode(thetaNode->subregion(), { loopVar.pre }, { valueType });
373 loopVar.post->divert_to(node->output(0));
375 auto & x1 = GraphExport::Create(*loopVar.output,
"x1");
379 const auto & tracedIn = traceOutputIntraProcedurally(*x1.origin(),
true);
380 EXPECT_EQ(&tracedIn, node->output(0));
381 EXPECT_EQ(tracedIn.region(), thetaNode->subregion());
384 const auto & tracedOut = traceOutputIntraProcedurally(*x1.origin(),
false);
385 EXPECT_EQ(&tracedOut, loopVar.output);
389TEST(TraceTests, GammaCachingTest)
394 const auto controlType = ControlType::Create(2);
395 const auto valueType = TestType::createValueType();
399 auto & predicate = GraphImport::Create(rvsdg, controlType,
"predicate");
400 auto & i1 = GraphImport::Create(rvsdg, valueType,
"i1");
401 auto & i2 = GraphImport::Create(rvsdg, valueType,
"i2");
403 auto gammaNode = GammaNode::create(&predicate, 2);
404 auto i1EntryVar = gammaNode->AddEntryVar(&i1);
405 auto i2EntryVar = gammaNode->AddEntryVar(&i2);
408 gammaNode->AddExitVar({ i1EntryVar.branchArgument[0], i1EntryVar.branchArgument[1] });
410 auto & graphExport = GraphExport::Create(*exitVar.output,
"export");
419 auto traceResult = &tracer.
trace(*graphExport.origin());
420 assert(traceResult == &i1);
423 exitVar.branchResult[0]->divert_to(i2EntryVar.branchArgument[0]);
424 exitVar.branchResult[1]->divert_to(i2EntryVar.branchArgument[1]);
428 traceResult = &tracer.
trace(*graphExport.origin());
429 assert(traceResult == &i1);
433 traceResult = &tracer.
trace(*graphExport.origin());
434 assert(traceResult == &i2);
437TEST(TraceTests, ThetaCachingTest)
442 const auto controlType = ControlType::Create(2);
443 const auto valueType = TestType::createValueType();
447 auto & i1 = GraphImport::Create(rvsdg, valueType,
"i1");
448 auto & i2 = GraphImport::Create(rvsdg, valueType,
"i2");
451 auto loopVar1 = thetaNode->AddLoopVar(&i1);
452 auto loopVar2 = thetaNode->AddLoopVar(&i2);
454 auto & graphExport = GraphExport::Create(*loopVar1.output,
"export");
461 auto traceResult = &tracer.
trace(*graphExport.origin());
462 assert(traceResult == &i1);
465 loopVar1.post->divert_to(loopVar2.pre);
466 loopVar2.post->divert_to(loopVar1.pre);
470 traceResult = &tracer.
trace(*graphExport.origin());
471 assert(traceResult == &i1);
475 traceResult = &tracer.
trace(*graphExport.origin());
476 assert(traceResult == loopVar1.output);
479TEST(TraceTests, RegionPredicationThetaTest)
510 const auto controlType = ControlType::Create(2);
511 const auto int32Type = BitType::Create(32);
515 auto & int1Outer = BitConstantOperation::create(rvsdg.
GetRootRegion(), { 32, 1 });
516 auto & int2Outer = BitConstantOperation::create(rvsdg.
GetRootRegion(), { 32, 2 });
517 auto & int3Outer = BitConstantOperation::create(rvsdg.
GetRootRegion(), { 32, 3 });
519 auto & thetaNode = *ThetaNode::create(&rvsdg.
GetRootRegion());
520 auto loopVar1 = thetaNode.AddLoopVar(&int1Outer);
521 auto loopVar2 = thetaNode.AddLoopVar(&int2Outer);
522 auto loopVar3 = thetaNode.AddLoopVar(&int3Outer);
527 auto & gammaNode = *GammaNode::create(testOp.output(0), 2);
528 auto gammaEntry1 = gammaNode.AddEntryVar(loopVar1.pre);
529 auto gammaEntry2 = gammaNode.AddEntryVar(loopVar2.pre);
530 auto gammaEntry3 = gammaNode.AddEntryVar(loopVar3.pre);
533 auto & gammaCtrl0 = ControlConstantOperation::createFalse(*gammaNode.subregion(0));
534 auto & gammaInt4 = BitConstantOperation::create(*gammaNode.subregion(0), { 32, 4 });
537 auto & gammaCtrl1 = ControlConstantOperation::createTrue(*gammaNode.subregion(1));
538 auto & gammaInt5 = BitConstantOperation::create(*gammaNode.subregion(1), { 32, 5 });
540 auto gammaCtrlExit = gammaNode.AddExitVar({ &gammaCtrl0, &gammaCtrl1 });
542 gammaNode.AddExitVar({ gammaEntry1.branchArgument[0], gammaEntry1.branchArgument[1] });
543 auto gammaExit2 = gammaNode.AddExitVar({ gammaEntry2.branchArgument[0], &gammaInt5 });
544 auto gammaExit3 = gammaNode.AddExitVar({ &gammaInt4, gammaEntry3.branchArgument[1] });
547 thetaNode.predicate()->divert_to(gammaCtrlExit.output);
548 loopVar1.post->divert_to(gammaExit1.output);
549 loopVar2.post->divert_to(gammaExit2.output);
550 loopVar3.post->divert_to(gammaExit3.output);
553 auto & exportX = GraphExport::Create(*loopVar1.output,
"x");
554 auto & exportY = GraphExport::Create(*loopVar2.output,
"y");
555 auto & exportZ = GraphExport::Create(*loopVar3.output,
"z");
567 ASSERT_EQ(&tracer.
trace(*exportX.origin()), &int1Outer);
572 ASSERT_EQ(&tracer.
trace(*exportY.origin()), loopVar2.pre);
576 ASSERT_EQ(&tracer.
trace(*exportZ.origin()), &gammaInt4);
580 ASSERT_EQ(&tracer.
trace(*gammaExit1.output), &int1Outer);
583 ASSERT_EQ(&tracer.
trace(*gammaExit2.output), gammaExit2.output);
584 ASSERT_EQ(&tracer.
trace(*gammaExit3.output), gammaExit3.output);
587 ASSERT_EQ(&tracer.
trace(*loopVar1.pre), &int1Outer);
588 ASSERT_EQ(&tracer.
trace(*loopVar2.pre), loopVar2.pre);
589 ASSERT_EQ(&tracer.
trace(*loopVar3.pre), loopVar3.pre);
592TEST(TraceTests, RegionPredicationThetaToGammaTest)
626 const auto control2Type = ControlType::Create(2);
627 const auto control3Type = ControlType::Create(3);
628 const auto int32Type = BitType::Create(32);
632 auto & testOpCtrlOuter =
634 auto & testOpIntOuter =
637 auto & thetaNode = *ThetaNode::create(&rvsdg.
GetRootRegion());
638 auto loopVarCtrl = thetaNode.AddLoopVar(testOpCtrlOuter.output(0));
639 auto loopVarInt = thetaNode.AddLoopVar(testOpIntOuter.output(0));
641 auto & testOpCtrlInner =
643 auto & gammaInner = *GammaNode::create(testOpCtrlInner.output(0), 3);
646 auto & sub0ctrl0 = ControlConstantOperation::createFalse(*gammaInner.subregion(0));
647 auto & sub0Int1 = BitConstantOperation::create(*gammaInner.subregion(0), { 32, 1 });
650 auto & sub1ctrl0 = ControlConstantOperation::createFalse(*gammaInner.subregion(1));
651 auto & sub1ctrl1 = ControlConstantOperation::createTrue(*gammaInner.subregion(1));
652 auto & sub1Int2 = BitConstantOperation::create(*gammaInner.subregion(1), { 32, 2 });
655 auto & sub2ctrl0 = ControlConstantOperation::createFalse(*gammaInner.subregion(2));
656 auto & sub2ctrl1 = ControlConstantOperation::createTrue(*gammaInner.subregion(2));
657 auto & sub2Int3 = BitConstantOperation::create(*gammaInner.subregion(2), { 32, 3 });
660 auto thetaPredExit = gammaInner.AddExitVar({ &sub0ctrl0, &sub1ctrl0, &sub2ctrl1 });
661 auto innerToOuterGammaCtrlExit = gammaInner.AddExitVar({ &sub0ctrl0, &sub1ctrl1, &sub2ctrl0 });
662 auto innerIntExit = gammaInner.AddExitVar({ &sub0Int1, &sub1Int2, &sub2Int3 });
665 thetaNode.predicate()->divert_to(thetaPredExit.output);
666 loopVarCtrl.post->divert_to(innerToOuterGammaCtrlExit.output);
667 loopVarInt.post->divert_to(innerIntExit.output);
670 auto & outerGamma = *GammaNode::create(loopVarCtrl.output, 2);
671 auto outerIntEntry = outerGamma.AddEntryVar(loopVarInt.output);
682 ASSERT_EQ(&tracer.
trace(*outerIntEntry.branchArgument[0]), &sub0Int1);
683 ASSERT_EQ(&tracer.
trace(*outerIntEntry.branchArgument[1]), &sub1Int2);
686 ASSERT_EQ(&tracer.
trace(*loopVarInt.output), innerIntExit.output);
689TEST(TraceTests, ImpossibleSubregions)
727 const auto control2Type = ControlType::Create(2);
728 const auto int32Type = BitType::Create(32);
732 auto & testOpCtrlOuter =
734 auto & int10 = BitConstantOperation::create(rvsdg.
GetRootRegion(), { 32, 10 });
737 auto ctrlLoopVar = theta.AddLoopVar(testOpCtrlOuter.output(0));
738 auto intLoopVar = theta.AddLoopVar(&int10);
740 auto & testOpCtrlGamma0 =
742 auto & gamma0 = *GammaNode::create(testOpCtrlGamma0.output(0), 2);
743 auto gamma0IntEntryVar = gamma0.AddEntryVar(intLoopVar.pre);
746 auto & testOpCtrlGamma1 =
748 auto & gamma1 = *GammaNode::create(testOpCtrlGamma1.output(0), 2);
751 auto & gamma1leftCtrl0 = ControlConstantOperation::createFalse(*gamma1.subregion(0));
752 auto & gamma1leftCtrl1 = ControlConstantOperation::createTrue(*gamma1.subregion(0));
753 auto & gamma1leftInt20 = BitConstantOperation::create(*gamma1.subregion(0), { 32, 20 });
756 auto & gamma1rightCtrl0 = ControlConstantOperation::createFalse(*gamma1.subregion(1));
757 auto & gamma1rightCtrl1 = ControlConstantOperation::createTrue(*gamma1.subregion(1));
758 auto & gamma1rightInt30 = BitConstantOperation::create(*gamma1.subregion(1), { 32, 30 });
761 auto gamma1Exit0 = gamma1.AddExitVar({ &gamma1leftCtrl0, &gamma1rightCtrl1 });
762 auto gamma1Exit1 = gamma1.AddExitVar({ &gamma1leftCtrl1, &gamma1rightCtrl0 });
763 auto gamma1ExitInt = gamma1.AddExitVar({ &gamma1leftInt20, &gamma1rightInt30 });
766 auto & gamma0rightCtrl0 = ControlConstantOperation::createFalse(*gamma0.subregion(1));
769 auto gamma0Exit0 = gamma0.AddExitVar({ gamma1Exit0.output, &gamma0rightCtrl0 });
770 auto gamma0Exit1 = gamma0.AddExitVar({ gamma1Exit1.output, &gamma0rightCtrl0 });
772 gamma0.AddExitVar({ gamma1ExitInt.output, gamma0IntEntryVar.branchArgument[1] });
775 theta.predicate()->divert_to(gamma0Exit0.output);
776 ctrlLoopVar.post->divert_to(gamma0Exit1.output);
777 intLoopVar.post->divert_to(gamma0ExitInt.output);
780 auto & gamma2 = *GammaNode::create(ctrlLoopVar.output, 2);
781 auto gamma2EntryInt = gamma2.AddEntryVar(intLoopVar.output);
790 ASSERT_EQ(&tracer.
trace(*gamma2EntryInt.branchArgument[0]), intLoopVar.pre);
793 ASSERT_EQ(&tracer.
trace(*gamma2EntryInt.branchArgument[1]), &gamma1leftInt20);