diff --git a/cmake.sh b/cmake.sh new file mode 100755 index 0000000..c81cef4 --- /dev/null +++ b/cmake.sh @@ -0,0 +1,2 @@ +cmake -S . -B build +cmake --build build -j12 \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 692c160..17fe54f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(sysyc backend/llir.cc backend/assembly.cc opt/peephole.cc + opt/constprop.cc ) target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(sysyc PRIVATE SysYParser) diff --git a/src/opt/constprop.cc b/src/opt/constprop.cc index 3cd01da..eac8ec8 100644 --- a/src/opt/constprop.cc +++ b/src/opt/constprop.cc @@ -1,3 +1,134 @@ +#include "constprop.h" +#include "../frontend/IR.h" +#include +#include + namespace transform { - -} \ No newline at end of file + +void ConstProp::functionTransform(sysy::Function *func) { + for (auto &bb : func->getBasicBlocks()) { + this->curBB = bb.get(); + this->constantPropagation(bb.get()); + } +} + +void ConstProp::moduleTransform() { + auto *funcs = this->module->getFunctions(); + for (auto it = funcs->begin(); it != funcs->end(); ++it) { + this->functionTransform(it->second); + } +} + +void ConstProp::constantPropagation(sysy::BasicBlock *bb) { + int flag; + std::unordered_map valueMap; + std::unordered_map valuechange; + for (auto &inst : bb->CoInst) { + if (inst.op == "li") { // Assuming 'li' is the instruction to load immediate constants. + valueMap[inst.fields[0]] = inst.fields[1]; // Store constant value with its register. + valuechange[inst.fields[0]] = "0"; + } + else if(inst.op == "add" ){ + for (int i=1;i<=2;i++){ + flag = false; + if (inst.valid && !inst.fields.empty() && valueMap.find(inst.fields[i]) != valueMap.end() && valuechange[inst.fields[i]] == "0") { + inst.fields[i] = valueMap[inst.fields[i]]; + flag = true; + } + else break; + } + if (flag){ + int temp1 = std::stoll(inst.fields[1]); + int temp2 = std::stoll(inst.fields[2]); + valueMap[inst.fields[0]] = std::to_string(temp1 + temp2); + } + else{ + valuechange[inst.fields[0]] = "1"; + } + } + else if(inst.op == "sub" ){ + for (int i=1;i<=2;i++){ + flag = false; + if (inst.valid && !inst.fields.empty() && valueMap.find(inst.fields[i]) != valueMap.end() && valuechange[inst.fields[i]] == "0") { + inst.fields[i] = valueMap[inst.fields[i]]; + flag = true; + } + else break; + } + if (flag){ + int temp1 = std::stoll(inst.fields[1]); + int temp2 = std::stoll(inst.fields[2]); + valueMap[inst.fields[0]] = std::to_string(temp1 - temp2); + } + else{ + valuechange[inst.fields[0]] = "1"; + } + } + else if(inst.op == "mul" ){ + for (int i=1;i<=2;i++){ + flag = false; + if (inst.valid && !inst.fields.empty() && valueMap.find(inst.fields[i]) != valueMap.end() && valuechange[inst.fields[i]] == "0") { + inst.fields[i] = valueMap[inst.fields[i]]; + flag = true; + } + else break; + } + if (flag){ + int temp1 = std::stoll(inst.fields[1]); + int temp2 = std::stoll(inst.fields[2]); + valueMap[inst.fields[0]] = std::to_string(temp1 * temp2); + } + else{ + valuechange[inst.fields[0]] = "1"; + } + } + else if(inst.op == "div" ){ + for (int i=1;i<=2;i++){ + flag = false; + if (inst.valid && !inst.fields.empty() && valueMap.find(inst.fields[i]) != valueMap.end() && valuechange[inst.fields[i]] == "0") { + inst.fields[i] = valueMap[inst.fields[i]]; + flag = true; + } + else break; + } + if (flag){ + int temp1 = std::stoll(inst.fields[1]); + int temp2 = std::stoll(inst.fields[2]); + valueMap[inst.fields[0]] = std::to_string(temp1 / temp2); + } + else{ + valuechange[inst.fields[0]] = "1"; + } + } + else if (inst.op == "sw" ){ + std::string temp; + auto nextInst = std::next(&inst); + if (inst.valid && !inst.fields.empty() && valueMap.find(inst.fields[0]) != valueMap.end() && valuechange[inst.fields[0]] == "0") { + // Replace uses of constants. + //inst.fields[0] = valueMap[inst.fields[0]]; + temp = valueMap[inst.fields[0]]; + } + if (nextInst->op == "lw"){ + valueMap[nextInst->fields[0]] = temp;// Store constant value with its register. + valuechange[nextInst->fields[0]] = "0"; + } + } + else if (inst.op == "lw" ){ + continue; + } + // else if (inst.op == "addi" && inst.op == "ori" && inst.op == "subi" && inst.op == "slli" && inst.op == "sll" ){ + // if (inst.valid && !inst.fields.empty() && valueMap.find(inst.fields[0]) != valueMap.end() && valuechange[inst.fields[0]] == "0") { + // // Replace uses of constants. + // valuechange[inst.fields[0]] = "1"; + // } + // } + else{ + if (inst.valid && !inst.fields.empty() && valueMap.find(inst.fields[0]) != valueMap.end() && valuechange[inst.fields[0]] == "0") { + // Replace uses of constants. + valuechange[inst.fields[0]] = "1"; + } + } + } + +} +} // namespace transform \ No newline at end of file diff --git a/src/opt/constprop.h b/src/opt/constprop.h index e69de29..e2c7fd0 100644 --- a/src/opt/constprop.h +++ b/src/opt/constprop.h @@ -0,0 +1,21 @@ +#include "../frontend/IR.h" + +namespace transform { + +class ConstProp { +private: + sysy::Module *module; + +public: + sysy::BasicBlock *curBB; + + ConstProp(sysy::Module *module): module(module) {}; + + void moduleTransform(); + void functionTransform(sysy::Function *func); + void constantPropagation(sysy::BasicBlock *bb); + //bool isConstantValue(sysy::RVInst *inst); + //void replaceConstantUses(sysy::RVInst *defInst, int constantValue); +}; // class ConstProp + +} // namespace transform \ No newline at end of file diff --git a/src/sysyc.cc b/src/sysyc.cc index 03b2580..d4bdb50 100644 --- a/src/sysyc.cc +++ b/src/sysyc.cc @@ -9,6 +9,7 @@ #include "backend/llir.h" #include "backend/assembly.h" #include "opt/peephole.h" +#include "opt/constprop.h" struct ArgsOptions { std::string srcfile; @@ -29,6 +30,7 @@ class TransformFlags { {"--fpeephole", false}, {"--verbose", false}, {"--fparallel", false}, + {"--fconstprop",false}, {"--opt", false}}; std::string srcfile; void parseFlags(int argc, char** argv) { @@ -57,6 +59,10 @@ class TransformFlags { transform::Hole hole(this->module); hole.moduleTransform(); } + if (this->flags["--fconstprop"]) { + transform::ConstProp constProp(this->module); + constProp.moduleTransform(); + } } void emit() { if (this->flags["--emit-ir"]) { diff --git a/test/17_constprop.sy b/test/17_constprop.sy new file mode 100644 index 0000000..556a4a2 --- /dev/null +++ b/test/17_constprop.sy @@ -0,0 +1,12 @@ +int main (){ + int a = 30; + int b = 9 - a / 5; + int c; + c = b * 4; + if (c > 10) { + c = c - 10; + }else{ + c = 100; + } + return c * (60 / a); +} \ No newline at end of file