codon/test/cir/analyze/reaching.cpp

180 lines
5.5 KiB
C++

#include "test.h"
#include "codon/cir/analyze/dataflow/cfg.h"
#include "codon/cir/analyze/dataflow/reaching.h"
using namespace codon::ir;
TEST_F(CIRCoreTest, RDAnalysisSimple) {
auto *f = module->Nr<BodiedFunc>("test_f");
auto *b = module->Nr<SeriesFlow>();
f->setBody(b);
auto *v = module->Nr<Var>(module->getIntType());
f->push_back(v);
auto *first = module->getInt(1);
auto *second = module->getInt(2);
auto *start = module->getBool(false);
auto *firstAssign = module->Nr<AssignInstr>(v, first);
auto *secondAssign = module->Nr<AssignInstr>(v, second);
auto *end = module->getBool(false);
b->push_back(start);
b->push_back(firstAssign);
b->push_back(secondAssign);
b->push_back(end);
auto c = analyze::dataflow::buildCFGraph(f);
analyze::dataflow::RDInspector rd(c.get());
rd.analyze();
auto startRd = rd.getReachingDefinitions(v, start);
auto firstRd = rd.getReachingDefinitions(v, firstAssign);
auto secondRd = rd.getReachingDefinitions(v, secondAssign);
auto endRd = rd.getReachingDefinitions(v, end);
auto firstRhsRd = rd.getReachingDefinitions(v, first);
auto secondRhsRd = rd.getReachingDefinitions(v, second);
ASSERT_EQ(0, startRd.size());
ASSERT_EQ(1, firstRd.size());
ASSERT_EQ(1, secondRd.size());
ASSERT_EQ(1, endRd.size());
ASSERT_EQ(0, firstRhsRd.size());
ASSERT_EQ(1, secondRhsRd.size());
ASSERT_EQ(first->getId(), *firstRd.begin());
ASSERT_EQ(second->getId(), *secondRd.begin());
ASSERT_EQ(second->getId(), *endRd.begin());
}
TEST_F(CIRCoreTest, RDAnalysisIfConditional) {
auto *f = module->Nr<BodiedFunc>("test_f");
auto *trueBranch = module->Nr<SeriesFlow>();
auto *falseBranch = module->Nr<SeriesFlow>();
auto *ifFlow = module->Nr<IfFlow>(module->getBool(false), trueBranch, falseBranch);
auto *b = module->Nr<SeriesFlow>();
f->setBody(b);
auto *v = module->Nr<Var>(module->getIntType());
f->push_back(v);
auto *first = module->getInt(1);
auto *second = module->getInt(2);
auto *start = module->getBool(false);
auto *firstAssign = module->Nr<AssignInstr>(v, first);
auto *secondAssign = module->Nr<AssignInstr>(v, second);
auto *end = module->getBool(false);
b->push_back(start);
b->push_back(ifFlow);
trueBranch->push_back(firstAssign);
falseBranch->push_back(secondAssign);
b->push_back(end);
auto c = analyze::dataflow::buildCFGraph(f);
analyze::dataflow::RDInspector rd(c.get());
rd.analyze();
auto startRd = rd.getReachingDefinitions(v, start);
auto endRd = rd.getReachingDefinitions(v, end);
ASSERT_EQ(0, startRd.size());
ASSERT_EQ(2, endRd.size());
ASSERT_TRUE(endRd.find(first->getId()) != endRd.end());
ASSERT_TRUE(endRd.find(second->getId()) != endRd.end());
}
TEST_F(CIRCoreTest, RDAnalysisTryCatch) {
auto *f = module->Nr<BodiedFunc>("test_f");
auto *body = module->Nr<SeriesFlow>();
auto *except = module->Nr<SeriesFlow>();
auto *finally = module->Nr<SeriesFlow>();
auto *tc = module->Nr<TryCatchFlow>(body, finally);
tc->emplace_back(except, nullptr);
auto *b = module->Nr<SeriesFlow>();
f->setBody(b);
auto *v = module->Nr<Var>(module->getIntType());
f->push_back(v);
auto *first = module->getInt(1);
auto *second = module->getInt(2);
auto *third = module->getInt(3);
auto *initial = module->getInt(0);
auto *zeroAssign = module->Nr<AssignInstr>(v, initial);
auto *start = module->getBool(false);
auto *firstAssign = module->Nr<AssignInstr>(v, first);
auto *secondAssign = module->Nr<AssignInstr>(v, second);
auto *middle = module->getBool(false);
auto *thirdAssign = module->Nr<AssignInstr>(v, third);
auto *end = module->getBool(false);
b->push_back(start);
b->push_back(zeroAssign);
b->push_back(tc);
body->push_back(firstAssign);
except->push_back(thirdAssign);
finally->push_back(middle);
finally->push_back(secondAssign);
b->push_back(end);
auto c = analyze::dataflow::buildCFGraph(f);
analyze::dataflow::RDInspector rd(c.get());
rd.analyze();
auto startRd = rd.getReachingDefinitions(v, start);
auto middleRd = rd.getReachingDefinitions(v, middle);
auto endRd = rd.getReachingDefinitions(v, end);
ASSERT_EQ(0, startRd.size());
ASSERT_EQ(1, endRd.size());
ASSERT_TRUE(endRd.find(second->getId()) != endRd.end());
ASSERT_TRUE(middleRd.find(first->getId()) != endRd.end());
ASSERT_TRUE(middleRd.find(third->getId()) != endRd.end());
ASSERT_TRUE(middleRd.find(initial->getId()) != endRd.end());
}
TEST_F(CIRCoreTest, RDAnalysisWhileLoop) {
auto *f = module->Nr<BodiedFunc>("test_f");
auto *loopBody = module->Nr<SeriesFlow>();
auto *whileFlow = module->Nr<WhileFlow>(module->getBool(false), loopBody);
auto *b = module->Nr<SeriesFlow>();
f->setBody(b);
auto *v = module->Nr<Var>(module->getIntType());
f->push_back(v);
auto *first = module->getInt(1);
auto *second = module->getInt(2);
auto *start = module->getBool(false);
auto *firstAssign = module->Nr<AssignInstr>(v, first);
auto *secondAssign = module->Nr<AssignInstr>(v, second);
auto *end = module->getBool(false);
b->push_back(start);
b->push_back(firstAssign);
b->push_back(whileFlow);
loopBody->push_back(secondAssign);
b->push_back(end);
auto c = analyze::dataflow::buildCFGraph(f);
analyze::dataflow::RDInspector rd(c.get());
rd.analyze();
auto startRd = rd.getReachingDefinitions(v, start);
auto endRd = rd.getReachingDefinitions(v, end);
ASSERT_EQ(0, startRd.size());
ASSERT_EQ(2, endRd.size());
ASSERT_TRUE(endRd.find(first->getId()) != endRd.end());
ASSERT_TRUE(endRd.find(second->getId()) != endRd.end());
}