6 #include <gtest/gtest.h>
26 for (
const auto & node : region->
Nodes())
48 auto subregion = theta->subregion();
49 auto idv = theta->AddLoopVar(init);
50 auto lvs = theta->AddLoopVar(step);
51 auto lve = theta->AddLoopVar(end);
57 idv.post->divert_to(arm);
58 theta->set_predicate(matchNode.output(0));
63 TEST(LoopUnrollingTests, test_unrollinfo)
82 EXPECT_NE(ui,
nullptr);
83 EXPECT_TRUE(ui->is_additive());
84 EXPECT_FALSE(ui->is_subtractive());
85 EXPECT_FALSE(ui->is_known());
86 EXPECT_FALSE(ui->niterations());
87 EXPECT_EQ(ui->theta(), theta);
88 EXPECT_EQ(theta->MapPreLoopVar(*ui->idv()).input->origin(), x);
107 auto theta =
create_theta(ult, add, init0, step1, end100);
109 EXPECT_TRUE(ui && *ui->niterations() == 100);
113 EXPECT_TRUE(ui && *ui->niterations() == 101);
117 EXPECT_TRUE(ui && *ui->niterations() == 100);
121 EXPECT_TRUE(ui && *ui->niterations() == 101);
125 EXPECT_TRUE(ui && !ui->niterations());
129 EXPECT_TRUE(ui && *ui->niterations() == 101);
133 EXPECT_TRUE(ui && !ui->niterations());
137 TEST(LoopUnrollingTests, test_known_boundaries)
219 TEST(LoopUnrollingTests, test_unknown_boundaries)
228 auto & graph = rm.Rvsdg();
234 auto lv1 = theta->AddLoopVar(x);
235 auto lv2 = theta->AddLoopVar(y);
237 auto one = &BitConstantOperation::create(*theta->subregion(), { 32, 1 });
240 auto & matchNode = MatchOperation::CreateNode(*cmp, { { 1, 0 } }, 1, 2);
242 lv1.post->divert_to(
add);
244 theta->set_predicate(matchNode.output(0));
246 auto & ex1 = GraphExport::Create(*lv1.output,
"x");
253 auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::GammaNode>(*ex1.origin());
254 EXPECT_NE(node,
nullptr);
255 node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::GammaNode>(*node->input(1)->origin());
256 EXPECT_NE(node,
nullptr);
264 static std::vector<jlm::rvsdg::ThetaNode *>
267 std::vector<jlm::rvsdg::ThetaNode *> thetas;
271 thetas.push_back(theta);
277 TEST(LoopUnrollingTests, test_nested_theta)
280 auto & graph = rm.
Rvsdg();
289 auto lvo_init = otheta->AddLoopVar(init);
290 auto lvo_step = otheta->AddLoopVar(step);
291 auto lvo_end = otheta->AddLoopVar(end);
296 otheta->set_predicate(matchNode.output(0));
297 lvo_init.post->divert_to(
add);
303 auto lvi_init = inner_theta->AddLoopVar(inner_init);
304 auto lvi_step = inner_theta->AddLoopVar(lvo_step.pre);
305 auto lvi_end = inner_theta->AddLoopVar(lvo_end.pre);
309 auto & innerMatchNode =
311 inner_theta->set_predicate(innerMatchNode.output(0));
312 lvi_init.post->divert_to(inner_add);
317 auto inner_nested_init =
319 auto lvi_nested_init = inner_nested_theta->AddLoopVar(inner_nested_init);
320 auto lvi_nested_step = inner_nested_theta->AddLoopVar(lvi_step.pre);
321 auto lvi_nested_end = inner_nested_theta->AddLoopVar(lvi_end.pre);
323 auto inner_nested_add =
325 auto inner_nested_compare =
327 auto & innerNestedMatchNode =
329 inner_nested_theta->set_predicate(innerNestedMatchNode.output(0));
330 lvi_nested_init.post->divert_to(inner_nested_add);
336 auto lvi2_init = inner2_theta->AddLoopVar(inner2_init);
337 auto lvi2_step = inner2_theta->AddLoopVar(lvo_step.pre);
338 auto lvi2_end = inner2_theta->AddLoopVar(lvo_end.pre);
342 auto & inner2MatchNode =
344 inner2_theta->set_predicate(inner2MatchNode.output(0));
345 lvi2_init.post->divert_to(inner2_add);
353 EXPECT_EQ(
nthetas(otheta->subregion()), 2u);
362 EXPECT_LE(otheta->subregion()->numNodes(), 20u);
371 EXPECT_LE(inner_theta->subregion()->numNodes(), 15u);
380 auto thetas =
find_thetas(inner_theta->subregion());
381 EXPECT_EQ(thetas.size(), 1u);
382 EXPECT_GE(thetas[0]->subregion()->numNodes(), 7u);
392 EXPECT_EQ(thetas.size(), 2u);
393 EXPECT_GE(thetas[1]->subregion()->numNodes(), 7u);
402 EXPECT_EQ(thetas.size(), 3u);
403 EXPECT_EQ(
nthetas(thetas[0]->subregion()), 8u);
static jlm::rvsdg::ThetaNode * create_theta(const jlm::rvsdg::BitCompareOperation &cop, const jlm::rvsdg::BitBinaryOperation &aop, jlm::rvsdg::Output *init, jlm::rvsdg::Output *step, jlm::rvsdg::Output *end)
TEST(LoopUnrollingTests, test_unrollinfo)
static size_t nthetas(jlm::rvsdg::Region *region)
static jlm::util::StatisticsCollector statisticsCollector
static std::vector< jlm::rvsdg::ThetaNode * > find_thetas(jlm::rvsdg::Region *region)
Dead Node Elimination Optimization.
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static std::unique_ptr< LoopUnrollInfo > create(rvsdg::ThetaNode *theta)
Optimization that attempts to unroll loops (thetas).
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
static Output & create(Region ®ion, BitValueRepresentation value)
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
Region & GetRootRegion() const noexcept
std::unique_ptr< BitBinaryOperation > create(size_t nbits) const override
std::unique_ptr< BitCompareOperation > create(size_t nbits) const override
static Node & CreateNode(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
virtual std::unique_ptr< Operation > copy() const =0
rvsdg::Region * region() const noexcept
Represent acyclic RVSDG subgraphs.
Graph * graph() const noexcept
NodeRange Nodes() noexcept
NodeOutput * output(size_t index) const noexcept
static SimpleNode & Create(Region ®ion, std::unique_ptr< Operation > operation, const std::vector< rvsdg::Output * > &operands)
static ThetaNode * create(rvsdg::Region *parent)
Global memory state passed between functions.
void unroll(rvsdg::ThetaNode *otheta, size_t factor)