Commit 169a7e86 authored by 刘睿博's avatar 刘睿博 🎯

lab4 init

parent 68fc6e03
...@@ -40,6 +40,7 @@ INCLUDE_DIRECTORIES( ...@@ -40,6 +40,7 @@ INCLUDE_DIRECTORIES(
include/common include/common
include/lightir include/lightir
include/codegen include/codegen
include/passes
${LLVM_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}
) )
......
...@@ -357,6 +357,17 @@ class PhiInst : public BaseInst<PhiInst> { ...@@ -357,6 +357,17 @@ class PhiInst : public BaseInst<PhiInst> {
this->add_operand(val); this->add_operand(val);
this->add_operand(pre_bb); this->add_operand(pre_bb);
} }
void remove_phi_operand(Value *pre_bb) {
for (unsigned i = 0; i < this->get_num_operand(); i += 2) {
if (this->get_operand(i + 1) == pre_bb) {
this->remove_operand(i);
this->remove_operand(i);
return;
}
}
}
std::vector<std::pair<Value *, BasicBlock *>> get_phi_pairs() { std::vector<std::pair<Value *, BasicBlock *>> get_phi_pairs() {
std::vector<std::pair<Value *, BasicBlock *>> res; std::vector<std::pair<Value *, BasicBlock *>> res;
for (size_t i = 0; i < get_num_operand(); i += 2) { for (size_t i = 0; i < get_num_operand(); i += 2) {
......
#pragma once
#include "FuncInfo.hpp"
#include "PassManager.hpp"
#include <unordered_set>
/**
* 死代码消除:参见
*https://www.clear.rice.edu/comp512/Lectures/10Dead-Clean-SCCP.pdf
**/
class DeadCode : public Pass {
public:
DeadCode(Module *m) : Pass(m), func_info(std::make_shared<FuncInfo>(m)) {}
void run();
private:
std::shared_ptr<FuncInfo> func_info;
int ins_count{0}; // 用以衡量死代码消除的性能
std::deque<Instruction *> work_list{};
std::unordered_map<Instruction *, bool> marked{};
void mark(Function *func);
void mark(Instruction *ins);
bool sweep(Function *func);
bool clear_basic_blocks(Function *func);
bool is_critical(Instruction *ins);
void sweep_globally();
};
#pragma once
#include "BasicBlock.hpp"
#include "PassManager.hpp"
#include <map>
#include <set>
class Dominators : public Pass {
public:
using BBSet = std::set<BasicBlock *>;
explicit Dominators(Module *m) : Pass(m) {}
~Dominators() = default;
void run() override;
void run_on_func(Function *f);
// functions for getting information
BasicBlock *get_idom(BasicBlock *bb) { return idom_.at(bb); }
const BBSet &get_dominance_frontier(BasicBlock *bb) {
return dom_frontier_.at(bb);
}
const BBSet &get_dom_tree_succ_blocks(BasicBlock *bb) {
return dom_tree_succ_blocks_.at(bb);
}
// print cfg or dominance tree
void dump_cfg(Function *f);
void dump_dominator_tree(Function *f);
// functions for dominance tree
const bool is_dominate(BasicBlock *bb1, BasicBlock *bb2) {
return dom_tree_L_.at(bb1) <= dom_tree_L_.at(bb2) &&
dom_tree_R_.at(bb1) >= dom_tree_L_.at(bb2);
}
const std::vector<BasicBlock *> &get_dom_dfs_order() {
return dom_dfs_order_;
}
const std::vector<BasicBlock *> &get_dom_post_order() {
return dom_post_order_;
}
private:
void dfs(BasicBlock *bb, std::set<BasicBlock *> &visited);
void create_idom(Function *f);
void create_dominance_frontier(Function *f);
void create_dom_tree_succ(Function *f);
void create_dom_dfs_order(Function *f);
BasicBlock * intersect(BasicBlock *b1, BasicBlock *b2);
void create_reverse_post_order(Function *f);
void set_idom(BasicBlock *bb, BasicBlock *idom) { idom_[bb] = idom; }
void set_dominance_frontier(BasicBlock *bb, BBSet &df) {
dom_frontier_[bb].clear();
dom_frontier_[bb].insert(df.begin(), df.end());
}
void add_dom_tree_succ_block(BasicBlock *bb, BasicBlock *dom_tree_succ_bb) {
dom_tree_succ_blocks_[bb].insert(dom_tree_succ_bb);
}
unsigned int get_post_order(BasicBlock *bb) {
return post_order_.at(bb);
}
// for debug
void print_idom(Function *f);
void print_dominance_frontier(Function *f);
// TODO 补充需要的函数
std::list<BasicBlock *> reverse_post_order_{};
std::map<BasicBlock *, int> post_order_id_{}; // the root has highest ID
std::vector<BasicBlock *> post_order_vec_{}; // 逆后序
std::map<BasicBlock *, unsigned int> post_order_{}; // 逆后序
std::map<BasicBlock *, BasicBlock *> idom_{}; // 直接支配
std::map<BasicBlock *, BBSet> dom_frontier_{}; // 支配边界集合
std::map<BasicBlock *, BBSet> dom_tree_succ_blocks_{}; // 支配树中的后继节点
// 支配树上的dfs序L,R
std::map<BasicBlock *, unsigned int> dom_tree_L_;
std::map<BasicBlock *, unsigned int> dom_tree_R_;
std::vector<BasicBlock *> dom_dfs_order_;
std::vector<BasicBlock *> dom_post_order_;
};
#pragma once
#include "PassManager.hpp"
#include "logging.hpp"
#include <deque>
#include <unordered_map>
/**
* 计算哪些函数是纯函数
* WARN:
* 假定所有函数都是纯函数,除非他写入了全局变量、修改了传入的数组、或者直接间接调用了非纯函数
*/
class FuncInfo : public Pass {
public:
FuncInfo(Module *m) : Pass(m) {}
void run();
bool is_pure_function(Function *func) const { return is_pure.at(func); }
private:
std::deque<Function *> worklist;
std::unordered_map<Function *, bool> is_pure;
void trivial_mark(Function *func);
void process(Function *func);
Value *get_first_addr(Value *val);
bool is_side_effect_inst(Instruction *inst);
bool is_local_load(LoadInst *inst);
bool is_local_store(StoreInst *inst);
void log();
};
#include "FuncInfo.hpp"
#include "LoopDetection.hpp"
#include "PassManager.hpp"
#include <memory>
#include <unordered_map>
class LoopInvariantCodeMotion : public Pass {
public:
LoopInvariantCodeMotion(Module *m) : Pass(m) {}
~LoopInvariantCodeMotion() = default;
void run() override;
private:
std::unordered_map<std::shared_ptr<Loop>, bool> is_loop_done_;
std::unique_ptr<LoopDetection> loop_detection_;
std::unique_ptr<FuncInfo> func_info_;
void traverse_loop(std::shared_ptr<Loop> loop);
void run_on_loop(std::shared_ptr<Loop> loop);
void collect_loop_info(std::shared_ptr<Loop> loop,
std::set<Value *> &loop_instructions,
std::set<Value *> &updated_global,
bool &contains_impure_call);
};
\ No newline at end of file
#pragma once
#include "Dominators.hpp"
#include "PassManager.hpp"
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>
class BasicBlock;
class Dominators;
class Function;
class Module;
using BBset = std::set<BasicBlock *>;
using BBvec = std::vector<BasicBlock *>;
class Loop {
private:
// attribute:
// preheader, header, blocks, parent, sub_loops, latches
BasicBlock *preheader_ = nullptr;
BasicBlock *header_;
std::shared_ptr<Loop> parent_ = nullptr;
BBvec blocks_;
std::vector<std::shared_ptr<Loop>> sub_loops_;
std::unordered_set<BasicBlock *> latches_;
public:
Loop(BasicBlock *header) : header_(header) {
blocks_.push_back(header);
}
~Loop() = default;
void add_block(BasicBlock *bb) { blocks_.push_back(bb); }
BasicBlock *get_header() { return header_; }
BasicBlock *get_preheader() { return preheader_; }
std::shared_ptr<Loop> get_parent() { return parent_; }
void set_parent(std::shared_ptr<Loop> parent) { parent_ = parent; }
void set_preheader(BasicBlock *bb) { preheader_ = bb; }
void add_sub_loop(std::shared_ptr<Loop> loop) { sub_loops_.push_back(loop); }
const BBvec& get_blocks() { return blocks_; }
const std::vector<std::shared_ptr<Loop>>& get_sub_loops() { return sub_loops_; }
const std::unordered_set<BasicBlock *>& get_latches() { return latches_; }
void add_latch(BasicBlock *bb) { latches_.insert(bb); }
};
class LoopDetection : public Pass {
private:
Function *func_;
std::unique_ptr<Dominators> dominators_;
std::vector<std::shared_ptr<Loop>> loops_;
// map from header to loop
std::unordered_map<BasicBlock *, std::shared_ptr<Loop>> bb_to_loop_;
void discover_loop_and_sub_loops(BasicBlock *bb, BBset &latches,
std::shared_ptr<Loop> loop);
public:
LoopDetection(Module *m) : Pass(m) {}
~LoopDetection() = default;
void run() override;
void run_on_func(Function *f);
void print() ;
std::vector<std::shared_ptr<Loop>> &get_loops() { return loops_; }
};
#pragma once
#include "Dominators.hpp"
#include "Instruction.hpp"
#include "Value.hpp"
#include <map>
#include <memory>
class Mem2Reg : public Pass {
private:
Function *func_;
std::unique_ptr<Dominators> dominators_;
std::map<Value *, Value *> phi_map;
// TODO 添加需要的变量
// 变量定值栈
std::map<Value *, std::vector<Value *>> var_val_stack;
// phi指令对应的左值(地址)
std::map<PhiInst *, Value *> phi_lval;
public:
Mem2Reg(Module *m) : Pass(m) {}
~Mem2Reg() = default;
void run() override;
void generate_phi();
void rename(BasicBlock *bb);
static inline bool is_global_variable(Value *l_val) {
return dynamic_cast<GlobalVariable *>(l_val) != nullptr;
}
static inline bool is_gep_instr(Value *l_val) {
return dynamic_cast<GetElementPtrInst *>(l_val) != nullptr;
}
static inline bool is_valid_ptr(Value *l_val) {
return not is_global_variable(l_val) and not is_gep_instr(l_val);
}
};
#pragma once
#include "Module.hpp"
#include <memory>
#include <vector>
class Pass {
public:
Pass(Module *m) : m_(m) {}
virtual ~Pass() = default;
virtual void run() = 0;
protected:
Module *m_;
};
class PassManager {
public:
PassManager(Module *m) : m_(m) {}
template <typename PassType, typename... Args>
void add_pass(Args &&...args) {
passes_.emplace_back(new PassType(m_, std::forward<Args>(args)...));
}
void run() {
for (auto &pass : passes_) {
pass->run();
}
}
private:
std::vector<std::unique_ptr<Pass>> passes_;
Module *m_;
};
...@@ -4,4 +4,5 @@ add_subdirectory(logging) ...@@ -4,4 +4,5 @@ add_subdirectory(logging)
add_subdirectory(cminusfc) add_subdirectory(cminusfc)
add_subdirectory(lightir) add_subdirectory(lightir)
add_subdirectory(io) add_subdirectory(io)
add_subdirectory(codegen) add_subdirectory(codegen)
\ No newline at end of file add_subdirectory(passes)
\ No newline at end of file
...@@ -11,6 +11,7 @@ target_link_libraries( ...@@ -11,6 +11,7 @@ target_link_libraries(
codegen codegen
syntax syntax
stdc++fs stdc++fs
passes
) )
install( install(
......
#include "Module.hpp" #include "Module.hpp"
#include "PassManager.hpp"
#include "ast.hpp" #include "ast.hpp"
#include "cminusf_builder.hpp" #include "cminusf_builder.hpp"
#include "CodeGen.hpp" #include "CodeGen.hpp"
#include "PassManager.hpp"
#include "DeadCode.hpp"
#include "Mem2Reg.hpp"
#include "LoopDetection.hpp"
#include "LICM.hpp"
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
...@@ -19,6 +26,9 @@ struct Config { ...@@ -19,6 +26,9 @@ struct Config {
bool emitast{false}; bool emitast{false};
bool emitasm{false}; bool emitasm{false};
bool emitllvm{false}; bool emitllvm{false};
// optization conifg
bool mem2reg{false};
bool licm{false};
Config(int argc, char **argv) : argc(argc), argv(argv) { Config(int argc, char **argv) : argc(argc), argv(argv) {
parse_cmd_line(); parse_cmd_line();
...@@ -51,6 +61,18 @@ int main(int argc, char **argv) { ...@@ -51,6 +61,18 @@ int main(int argc, char **argv) {
ast.run_visitor(builder); ast.run_visitor(builder);
m = builder.getModule(); m = builder.getModule();
PassManager PM(m.get());
// optimization
if(config.mem2reg) {
PM.add_pass<Mem2Reg>();
PM.add_pass<DeadCode>();
}
if(config.licm) {
PM.add_pass<LoopInvariantCodeMotion>();
PM.add_pass<DeadCode>();
}
PM.run();
std::ofstream output_stream(config.output_file); std::ofstream output_stream(config.output_file);
if (config.emitllvm) { if (config.emitllvm) {
auto abs_path = std::filesystem::canonical(config.input_file); auto abs_path = std::filesystem::canonical(config.input_file);
...@@ -62,8 +84,6 @@ int main(int argc, char **argv) { ...@@ -62,8 +84,6 @@ int main(int argc, char **argv) {
codegen.run(); codegen.run();
output_stream << codegen.print(); output_stream << codegen.print();
} }
// TODO: lab4 (IR optimization or codegen)
} }
return 0; return 0;
...@@ -87,7 +107,11 @@ void Config::parse_cmd_line() { ...@@ -87,7 +107,11 @@ void Config::parse_cmd_line() {
emitasm = true; emitasm = true;
} else if (argv[i] == "-emit-llvm"s) { } else if (argv[i] == "-emit-llvm"s) {
emitllvm = true; emitllvm = true;
} else { } else if (argv[i] == "-mem2reg"s) {
mem2reg = true;
} else if (argv[i] == "-licm"s) {
licm = true;
}else {
if (input_file.empty()) { if (input_file.empty()) {
input_file = argv[i]; input_file = argv[i];
} else { } else {
...@@ -106,14 +130,29 @@ void Config::check() { ...@@ -106,14 +130,29 @@ void Config::check() {
if (input_file.extension() != ".cminus") { if (input_file.extension() != ".cminus") {
print_err("file format not recognized"); print_err("file format not recognized");
} }
if (emitllvm and emitasm) {
print_err("emit llvm and emit asm both set");
}
if (not emitllvm and not emitasm and not emitast) {
print_err("not supported: generate executable file directly");
}
if (licm and not mem2reg) {
print_err("licm must be used with mem2reg");
}
if (output_file.empty()) { if (output_file.empty()) {
output_file = input_file.stem(); output_file = input_file.stem();
if (emitllvm) {
output_file.replace_extension(".ll");
} else if (emitasm) {
output_file.replace_extension(".s");
}
} }
} }
void Config::print_help() const { void Config::print_help() const {
std::cout << "Usage: " << exe_name std::cout << "Usage: " << exe_name
<< " [-h|--help] [-o <target-file>] [-emit-ast] [-emit-llvm] [-S] " << " [-h|--help] [-o <target-file>] [-emit-llvm] [-S] [-dump-json]"
"[-mem2reg] [-licm]"
"<input-file>" "<input-file>"
<< std::endl; << std::endl;
exit(0); exit(0);
......
add_library(
passes STATIC
DeadCode.cpp
Dominators.cpp
FuncInfo.cpp
LoopDetection.cpp
LICM.cpp
Mem2Reg.cpp
)
\ No newline at end of file
#include "DeadCode.hpp"
#include "logging.hpp"
#include <vector>
// 处理流程:两趟处理,mark 标记有用变量,sweep 删除无用指令
void DeadCode::run() {
bool changed{};
func_info->run();
do {
changed = false;
for (auto &F : m_->get_functions()) {
auto func = &F;
changed |= clear_basic_blocks(func);
mark(func);
changed |= sweep(func);
}
} while (changed);
LOG_INFO << "dead code pass erased " << ins_count << " instructions";
}
bool DeadCode::clear_basic_blocks(Function *func) {
bool changed = 0;
std::vector<BasicBlock *> to_erase;
for (auto &bb1 : func->get_basic_blocks()) {
auto bb = &bb1;
if(bb->get_pre_basic_blocks().empty() && bb != func->get_entry_block()) {
to_erase.push_back(bb);
changed = 1;
}
}
for (auto &bb : to_erase) {
bb->erase_from_parent();
delete bb;
}
return changed;
}
void DeadCode::mark(Function *func) {
work_list.clear();
marked.clear();
for (auto &bb : func->get_basic_blocks()) {
for (auto &ins : bb.get_instructions()) {
if (is_critical(&ins)) {
marked[&ins] = true;
work_list.push_back(&ins);
}
}
}
while (work_list.empty() == false) {
auto now = work_list.front();
work_list.pop_front();
mark(now);
}
}
void DeadCode::mark(Instruction *ins) {
for (auto op : ins->get_operands()) {
auto def = dynamic_cast<Instruction *>(op);
if (def == nullptr)
continue;
if (marked[def])
continue;
if (def->get_function() != ins->get_function())
continue;
marked[def] = true;
work_list.push_back(def);
}
}
bool DeadCode::sweep(Function *func) {
std::unordered_set<Instruction *> wait_del{};
for (auto &bb : func->get_basic_blocks()) {
for (auto it = bb.get_instructions().begin();
it != bb.get_instructions().end();) {
if (marked[&*it]) {
++it;
continue;
} else {
auto tmp = &*it;
wait_del.insert(tmp);
it++;
}
}
}
for (auto inst : wait_del)
inst->remove_all_operands();
for (auto inst : wait_del)
inst->get_parent()->get_instructions().erase(inst);
ins_count += wait_del.size();
return not wait_del.empty(); // changed
}
bool DeadCode::is_critical(Instruction *ins) {
// 对纯函数的无用调用也可以在删除之列
if (ins->is_call()) {
auto call_inst = dynamic_cast<CallInst *>(ins);
auto callee = dynamic_cast<Function *>(call_inst->get_operand(0));
if (func_info->is_pure_function(callee))
return false;
return true;
}
if (ins->is_br() || ins->is_ret())
return true;
if (ins->is_store())
return true;
return false;
}
void DeadCode::sweep_globally() {
std::vector<Function *> unused_funcs;
std::vector<GlobalVariable *> unused_globals;
for (auto &f_r : m_->get_functions()) {
if (f_r.get_use_list().size() == 0 and f_r.get_name() != "main")
unused_funcs.push_back(&f_r);
}
for (auto &glob_var_r : m_->get_global_variable()) {
if (glob_var_r.get_use_list().size() == 0)
unused_globals.push_back(&glob_var_r);
}
// changed |= unused_funcs.size() or unused_globals.size();
for (auto func : unused_funcs)
m_->get_functions().erase(func);
for (auto glob : unused_globals)
m_->get_global_variable().erase(glob);
}
This diff is collapsed.
#include "FuncInfo.hpp"
#include "Function.hpp"
void FuncInfo::run() {
for (auto &f : m_->get_functions()) {
auto func = &f;
trivial_mark(func);
if (not is_pure[func])
worklist.push_back(func);
}
while (worklist.empty() == false) {
auto now = worklist.front();
worklist.pop_front();
process(now);
}
log();
}
void FuncInfo::log() {
for (auto it : is_pure) {
LOG_INFO << it.first->get_name() << " is pure? " << it.second;
}
}
// 有 store 操作的函数非纯函数来处理
void FuncInfo::trivial_mark(Function *func) {
if (func->is_declaration() or func->get_name() == "main") {
is_pure[func] = false;
return;
}
// 只要传入数组,都作为非纯函数处理
for (auto it = func->get_function_type()->param_begin();
it != func->get_function_type()->param_end(); ++it) {
auto arg_type = *it;
if (arg_type->is_integer_type() == false and
arg_type->is_float_type() == false) {
is_pure[func] = false;
return;
}
}
for (auto &bb : func->get_basic_blocks())
for (auto &inst : bb.get_instructions()) {
if (is_side_effect_inst(&inst)) {
is_pure[func] = false;
return;
}
}
is_pure[func] = true;
}
void FuncInfo::process(Function *func) {
for (auto &use : func->get_use_list()) {
LOG_INFO << use.val_->print() << " uses func: " << func->get_name();
if (auto inst = dynamic_cast<Instruction *>(use.val_)) {
auto func = (inst->get_parent()->get_parent());
if (is_pure[func]) {
is_pure[func] = false;
worklist.push_back(func);
}
} else
LOG_WARNING << "Value besides instruction uses a function";
}
}
// 对局部变量进行 store 没有副作用
bool FuncInfo::is_side_effect_inst(Instruction *inst) {
if (inst->is_store()) {
if (is_local_store(dynamic_cast<StoreInst *>(inst)))
return false;
return true;
}
if (inst->is_load()) {
if (is_local_load(dynamic_cast<LoadInst *>(inst)))
return false;
return true;
}
// call 指令的副作用会在后续 bfs 中计算
return false;
}
bool FuncInfo::is_local_load(LoadInst *inst) {
auto addr =
dynamic_cast<Instruction *>(get_first_addr(inst->get_operand(0)));
if (addr and addr->is_alloca())
return true;
return false;
}
bool FuncInfo::is_local_store(StoreInst *inst) {
auto addr = dynamic_cast<Instruction *>(get_first_addr(inst->get_lval()));
if (addr and addr->is_alloca())
return true;
return false;
}
Value *FuncInfo::get_first_addr(Value *val) {
if (auto inst = dynamic_cast<Instruction *>(val)) {
if (inst->is_alloca())
return inst;
if (inst->is_gep())
return get_first_addr(inst->get_operand(0));
if (inst->is_load())
return val;
LOG_WARNING << "FuncInfo: try to determine addr in operands";
for (auto op : inst->get_operands()) {
if (op->get_type()->is_pointer_type())
return get_first_addr(op);
}
}
return val;
}
#include "BasicBlock.hpp"
#include "Constant.hpp"
#include "Function.hpp"
#include "GlobalVariable.hpp"
#include "Instruction.hpp"
#include "LICM.hpp"
#include "PassManager.hpp"
#include <cstddef>
#include <memory>
#include <vector>
/**
* @brief 循环不变式外提Pass的主入口函数
*
*/
void LoopInvariantCodeMotion::run() {
loop_detection_ = std::make_unique<LoopDetection>(m_);
loop_detection_->run();
func_info_ = std::make_unique<FuncInfo>(m_);
func_info_->run();
for (auto &loop : loop_detection_->get_loops()) {
is_loop_done_[loop] = false;
}
for (auto &loop : loop_detection_->get_loops()) {
traverse_loop(loop);
}
}
/**
* @brief 遍历循环及其子循环
* @param loop 当前要处理的循环
*
*/
void LoopInvariantCodeMotion::traverse_loop(std::shared_ptr<Loop> loop) {
if (is_loop_done_[loop]) {
return;
}
is_loop_done_[loop] = true;
for (auto &sub_loop : loop->get_sub_loops()) {
traverse_loop(sub_loop);
}
run_on_loop(loop);
}
// 1. 遍历当前循环及其子循环的所有指令
// 2. 收集所有指令到loop_instructions中
// 3. 检查store指令是否修改了全局变量,如果是则添加到updated_global中
// 4. 检查是否包含非纯函数调用,如果有则设置contains_impure_call为true
void LoopInvariantCodeMotion::collect_loop_info(
std::shared_ptr<Loop> loop,
std::set<Value *> &loop_instructions,
std::set<Value *> &updated_global,
bool &contains_impure_call) {
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
}
/**
* @brief 对单个循环执行不变式外提优化
* @param loop 要优化的循环
*
*/
void LoopInvariantCodeMotion::run_on_loop(std::shared_ptr<Loop> loop) {
std::set<Value *> loop_instructions;
std::set<Value *> updated_global;
bool contains_impure_call = false;
collect_loop_info(loop, loop_instructions, updated_global, contains_impure_call);
std::vector<Value *> loop_invariant;
// TODO: 识别循环不变式指令
//
// - 如果指令已被标记为不变式则跳过
// - 跳过 store、ret、br、phi 等指令与非纯函数调用
// - 特殊处理全局变量的 load 指令
// - 检查指令的所有操作数是否都是循环不变的
// - 如果有新的不变式被添加则注意更新 changed 标志,继续迭代
bool changed;
do {
changed = false;
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} while (changed);
if (loop->get_preheader() == nullptr) {
loop->set_preheader(
BasicBlock::create(m_, "", loop->get_header()->get_parent()));
}
if (loop_invariant.empty())
return;
// insert preheader
auto preheader = loop->get_preheader();
// TODO: 更新 phi 指令
for (auto &phi_inst_ : loop->get_header()->get_instructions()) {
if (phi_inst_.get_instr_type() != Instruction::phi)
break;
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
}
// TODO: 用跳转指令重构控制流图
// 将所有非 latch 的 header 前驱块的跳转指向 preheader
// 并将 preheader 的跳转指向 header
// 注意这里需要更新前驱块的后继和后继的前驱
std::vector<BasicBlock *> pred_to_remove;
for (auto &pred : loop->get_header()->get_pre_basic_blocks()) {
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
}
for (auto &pred : pred_to_remove) {
loop->get_header()->remove_pre_basic_block(pred);
}
// TODO: 外提循环不变指令
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
// insert preheader br to header
BranchInst::create_br(loop->get_header(), preheader);
// insert preheader to parent loop
if (loop->get_parent() != nullptr) {
loop->get_parent()->add_block(preheader);
}
}
#include "LoopDetection.hpp"
#include "Dominators.hpp"
#include <memory>
/**
* @brief 循环检测Pass的主入口函数
*
* 该函数执行以下步骤:
* 1. 创建支配树分析实例
* 2. 遍历模块中的所有函数
* 3. 对每个非声明函数执行循环检测
* 4. 最后打印检测结果
*/
void LoopDetection::run() {
dominators_ = std::make_unique<Dominators>(m_);
for (auto &f1 : m_->get_functions()) {
auto f = &f1;
if (f->is_declaration())
continue;
func_ = f;
run_on_func(f);
}
print();
}
/**
* @brief 发现循环及其子循环
* @param bb 循环的header块
* @param latches 循环的回边终点(latch)集合
* @param loop 当前正在处理的循环对象
*/
void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, BBset &latches,
std::shared_ptr<Loop> loop) {
// TODO List:
// 1. 初始化工作表,将所有latch块加入
// 2. 实现主循环逻辑
// 3. 处理未分配给任何循环的节点
// 4. 处理已属于其他循环的节点
// 5. 建立正确的循环嵌套关系
BBvec work_list = {latches.begin(), latches.end()}; // 初始化工作表
while (!work_list.empty()) { // 当工作表非空时继续处理
auto bb = work_list.back();
work_list.pop_back();
// TODO-1: 处理未分配给任何循环的节点
if (bb_to_loop_.find(bb) == bb_to_loop_.end()) {
/* 在此添加代码:
* 1. 使用loop->add_block将bb加入当前循环
* 2. 更新bb_to_loop_映射
* 3. 将bb的所有前驱加入工作表
*/
}
// TODO-2: 处理已属于其他循环的节点
else if (bb_to_loop_[bb] != loop) {
/* 在此添加代码:
* 1. 获取bb当前所属的循环sub_loop
* 2. 找到sub_loop的最顶层父循环
* 3. 检查是否需要继续处理
* 4. 建立循环嵌套关系:
* - 设置父循环
* - 添加子循环
* 5. 将子循环header的前驱加入工作表
*/
}
}
}
/**
* @brief 对单个函数执行循环检测
* @param f 要分析的函数
*
* 该函数通过以下步骤检测循环:
* 1. 运行支配树分析
* 2. 按支配树后序遍历所有基本块
* 3. 对每个块,检查其前驱是否存在回边
* 4. 如果存在回边,创建新的循环并:
* - 设置循环header
* - 添加latch节点
* - 发现循环体和子循环
*/
void LoopDetection::run_on_func(Function *f) {
dominators_->run_on_func(f);
for (auto &bb1 : dominators_->get_dom_post_order()) {
auto bb = bb1;
BBset latches;
for (auto &pred : bb->get_pre_basic_blocks()) {
if (dominators_->is_dominate(bb, pred)) {
// pred is a back edge
// pred -> bb , pred is the latch node
latches.insert(pred);
}
}
if (latches.empty()) {
continue;
}
// create loop
auto loop = std::make_shared<Loop>(bb);
bb_to_loop_[bb] = loop;
// add latch nodes
for (auto &latch : latches) {
loop->add_latch(latch);
}
loops_.push_back(loop);
discover_loop_and_sub_loops(bb, latches, loop);
}
}
/**
* @brief 打印循环检测的结果
*
* 为每个检测到的循环打印:
* 1. 循环的header块
* 2. 循环包含的所有基本块
* 3. 循环的所有子循环
*/
void LoopDetection::print() {
m_->set_print_name();
std::cerr << "Loop Detection Result:" << std::endl;
for (auto &loop : loops_) {
std::cerr << "Loop header: " << loop->get_header()->get_name()
<< std::endl;
std::cerr << "Loop blocks: ";
for (auto &bb : loop->get_blocks()) {
std::cerr << bb->get_name() << " ";
}
std::cerr << std::endl;
std::cerr << "Sub loops: ";
for (auto &sub_loop : loop->get_sub_loops()) {
std::cerr << sub_loop->get_header()->get_name() << " ";
}
std::cerr << std::endl;
}
}
\ No newline at end of file
#include "Mem2Reg.hpp"
#include "IRBuilder.hpp"
#include "Value.hpp"
#include <memory>
/**
* @brief Mem2Reg Pass的主入口函数
*
* 该函数执行内存到寄存器的提升过程,将栈上的局部变量提升到SSA格式。
* 主要步骤:
* 1. 创建并运行支配树分析
* 2. 对每个非声明函数:
* - 清空相关数据结构
* - 插入必要的phi指令
* - 执行变量重命名
*
* 注意:函数执行后,冗余的局部变量分配指令将由后续的死代码删除Pass处理
*/
void Mem2Reg::run() {
// 创建支配树分析 Pass 的实例
dominators_ = std::make_unique<Dominators>(m_);
// 建立支配树
dominators_->run();
// 以函数为单元遍历实现 Mem2Reg 算法
for (auto &f : m_->get_functions()) {
if (f.is_declaration())
continue;
func_ = &f;
var_val_stack.clear();
phi_lval.clear();
if (func_->get_basic_blocks().size() >= 1) {
// 对应伪代码中 phi 指令插入的阶段
generate_phi();
// 对应伪代码中重命名阶段
rename(func_->get_entry_block());
}
// 后续 DeadCode 将移除冗余的局部变量的分配空间
}
}
/**
* @brief 在必要的位置插入phi指令
*
* 该函数实现了经典的phi节点插入算法:
* 1. 收集全局活跃变量:
* - 扫描所有store指令
* - 识别在多个基本块中被赋值的变量
*
* 2. 插入phi指令:
* - 对每个全局活跃变量
* - 在其定值点的支配边界处插入phi指令
* - 使用工作表法处理迭代式的phi插入
*
* phi指令的插入遵循最小化原则,只在必要的位置插入phi节点
*/
void Mem2Reg::generate_phi() {
// global_live_var_name 是全局名字集合,以 alloca 出的局部变量来统计。
// 步骤一:找到活跃在多个 block 的全局名字集合,以及它们所属的 bb 块
std::set<Value *> global_live_var_name;
std::map<Value *, std::set<BasicBlock *>> live_var_2blocks;
for (auto &bb : func_->get_basic_blocks()) {
std::set<Value *> var_is_killed;
for (auto &instr : bb.get_instructions()) {
if (instr.is_store()) {
// store i32 a, i32 *b
// a is r_val, b is l_val
auto l_val = static_cast<StoreInst *>(&instr)->get_lval();
if (is_valid_ptr(l_val)) {
global_live_var_name.insert(l_val);
live_var_2blocks[l_val].insert(&bb);
}
}
}
}
// 步骤二:从支配树获取支配边界信息,并在对应位置插入 phi 指令
std::map<std::pair<BasicBlock *, Value *>, bool>
bb_has_var_phi; // bb has phi for var
for (auto var : global_live_var_name) {
std::vector<BasicBlock *> work_list;
work_list.assign(live_var_2blocks[var].begin(),
live_var_2blocks[var].end());
for (unsigned i = 0; i < work_list.size(); i++) {
auto bb = work_list[i];
for (auto bb_dominance_frontier_bb :
dominators_->get_dominance_frontier(bb)) {
if (bb_has_var_phi.find({bb_dominance_frontier_bb, var}) ==
bb_has_var_phi.end()) {
// generate phi for bb_dominance_frontier_bb & add
// bb_dominance_frontier_bb to work list
auto phi = PhiInst::create_phi(
var->get_type()->get_pointer_element_type(),
bb_dominance_frontier_bb);
phi_lval.emplace(phi, var);
bb_dominance_frontier_bb->add_instr_begin(phi);
work_list.push_back(bb_dominance_frontier_bb);
bb_has_var_phi[{bb_dominance_frontier_bb, var}] = true;
}
}
}
}
}
void Mem2Reg::rename(BasicBlock *bb) {
std::vector<Instruction *> wait_delete;
// TODO
// 步骤一:将 phi 指令作为 lval 的最新定值,lval 即是为局部变量 alloca 出的地址空间
// 步骤二:用 lval 最新的定值替代对应的load指令
// 步骤三:将 store 指令的 rval,也即被存入内存的值,作为 lval 的最新定值
// 步骤四:为 lval 对应的 phi 指令参数补充完整
// 步骤五:对 bb 在支配树上的所有后继节点,递归执行 re_name 操作
// 步骤六:pop出 lval 的最新定值
// 步骤七:清除冗余的指令
for (auto instr : wait_delete) {
bb->erase_instr(instr);
}
}
#!/bin/bash
rm -rf output log.txt
#!/bin/bash
project_dir=$(realpath ../../)
io_dir=$(realpath "$project_dir"/src/io)
output_dir=output
suffix=cminus
LOG=log.txt
usage() {
cat <<JIANMU
Usage: $0 [path-to-testcases] [type]
path-to-testcases: './testcases/functional-cases' or '../testcases_general' or 'self made cases'
type: 'debug' or 'test', debug will output .ll file
JIANMU
exit 0
}
check_return_value() {
rv=$1
expected_rv=$2
fail_msg=$3
detail=$4
if [ "$rv" -eq "$expected_rv" ]; then
return 0
else
printf "\033[1;31m%s: \033[0m%s\n" "$fail_msg" "$detail"
return 1
fi
}
# check arguments
[ $# -lt 2 ] && usage
if [ "$2" == "debug" ]; then
debug_mode=true
elif [ "$2" == "test" ]; then
debug_mode=false
else
usage
fi
test_dir=$1
testcases=$(ls "$test_dir"/*."$suffix" | sort -V)
check_return_value $? 0 "PATH" "unable to access to '$test_dir'" || exit 1
# hide stderr in the script
# exec 2>/dev/null
mkdir -p $output_dir
truncate -s 0 $LOG
if [ $debug_mode = false ]; then
exec 3>/dev/null 4>&1 5>&2 1>&3 2>&3
else
exec 3>&1
fi
if [ $debug_mode = false ]; then
exec 1>&4 2>&5
fi
echo "[info] Start testing, using testcase dir: $test_dir"
# asm
for case in $testcases; do
echo "==========$case==========" >>$LOG
case_base_name=$(basename -s .$suffix "$case")
std_out_file=$test_dir/$case_base_name.out
in_file=$test_dir/$case_base_name.in
asm_file=$output_dir/$case_base_name.s
exe_file=$output_dir/$case_base_name
out_file=$output_dir/$case_base_name.out
ll_file=$output_dir/$case_base_name.ll
echo -n "$case_base_name..."
# if debug mode on, generate .ll also
if [ $debug_mode = true ]; then
bash -c "cminusfc -mem2reg -emit-llvm $case -o $ll_file" >>$LOG 2>&1
fi
# cminusfc compile to .s
bash -c "cminusfc -S -mem2reg $case -o $asm_file" >>$LOG 2>&1
check_return_value $? 0 "CE" "cminusfc compiler error" || continue
# gcc compile asm to executable
if [ $debug_mode = true ]; then
loongarch64-unknown-linux-gnu-gcc -g -static \
"$asm_file" "$io_dir"/io.c -o "$exe_file" \
>>$LOG
else
loongarch64-unknown-linux-gnu-gcc -static \
"$asm_file" "$io_dir"/io.c -o "$exe_file" \
>>$LOG
fi
check_return_value $? 0 "CE" "gcc compiler error" || continue
# qemu run
if [ -e "$in_file" ]; then
exec_cmd="qemu-loongarch64 $exe_file >$out_file <$in_file"
else
exec_cmd="qemu-loongarch64 $exe_file >$out_file"
fi
bash -c "$exec_cmd"
ret=$?
# remove trailing null byte in the end line
sed -i "\$s/\x00*$//" "$out_file"
# append return value
echo $ret >>"$out_file"
# compare output
diff --strip-trailing-cr "$std_out_file" "$out_file" -y >>$LOG
check_return_value $? 0 "WA" "output differ, check $std_out_file and $out_file" || continue
# ok
printf "\033[1;32mOK\033[0m\n"
done
#!/bin/bash
project_dir=$(realpath ../../)
io_dir=$(realpath "$project_dir"/src/io)
output_dir=output
suffix=cminus
flag = ""
LOG=log.txt
check_return_value() {
rv=$1
expected_rv=$2
fail_msg=$3
detail=$4
if [ "$rv" -eq "$expected_rv" ]; then
return 0
else
printf "\033[1;31m%s: \033[0m%s\n" "$fail_msg" "$detail"
return 1
fi
}
usage() {
cat <<JIANMU
Usage: $0 [licm | mem2reg]
JIANMU
exit 0
}
[ $# -lt 1 ] && usage
if [ "$1" == "licm" ]; then
licm=true
nfalg = "-mem2reg"
flag = "-mem2reg -licm"
elif [ "$1" == "mem2reg" ]; then
licm=false
nflag = ""
flag = "-mem2reg"
else
usage
fi
if [ $licm = true ]; then
test_dir=./testcases/loop
else
test_dir=./testcases/mem2reg
fi
testcases=$(ls "$test_dir"/*."$suffix" | sort -V)
check_return_value $? 0 "PATH" "unable to access to '$test_dir'" || exit 1
# hide stderr in the script
# exec 2>/dev/null
mkdir -p $output_dir
truncate -s 0 $LOG
echo "[info] Start testing, using testcase dir: $test_dir"
# asm
for case in $testcases; do
echo "==========$case==========" >>$LOG
case_base_name=$(basename -s .$suffix "$case")
in_file=$test_dir/$case_base_name.in
asm_mem2reg_on=$output_dir/${case_base_name}-$1-on.s
asm_mem2reg_off=$output_dir/${case_base_name}-$1-off.s
exe_mem2reg_on=$output_dir/${case_base_name}-$1-on
exe_mem2reg_off=$output_dir/${case_base_name}-$1-off
echo "==========$case=========="
#### mem2reg off
# cminusfc compile to .s
bash -c "cminusfc -S $nflag $case -o $asm_mem2reg_off" >>$LOG 2>&1
check_return_value $? 0 "CE" "cminusfc compiler error" || continue
# gcc compile asm to executable
loongarch64-unknown-linux-gnu-gcc -static \
"$asm_mem2reg_off" "$io_dir"/io.c -o "$exe_mem2reg_off" \
>>$LOG
check_return_value $? 0 "CE" "gcc compiler error" || continue
#### mem2reg on
# cminusfc compile to .s
bash -c "cminusfc -S $flag $case -o $asm_mem2reg_on" >>$LOG 2>&1
check_return_value $? 0 "CE" "cminusfc compiler error" || continue
# gcc compile asm to executable
loongarch64-unknown-linux-gnu-gcc -static \
"$asm_mem2reg_on" "$io_dir"/io.c -o "$exe_mem2reg_on" \
>>$LOG
check_return_value $? 0 "CE" "gcc compiler error" || continue
echo "==========$1 off"
if [ -e "$in_file" ]; then
exec_cmd="qemu-loongarch64 $exe_mem2reg_off >/dev/null <$in_file"
else
exec_cmd="qemu-loongarch64 $exe_mem2reg_off >/dev/null"
fi
time bash -c "$exec_cmd"
echo "==========$1 on"
if [ -e "$in_file" ]; then
exec_cmd="qemu-loongarch64 $exe_mem2reg_on >/dev/null <$in_file"
else
exec_cmd="qemu-loongarch64 $exe_mem2reg_on >/dev/null"
fi
time bash -c "$exec_cmd"
done
int main(void) {
output(input());
return 0;
}
int main(void) {
output(111);
return 111;
}
int main(void) {
float a;
float b;
float c;
a = 1.1;
b = 1.5;
c = 1.2;
outputFloat(a * b + c);
return 0;
}
/*
用 gcc 编译此文件生成汇编代码时,命令为 gcc -include io.h -S 10-float.c
其中 io.h 位于 src/io/io.h,
也可以在本文件开头加上 void outputFloat(float x);
*/
/* float function call */
float mod(float x, float y) {
int div;
div = x / y;
return x - div * y;
}
int main(void) {
float a;
float b;
a = 11.2;
b = 2.2;
outputFloat(mod(a, b));
return 0;
}
int seed;
int randomLCG(void) {
seed = seed * 1103515245 + 12345;
return seed;
}
int randBin(void) {
if (randomLCG() > 0)
return 1;
else
return 0;
}
/* random walk */
int returnToZeroSteps(void) {
int x;
int steps;
x = 0;
steps = 0;
while (steps < 20) {
if (randBin())
x = x + 1;
else
x = x - 1;
steps = steps + 1;
if (x == 0)
return steps;
}
return 20;
}
int main(void) {
int i;
i = 0;
seed = 3407;
while (i < 20) {
output(returnToZeroSteps());
i = i + 1;
}
return 0;
}
4
2
2
4
8
2
2
2
2
2
6
2
10
8
4
2
20
2
2
8
0
/* 01 背包问题 */
int n;
int m;
int w[5];
int v[5];
int dp[66]; /* dp[n * 11 + size] 表示前 n 个物品放入容量为 size 的背包中的最大价值,初始化为 -1 */
int max(int a, int b) {
if (a > b)
return a;
else
return b;
}
/* 状态转移方程:
dp[n][size] = max(dp[n - 1][size], dp[n - 1][size - w[n]] + v[n])
边界条件:
dp[n][size <= 0] = 0
dp[0][size] = 0 */
int knapsack(int n, int size) {
int result;
if (size <= 0)
return 0;
if (n == 0)
return 0;
if (dp[n * 11 + size] >= 0)
return dp[n * 11 + size];
if (size < w[n - 1])
result = knapsack(n - 1, size);
else
result = max(knapsack(n - 1, size), knapsack(n - 1, size - w[n - 1]) + v[n - 1]);
dp[n * 11 + size] = result;
return result;
}
int main(void) {
int i;
i = 0;
n = 5;
m = 10;
w[0] = 2;
w[1] = 2;
w[2] = 6;
w[3] = 5;
w[4] = 4;
v[0] = 6;
v[1] = 3;
v[2] = 5;
v[3] = 4;
v[4] = 6;
while (i < 66) {
dp[i] = 0 - 1;
i = i + 1;
}
output(knapsack(n, m));
return 0;
}
int main(void) {
int a;
int b;
int c;
a = 23;
b = 25;
c = 4;
return a + b * c;
}
int main(void) {
output(11);
output(22222);
return 0;
}
int main(void) {
int a;
int b;
int c;
a = 11;
b = 22;
c = 33;
/* max value */
if (a > b) {
if (a > c)
output(a);
else
output(c);
} else {
if (c < b)
output(b);
else
output(c);
}
return 0;
}
int main(void) {
int n;
int i;
n = 10;
i = 0;
while (i < n) {
output(i);
i = i + 1;
}
return 0;
}
int main(void) {
int a[10];
int i;
i = 0;
a[0] = 11;
a[4] = 22;
a[9] = 33;
output(a[0]);
output(a[4]);
output(a[9]);
return 0;
}
int min(int a, int b) {
if (a <= b)
return a;
else
return b;
}
int main(void) {
int a;
int b;
int c;
a = 11;
b = 22;
c = 33;
output(min(a, b));
output(min(b, c));
output(min(c, a));
return 0;
}
int store(int arr[], int index, int value) {
arr[index] = value;
return value;
}
int main(void) {
int a[10];
int i;
int sum;
i = 0;
while (i < 10) {
store(a, i, i * 2);
i = i + 1;
}
sum = 0;
i = 0;
while (i < 10) {
sum = sum + a[i];
i = i + 1;
}
output(sum);
return 0;
}
int fibonacci(int n) {
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
int main(void) {
int n;
int i;
n = 10;
i = 0;
while (i < n) {
output(fibonacci(i));
i = i + 1;
}
return 0;
}
; ModuleID = 'cminus'
source_filename = "/home/haiqwa/2020fall-compiler_cminus/tests/lab5/./testcases/LoopInvHoist/testcase-5.cminus"
declare i32 @input()
declare void @output(i32)
declare void @outputFloat(float)
declare void @neg_idx_except()
define void @main() {
label_entry:
br label %label3
label3: ; preds = %label_entry, %label58
%op61 = phi i32 [ %op64, %label58 ], [ undef, %label_entry ]
%op62 = phi i32 [ 1, %label_entry ], [ %op60, %label58 ]
%op63 = phi i32 [ %op65, %label58 ], [ undef, %label_entry ]
%op5 = icmp slt i32 %op62, 10000
%op6 = zext i1 %op5 to i32
%op7 = icmp ne i32 %op6, 0
br i1 %op7, label %label8, label %label9
label8: ; preds = %label3
%op19 = mul i32 %op62, %op62
%op21 = mul i32 %op19, %op62
%op23 = mul i32 %op21, %op62
%op25 = mul i32 %op23, %op62
%op27 = mul i32 %op25, %op62
%op29 = mul i32 %op27, %op62
%op31 = mul i32 %op29, %op62
%op33 = mul i32 %op31, %op62
%op35 = mul i32 %op33, %op62
%op37 = sdiv i32 %op35, %op62
%op39 = sdiv i32 %op37, %op62
%op41 = sdiv i32 %op39, %op62
%op43 = sdiv i32 %op41, %op62
%op45 = sdiv i32 %op43, %op62
%op47 = sdiv i32 %op45, %op62
%op49 = sdiv i32 %op47, %op62
%op51 = sdiv i32 %op49, %op62
%op53 = sdiv i32 %op51, %op62
%op55 = sdiv i32 %op53, %op62
br label %label11
label9: ; preds = %label3
call void @output(i32 %op61)
ret void
label11: ; preds = %label8, %label16
%op64 = phi i32 [ %op61, %label8 ], [ %op55, %label16 ]
%op65 = phi i32 [ 0, %label8 ], [ %op57, %label16 ]
%op13 = icmp slt i32 %op65, 10000
%op14 = zext i1 %op13 to i32
%op15 = icmp ne i32 %op14, 0
br i1 %op15, label %label16, label %label58
label16: ; preds = %label11
%op57 = add i32 %op65, 1
br label %label11
label58: ; preds = %label11
%op60 = add i32 %op62, 1
br label %label3
}
; ModuleID = 'cminus'
source_filename = "/home/haiqwa/2020fall-compiler_cminus/tests/lab5/./testcases/LoopInvHoist/testcase-6.cminus"
declare i32 @input()
declare void @output(i32)
declare void @outputFloat(float)
declare void @neg_idx_except()
define void @main() {
label_entry:
%op20 = mul i32 2, 2
%op22 = mul i32 %op20, 2
%op24 = mul i32 %op22, 2
%op26 = mul i32 %op24, 2
%op28 = mul i32 %op26, 2
%op30 = mul i32 %op28, 2
%op32 = mul i32 %op30, 2
%op34 = mul i32 %op32, 2
%op36 = mul i32 %op34, 2
%op38 = sdiv i32 %op36, 2
%op40 = sdiv i32 %op38, 2
%op42 = sdiv i32 %op40, 2
%op44 = sdiv i32 %op42, 2
%op46 = sdiv i32 %op44, 2
%op48 = sdiv i32 %op46, 2
%op50 = sdiv i32 %op48, 2
%op52 = sdiv i32 %op50, 2
%op54 = sdiv i32 %op52, 2
%op56 = sdiv i32 %op54, 2
br label %label4
label4: ; preds = %label_entry, %label59
%op62 = phi i32 [ %op65, %label59 ], [ undef, %label_entry ]
%op63 = phi i32 [ 0, %label_entry ], [ %op61, %label59 ]
%op64 = phi i32 [ %op66, %label59 ], [ undef, %label_entry ]
%op6 = icmp slt i32 %op63, 10000000
%op7 = zext i1 %op6 to i32
%op8 = icmp ne i32 %op7, 0
br i1 %op8, label %label9, label %label10
label9: ; preds = %label4
br label %label12
label10: ; preds = %label4
call void @output(i32 %op62)
ret void
label12: ; preds = %label9, %label17
%op65 = phi i32 [ %op62, %label9 ], [ %op56, %label17 ]
%op66 = phi i32 [ 0, %label9 ], [ %op58, %label17 ]
%op14 = icmp slt i32 %op66, 2
%op15 = zext i1 %op14 to i32
%op16 = icmp ne i32 %op15, 0
br i1 %op16, label %label17, label %label59
label17: ; preds = %label12
%op58 = add i32 %op66, 1
br label %label12
label59: ; preds = %label12
%op61 = add i32 %op63, 1
br label %label4
}
declare i32 @input()
declare void @output(i32)
declare void @outputFloat(float)
declare void @neg_idx_except()
define void @main() {
label_entry:
%op60 = mul i32 2, 2
%op62 = mul i32 %op60, 2
%op64 = mul i32 %op62, 2
%op66 = mul i32 %op64, 2
%op68 = mul i32 %op66, 2
%op70 = mul i32 %op68, 2
%op72 = mul i32 %op70, 2
%op74 = mul i32 %op72, 2
%op76 = mul i32 %op74, 2
%op78 = sdiv i32 %op76, 2
%op80 = sdiv i32 %op78, 2
%op82 = sdiv i32 %op80, 2
%op84 = sdiv i32 %op82, 2
%op86 = sdiv i32 %op84, 2
%op88 = sdiv i32 %op86, 2
%op90 = sdiv i32 %op88, 2
%op92 = sdiv i32 %op90, 2
%op94 = sdiv i32 %op92, 2
%op96 = sdiv i32 %op94, 2
br label %label8
label8: ; preds = %label_entry, %label22
%op102 = phi i32 [ %op109, %label22 ], [ undef, %label_entry ]
%op103 = phi i32 [ %op110, %label22 ], [ undef, %label_entry ]
%op104 = phi i32 [ %op111, %label22 ], [ undef, %label_entry ]
%op105 = phi i32 [ %op112, %label22 ], [ undef, %label_entry ]
%op106 = phi i32 [ %op113, %label22 ], [ undef, %label_entry ]
%op107 = phi i32 [ 0, %label_entry ], [ %op24, %label22 ]
%op108 = phi i32 [ %op114, %label22 ], [ undef, %label_entry ]
%op10 = icmp slt i32 %op107, 1000000
%op11 = zext i1 %op10 to i32
%op12 = icmp ne i32 %op11, 0
br i1 %op12, label %label13, label %label14
label13: ; preds = %label8
br label %label16
label14: ; preds = %label8
call void @output(i32 %op102)
ret void
label16: ; preds = %label13, %label31
%op109 = phi i32 [ %op102, %label13 ], [ %op115, %label31 ]
%op110 = phi i32 [ %op103, %label13 ], [ %op116, %label31 ]
%op111 = phi i32 [ %op104, %label13 ], [ %op117, %label31 ]
%op112 = phi i32 [ %op105, %label13 ], [ %op118, %label31 ]
%op113 = phi i32 [ %op106, %label13 ], [ %op119, %label31 ]
%op114 = phi i32 [ 0, %label13 ], [ %op33, %label31 ]
%op18 = icmp slt i32 %op114, 2
%op19 = zext i1 %op18 to i32
%op20 = icmp ne i32 %op19, 0
br i1 %op20, label %label21, label %label22
label21: ; preds = %label16
br label %label25
label22: ; preds = %label16
%op24 = add i32 %op107, 1
br label %label8
label25: ; preds = %label21, %label40
%op115 = phi i32 [ %op109, %label21 ], [ %op120, %label40 ]
%op116 = phi i32 [ %op110, %label21 ], [ %op121, %label40 ]
%op117 = phi i32 [ %op111, %label21 ], [ %op122, %label40 ]
%op118 = phi i32 [ %op112, %label21 ], [ %op123, %label40 ]
%op119 = phi i32 [ 0, %label21 ], [ %op42, %label40 ]
%op27 = icmp slt i32 %op119, 2
%op28 = zext i1 %op27 to i32
%op29 = icmp ne i32 %op28, 0
br i1 %op29, label %label30, label %label31
label30: ; preds = %label25
br label %label34
label31: ; preds = %label25
%op33 = add i32 %op114, 1
br label %label16
label34: ; preds = %label30, %label49
%op120 = phi i32 [ %op115, %label30 ], [ %op124, %label49 ]
%op121 = phi i32 [ %op116, %label30 ], [ %op125, %label49 ]
%op122 = phi i32 [ %op117, %label30 ], [ %op126, %label49 ]
%op123 = phi i32 [ 0, %label30 ], [ %op51, %label49 ]
%op36 = icmp slt i32 %op123, 2
%op37 = zext i1 %op36 to i32
%op38 = icmp ne i32 %op37, 0
br i1 %op38, label %label39, label %label40
label39: ; preds = %label34
br label %label43
label40: ; preds = %label34
%op42 = add i32 %op119, 1
br label %label25
label43: ; preds = %label39, %label99
%op124 = phi i32 [ %op120, %label39 ], [ %op127, %label99 ]
%op125 = phi i32 [ %op121, %label39 ], [ %op128, %label99 ]
%op126 = phi i32 [ 0, %label39 ], [ %op101, %label99 ]
%op45 = icmp slt i32 %op126, 2
%op46 = zext i1 %op45 to i32
%op47 = icmp ne i32 %op46, 0
br i1 %op47, label %label48, label %label49
label48: ; preds = %label43
br label %label52
label49: ; preds = %label43
%op51 = add i32 %op123, 1
br label %label34
label52: ; preds = %label48, %label57
%op127 = phi i32 [ %op124, %label48 ], [ %op96, %label57 ]
%op128 = phi i32 [ 0, %label48 ], [ %op98, %label57 ]
%op54 = icmp slt i32 %op128, 2
%op55 = zext i1 %op54 to i32
%op56 = icmp ne i32 %op55, 0
br i1 %op56, label %label57, label %label99
label57: ; preds = %label52
%op98 = add i32 %op128, 1
br label %label52
label99: ; preds = %label52
%op101 = add i32 %op126, 1
br label %label43
}
declare i32 @input()
declare void @output(i32)
declare void @outputFloat(float)
declare void @neg_idx_except()
define void @main() {
label_entry:
%op71 = mul i32 2, 2
%op73 = mul i32 %op71, 2
%op75 = mul i32 %op73, 2
%op77 = mul i32 %op75, 2
%op79 = mul i32 %op77, 2
%op81 = mul i32 %op79, 2
%op83 = mul i32 %op81, 2
%op85 = mul i32 %op83, 2
%op87 = mul i32 %op85, 2
%op89 = sdiv i32 %op87, 2
%op91 = sdiv i32 %op89, 2
%op93 = sdiv i32 %op91, 2
%op95 = sdiv i32 %op93, 2
%op97 = sdiv i32 %op95, 2
%op99 = sdiv i32 %op97, 2
%op101 = sdiv i32 %op99, 2
%op103 = sdiv i32 %op101, 2
%op105 = sdiv i32 %op103, 2
%op107 = sdiv i32 %op105, 2
%op59 = icmp sgt i32 2, 1
%op60 = zext i1 %op59 to i32
%op61 = icmp ne i32 %op60, 0
br label %label8
label8: ; preds = %label_entry, %label22
%op110 = phi i32 [ %op117, %label22 ], [ undef, %label_entry ]
%op111 = phi i32 [ %op118, %label22 ], [ undef, %label_entry ]
%op112 = phi i32 [ %op119, %label22 ], [ undef, %label_entry ]
%op113 = phi i32 [ %op120, %label22 ], [ undef, %label_entry ]
%op114 = phi i32 [ %op121, %label22 ], [ undef, %label_entry ]
%op115 = phi i32 [ 0, %label_entry ], [ %op24, %label22 ]
%op116 = phi i32 [ %op122, %label22 ], [ undef, %label_entry ]
%op10 = icmp slt i32 %op115, 1000000
%op11 = zext i1 %op10 to i32
%op12 = icmp ne i32 %op11, 0
br i1 %op12, label %label13, label %label14
label13: ; preds = %label8
br label %label16
label14: ; preds = %label8
call void @output(i32 %op110)
ret void
label16: ; preds = %label13, %label31
%op117 = phi i32 [ %op110, %label13 ], [ %op123, %label31 ]
%op118 = phi i32 [ %op111, %label13 ], [ %op124, %label31 ]
%op119 = phi i32 [ %op112, %label13 ], [ %op125, %label31 ]
%op120 = phi i32 [ %op113, %label13 ], [ %op126, %label31 ]
%op121 = phi i32 [ %op114, %label13 ], [ %op127, %label31 ]
%op122 = phi i32 [ 0, %label13 ], [ %op33, %label31 ]
%op18 = icmp slt i32 %op122, 2
%op19 = zext i1 %op18 to i32
%op20 = icmp ne i32 %op19, 0
br i1 %op20, label %label21, label %label22
label21: ; preds = %label16
br label %label25
label22: ; preds = %label16
%op24 = add i32 %op115, 1
br label %label8
label25: ; preds = %label21, %label40
%op123 = phi i32 [ %op117, %label21 ], [ %op129, %label40 ]
%op124 = phi i32 [ %op118, %label21 ], [ %op130, %label40 ]
%op125 = phi i32 [ %op119, %label21 ], [ %op131, %label40 ]
%op126 = phi i32 [ %op120, %label21 ], [ %op132, %label40 ]
%op127 = phi i32 [ 0, %label21 ], [ %op42, %label40 ]
%op128 = phi i32 [ %op122, %label21 ], [ %op133, %label40 ]
%op27 = icmp slt i32 %op127, 2
%op28 = zext i1 %op27 to i32
%op29 = icmp ne i32 %op28, 0
br i1 %op29, label %label30, label %label31
label30: ; preds = %label25
br label %label34
label31: ; preds = %label25
%op33 = add i32 %op128, 1
br label %label16
label34: ; preds = %label30, %label49
%op129 = phi i32 [ %op123, %label30 ], [ %op134, %label49 ]
%op130 = phi i32 [ %op124, %label30 ], [ %op135, %label49 ]
%op131 = phi i32 [ %op125, %label30 ], [ %op136, %label49 ]
%op132 = phi i32 [ 0, %label30 ], [ %op51, %label49 ]
%op133 = phi i32 [ %op128, %label30 ], [ %op137, %label49 ]
%op36 = icmp slt i32 %op132, 2
%op37 = zext i1 %op36 to i32
%op38 = icmp ne i32 %op37, 0
br i1 %op38, label %label39, label %label40
label39: ; preds = %label34
br label %label43
label40: ; preds = %label34
%op42 = add i32 %op127, 1
br label %label25
label43: ; preds = %label39, %label62
%op134 = phi i32 [ %op129, %label39 ], [ %op138, %label62 ]
%op135 = phi i32 [ %op130, %label39 ], [ %op139, %label62 ]
%op136 = phi i32 [ 0, %label39 ], [ %op64, %label62 ]
%op137 = phi i32 [ %op133, %label39 ], [ %op140, %label62 ]
%op45 = icmp slt i32 %op136, 2
%op46 = zext i1 %op45 to i32
%op47 = icmp ne i32 %op46, 0
br i1 %op47, label %label48, label %label49
label48: ; preds = %label43
br label %label52
label49: ; preds = %label43
%op51 = add i32 %op132, 1
br label %label34
label52: ; preds = %label48, %label68
%op138 = phi i32 [ %op134, %label48 ], [ %op107, %label68 ]
%op139 = phi i32 [ 0, %label48 ], [ %op109, %label68 ]
%op140 = phi i32 [ %op137, %label48 ], [ %op141, %label68 ]
%op54 = icmp slt i32 %op139, 2
%op55 = zext i1 %op54 to i32
%op56 = icmp ne i32 %op55, 0
br i1 %op56, label %label57, label %label62
label57: ; preds = %label52
br i1 %op61, label %label65, label %label68
label62: ; preds = %label52
%op64 = add i32 %op136, 1
br label %label43
label65: ; preds = %label57
%op67 = add i32 %op140, 1
br label %label68
label68: ; preds = %label57, %label65
%op141 = phi i32 [ %op140, %label57 ], [ %op67, %label65 ]
%op109 = add i32 %op139, 1
br label %label52
}
void main(void){
int i;
int j;
int ret;
i = 1;
while(i<10000)
{
j = 0;
while(j<10000)
{
ret = (i*i*i*i*i*i*i*i*i*i)/i/i/i/i/i/i/i/i/i/i;
j=j+1;
}
i=i+1;
}
output(ret);
return ;
}
\ No newline at end of file
void main(void){
int i;
int j;
int a;
int ret;
i = 0;
a = 2;
while(i<10000000)
{
j = 0;
while(j<2)
{
ret = (a*a*a*a*a*a*a*a*a*a)/a/a/a/a/a/a/a/a/a/a;
j=j+1;
}
i=i+1;
}
output(ret);
return ;
}
\ No newline at end of file
void main(void){
int i;
int j;
int k;
int o;
int p;
int q;
int a;
int ret;
a = 2;
i = 0;
while(i<1000000)
{
j = 0;
while(j<2)
{
k = 0;
while(k<2)
{
o = 0;
while(o<2)
{
p = 0;
while(p<2)
{
q = 0;
while(q<2)
{
ret = (a*a*a*a*a*a*a*a*a*a)/a/a/a/a/a/a/a/a/a/a;
q=q+1;
}
p=p+1;
}
o=o+1;
}
k=k+1;
}
j=j+1;
}
i=i+1;
}
output(ret);
return ;
}
\ No newline at end of file
void main(void){
int i;
int j;
int k;
int o;
int p;
int q;
int a;
int ret;
a = 2;
i = 0;
while(i<1000000)
{
j = 0;
while(j<2)
{
k = 0;
while(k<2)
{
o = 0;
while(o<2)
{
p = 0;
while(p<2)
{
q = 0;
while(q<2)
{
if( a > 1 )
{
j = j+1;
}
ret = (a*a*a*a*a*a*a*a*a*a)/a/a/a/a/a/a/a/a/a/a;
q=q+1;
}
p=p+1;
}
o=o+1;
}
k=k+1;
}
j=j+1;
}
i=i+1;
}
output(ret);
return ;
}
\ No newline at end of file
; ModuleID = 'cminus'
source_filename = "/home/zox/compiler/2024ustc-jianmu-compiler-ta/tests/4-mem2reg/performance-cases/testcase-1.cminus"
declare i32 @input()
declare void @output(i32)
declare void @outputFloat(float)
declare void @neg_idx_except()
define void @main() {
label_entry:
%op0 = call i32 @input()
br label %label1
label1: ; preds = %label_entry, %label7
%op2 = phi i32 [ 0, %label_entry ], [ %op33, %label7 ]
%op3 = phi i32 [ 0, %label_entry ], [ %op32, %label7 ]
%op4 = icmp slt i32 %op2, %op0
%op5 = zext i1 %op4 to i32
%op6 = icmp ne i32 %op5, 0
br i1 %op6, label %label7, label %label34
label7: ; preds = %label1
%op8 = fmul float 0x3ff3c0c200000000, 0x4016f06a20000000
%op9 = fmul float %op8, 0x4002aa9940000000
%op10 = fmul float %op9, 0x4011781d80000000
%op11 = fmul float %op10, 0x401962ac40000000
%op12 = fptosi float %op11 to i32
%op13 = mul i32 %op12, %op12
%op14 = mul i32 %op13, %op12
%op15 = mul i32 %op14, %op12
%op16 = mul i32 %op15, %op12
%op17 = mul i32 %op16, %op12
%op18 = mul i32 %op17, %op17
%op19 = mul i32 %op18, %op17
%op20 = mul i32 %op19, %op17
%op21 = mul i32 %op20, %op17
%op22 = mul i32 %op21, %op17
%op23 = mul i32 %op22, %op22
%op24 = mul i32 %op23, %op22
%op25 = mul i32 %op24, %op22
%op26 = mul i32 %op25, %op22
%op27 = mul i32 %op26, %op22
%op28 = mul i32 %op27, %op27
%op29 = mul i32 %op28, %op27
%op30 = mul i32 %op29, %op27
%op31 = mul i32 %op30, %op27
%op32 = mul i32 %op31, %op27
%op33 = add i32 %op2, 1
br label %label1
label34: ; preds = %label1
call void @output(i32 %op3)
ret void
}
; ModuleID = 'cminus'
source_filename = "/home/zox/compiler/2024ustc-jianmu-compiler-ta/tests/4-mem2reg/performance-cases/testcase-2.cminus"
declare i32 @input()
declare void @output(i32)
declare void @outputFloat(float)
declare void @neg_idx_except()
define i32 @main() {
label_entry:
br label %label0
label0: ; preds = %label_entry, %label5
%op1 = phi i32 [ 1, %label_entry ], [ %op6, %label5 ]
%op2 = icmp slt i32 %op1, 999999999
%op3 = zext i1 %op2 to i32
%op4 = icmp ne i32 %op3, 0
br i1 %op4, label %label5, label %label7
label5: ; preds = %label0
%op6 = add i32 %op1, 1
br label %label0
label7: ; preds = %label0
ret i32 %op1
}
; ModuleID = 'cminus'
source_filename = "/home/zox/compiler/2024ustc-jianmu-compiler-ta/tests/4-mem2reg/performance-cases/testcase-3.cminus"
@matrix = global [20000000 x i32] zeroinitializer
@ad = global [100000 x i32] zeroinitializer
@len = global i32 zeroinitializer
declare i32 @input()
declare void @output(i32)
declare void @outputFloat(float)
declare void @neg_idx_except()
define void @readarray() {
label_entry:
br label %label0
label0: ; preds = %label_entry, %label11
%op1 = phi i32 [ 0, %label_entry ], [ %op13, %label11 ]
%op2 = load i32, i32* @len
%op3 = icmp slt i32 %op1, %op2
%op4 = zext i1 %op3 to i32
%op5 = icmp ne i32 %op4, 0
br i1 %op5, label %label6, label %label9
label6: ; preds = %label0
%op7 = call i32 @input()
%op8 = icmp slt i32 %op1, 0
br i1 %op8, label %label10, label %label11
label9: ; preds = %label0
ret void
label10: ; preds = %label6
call void @neg_idx_except()
ret void
label11: ; preds = %label6
%op12 = getelementptr [100000 x i32], [100000 x i32]* @ad, i32 0, i32 %op1
store i32 %op7, i32* %op12
%op13 = add i32 %op1, 1
br label %label0
}
define i32 @transpose(i32 %arg0, i32* %arg1, i32 %arg2) {
label_entry:
%op3 = sdiv i32 %arg0, %arg2
br label %label4
label4: ; preds = %label_entry, %label21
%op5 = phi i32 [ 0, %label_entry ], [ %op22, %label21 ]
%op6 = icmp slt i32 %op5, %op3
%op7 = zext i1 %op6 to i32
%op8 = icmp ne i32 %op7, 0
br i1 %op8, label %label9, label %label10
label9: ; preds = %label4
br label %label12
label10: ; preds = %label4
%op11 = sub i32 0, 1
ret i32 %op11
label12: ; preds = %label9, %label25
%op13 = phi i32 [ 0, %label9 ], [ %op26, %label25 ]
%op14 = icmp slt i32 %op13, %arg2
%op15 = zext i1 %op14 to i32
%op16 = icmp ne i32 %op15, 0
br i1 %op16, label %label17, label %label21
label17: ; preds = %label12
%op18 = icmp slt i32 %op5, %op13
%op19 = zext i1 %op18 to i32
%op20 = icmp ne i32 %op19, 0
br i1 %op20, label %label23, label %label27
label21: ; preds = %label12
%op22 = add i32 %op5, 1
br label %label4
label23: ; preds = %label17
%op24 = add i32 %op13, 1
br label %label25
label25: ; preds = %label23, %label52
%op26 = phi i32 [ %op24, %label23 ], [ %op54, %label52 ]
br label %label12
label27: ; preds = %label17
%op28 = mul i32 %op5, %arg2
%op29 = add i32 %op28, %op13
%op30 = icmp slt i32 %op29, 0
br i1 %op30, label %label31, label %label32
label31: ; preds = %label27
call void @neg_idx_except()
ret i32 0
label32: ; preds = %label27
%op33 = getelementptr i32, i32* %arg1, i32 %op29
%op34 = load i32, i32* %op33
%op35 = mul i32 %op5, %arg2
%op36 = add i32 %op35, %op13
%op37 = icmp slt i32 %op36, 0
br i1 %op37, label %label38, label %label39
label38: ; preds = %label32
call void @neg_idx_except()
ret i32 0
label39: ; preds = %label32
%op40 = getelementptr i32, i32* %arg1, i32 %op36
%op41 = load i32, i32* %op40
%op42 = mul i32 %op13, %op3
%op43 = add i32 %op42, %op5
%op44 = icmp slt i32 %op43, 0
br i1 %op44, label %label45, label %label46
label45: ; preds = %label39
call void @neg_idx_except()
ret i32 0
label46: ; preds = %label39
%op47 = getelementptr i32, i32* %arg1, i32 %op43
store i32 %op41, i32* %op47
%op48 = mul i32 %op5, %arg2
%op49 = add i32 %op48, %op13
%op50 = icmp slt i32 %op49, 0
br i1 %op50, label %label51, label %label52
label51: ; preds = %label46
call void @neg_idx_except()
ret i32 0
label52: ; preds = %label46
%op53 = getelementptr i32, i32* %arg1, i32 %op49
store i32 %op34, i32* %op53
%op54 = add i32 %op13, 1
br label %label25
}
define i32 @main() {
label_entry:
%op0 = call i32 @input()
%op1 = call i32 @input()
store i32 %op1, i32* @len
call void @readarray()
br label %label2
label2: ; preds = %label_entry, %label11
%op3 = phi i32 [ 0, %label_entry ], [ %op13, %label11 ]
%op4 = icmp slt i32 %op3, %op0
%op5 = zext i1 %op4 to i32
%op6 = icmp ne i32 %op5, 0
br i1 %op6, label %label7, label %label9
label7: ; preds = %label2
%op8 = icmp slt i32 %op3, 0
br i1 %op8, label %label10, label %label11
label9: ; preds = %label2
br label %label14
label10: ; preds = %label7
call void @neg_idx_except()
ret i32 0
label11: ; preds = %label7
%op12 = getelementptr [20000000 x i32], [20000000 x i32]* @matrix, i32 0, i32 %op3
store i32 %op3, i32* %op12
%op13 = add i32 %op3, 1
br label %label2
label14: ; preds = %label9, %label25
%op15 = phi i32 [ 0, %label9 ], [ %op29, %label25 ]
%op16 = load i32, i32* @len
%op17 = icmp slt i32 %op15, %op16
%op18 = zext i1 %op17 to i32
%op19 = icmp ne i32 %op18, 0
br i1 %op19, label %label20, label %label23
label20: ; preds = %label14
%op21 = getelementptr [20000000 x i32], [20000000 x i32]* @matrix, i32 0, i32 0
%op22 = icmp slt i32 %op15, 0
br i1 %op22, label %label24, label %label25
label23: ; preds = %label14
br label %label30
label24: ; preds = %label20
call void @neg_idx_except()
ret i32 0
label25: ; preds = %label20
%op26 = getelementptr [100000 x i32], [100000 x i32]* @ad, i32 0, i32 %op15
%op27 = load i32, i32* %op26
%op28 = call i32 @transpose(i32 %op0, i32* %op21, i32 %op27)
%op29 = add i32 %op15, 1
br label %label14
label30: ; preds = %label23, %label45
%op31 = phi i32 [ 0, %label23 ], [ %op49, %label45 ]
%op32 = phi i32 [ 0, %label23 ], [ %op50, %label45 ]
%op33 = load i32, i32* @len
%op34 = icmp slt i32 %op32, %op33
%op35 = zext i1 %op34 to i32
%op36 = icmp ne i32 %op35, 0
br i1 %op36, label %label37, label %label40
label37: ; preds = %label30
%op38 = mul i32 %op32, %op32
%op39 = icmp slt i32 %op32, 0
br i1 %op39, label %label44, label %label45
label40: ; preds = %label30
%op41 = icmp slt i32 %op31, 0
%op42 = zext i1 %op41 to i32
%op43 = icmp ne i32 %op42, 0
br i1 %op43, label %label51, label %label53
label44: ; preds = %label37
call void @neg_idx_except()
ret i32 0
label45: ; preds = %label37
%op46 = getelementptr [20000000 x i32], [20000000 x i32]* @matrix, i32 0, i32 %op32
%op47 = load i32, i32* %op46
%op48 = mul i32 %op38, %op47
%op49 = add i32 %op31, %op48
%op50 = add i32 %op32, 1
br label %label30
label51: ; preds = %label40
%op52 = sub i32 0, %op31
br label %label53
label53: ; preds = %label40, %label51
%op54 = phi i32 [ %op31, %label40 ], [ %op52, %label51 ]
call void @output(i32 %op54)
ret i32 0
}
void main(void) {
int c;
int a;
int b;
int d;
int f;
int g;
int loopCnt;
loopCnt = input();
c = 0;
a = 0;
g = 0;
while (c < loopCnt) {
a = 1.23456 * 5.73478 * 2.3333 * 4.3673 * 6.34636;
b = a * a * a * a * a * a;
d = b * b * b * b * b * b;
f = d * d * d * d * d * d;
g = f * f * f * f * f * f;
c = c + 1;
}
output(g);
return;
}
\ No newline at end of file
int main(void) {
int a;
a = 1;
while (a < 999999999) {
a = a + 1;
}
return a;
}
int matrix[20000000];
int ad[100000];
int len;
void readarray(void) {
int cnt;
cnt = 0;
while (cnt < len) {
ad[cnt] = input();
cnt = cnt + 1;
}
}
int transpose(int n, int matrix[], int rowsize) {
int colsize;
int i;
int j;
int curr;
colsize = n / rowsize;
i = 0;
j = 0;
while (i < colsize) {
j = 0;
while (j < rowsize) {
if (i < j) {
j = j + 1;
} else {
curr = matrix[i * rowsize + j];
matrix[j * colsize + i] = matrix[i * rowsize + j];
matrix[i * rowsize + j] = curr;
j = j + 1;
}
}
i = i + 1;
}
return 0 - 1;
}
int main(void) {
int n;
int i;
int ans;
n = input();
len = input();
readarray();
i = 0;
while (i < n) {
matrix[i] = i;
i = i + 1;
}
i = 0;
while (i < len) {
transpose(n, matrix, ad[i]);
i = i + 1;
}
ans = 0;
i = 0;
while (i < len) {
ans = ans + i * i * matrix[i];
i = i + 1;
}
if (ans < 0) {
ans = 0 - ans;
}
output(ans);
return 0;
}
10000000
30
2
5
4
25
8
125
16
625
32
3125
2
5
4
25
8
125
16
625
32
3125
2
5
4
25
8
125
16
625
32
3125
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment