mirror of https://github.com/exaloop/codon.git
180 lines
5.5 KiB
C++
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());
|
|
}
|