diff --git a/include/ir/Module.hh b/include/ir/Module.hh
index 088a5e538c87d45f266f686600d4006c2b0edc7d..fd5ede85623e39944b43ae997a45cba5d72354b5 100644
--- a/include/ir/Module.hh
+++ b/include/ir/Module.hh
@@ -15,7 +15,7 @@ class Module {
   unordered_set<Function*> externFunctions;
   LinkedList<Function*> functions;
   BasicBlock* currBasicBlock;
-
+  unordered_map<string, Function*> libFunctions;
 
  public:
   Module();
@@ -32,13 +32,15 @@ class Module {
   AllocaInst* addAllocaInst(Type* type, string name);
   BinaryOpInst* addBinaryOpInst(OpTag opType, Value* op1, Value* op2,
                                 string name);
-  BranchInst* addBranchInst(Value* cond, BasicBlock* trueBlock, BasicBlock* falseBlock);
+  BranchInst* addBranchInst(Value* cond, BasicBlock* trueBlock,
+                            BasicBlock* falseBlock);
   CallInst* addCallInst(Function* func, string name);
   CallInst* addCallInst(Function* func, vector<Value*>& params, string name);
   IcmpInst* addIcmpInst(OpTag opType, Value* op1, Value* op2, string name);
   FcmpInst* addFcmpInst(OpTag opType, Value* op1, Value* op2, string name);
   FptosiInst* addFptosiInst(Value* src, string name);
-  GetElemPtrInst* addGetElemPtrInst(Value* ptr, Value* idx1, Value* idx2, string name);
+  GetElemPtrInst* addGetElemPtrInst(Value* ptr, Value* idx1, Value* idx2,
+                                    string name);
   GetElemPtrInst* addGetElemPtrInst(Value* ptr, Value* idx1, string name);
   JumpInst* addJumpInst(BasicBlock* block);
   LoadInst* addLoadInst(Value* addr, string name);
@@ -56,7 +58,9 @@ class Module {
   LinkedList<Function*>* getFunctions() { return &functions; }
   unordered_set<Function*>* getexternFunctions() { return &externFunctions; }
 
-
+  void addLibFunction(Function* func) { libFunctions[func->getName()] = func; }
+  Function* getLibFunction(string name) { return libFunctions[name]; }
+  
   void buildCFG();
 
   void irOptimize();
diff --git a/src/asm/Machine.cc b/src/asm/Machine.cc
index e710a49c5b0f939bf647c79a9ea8b5c12f1b6626..b59b1a5f0f44e9afe45e95907f2f126e7702b22d 100644
--- a/src/asm/Machine.cc
+++ b/src/asm/Machine.cc
@@ -610,11 +610,15 @@ vector<MFunction *> MModule::getFunctions() {
 
 std::ostream &operator<<(std::ostream &os, const MModule &obj) {
   bool gen_memset = false;
+  bool gen_multimod = false;
   for (const auto &ef : *obj.externFunctions) {
     if (ef->getName() == "memset") {
       gen_memset = true;
       continue;
     }
+    if (ef->getName() == "antpie_multimod") {
+      gen_multimod = true;
+    }
     os << ".extern " << ef->getName() << endl;
   }
 
@@ -632,6 +636,9 @@ std::ostream &operator<<(std::ostream &os, const MModule &obj) {
   if (gen_memset) {
     os << memset_code << endl;
   }
-
+#include "multimod.hh"
+  if (gen_multimod) {
+    os << multimod_code << endl;
+  }
   return os;
 }
\ No newline at end of file
diff --git a/src/asm/multimod.hh b/src/asm/multimod.hh
new file mode 100644
index 0000000000000000000000000000000000000000..bbf6ee32bc30c2b70578d9c4714310b2700a5c69
--- /dev/null
+++ b/src/asm/multimod.hh
@@ -0,0 +1,20 @@
+// int multimod(int x, int y, int m)
+
+#include <string>
+
+std::string multimod_code =
+    "antpie_multimod:\n"
+    "        mul    a3, a1, a0\n"
+    "        fcvt.d.l        fa5, a0\n"
+    "        fcvt.d.l        fa4, a1\n"
+    "        fmul.d  fa5, fa5, fa4\n"
+    "        fcvt.d.l        fa4, a2\n"
+    "        fdiv.d  fa5, fa5, fa4\n"
+    "        fcvt.l.d        a0, fa5, rtz\n"
+    "        mul     a0, a0, a2\n"
+    "        sub     a3, a3, a0\n"
+    "        rem     a0, a3, a2\n"
+    "        srai    a1, a0, 63\n"
+    "        and     a1, a1, a2\n"
+    "        addw    a0, a0, a1\n"
+    "        ret\n";
\ No newline at end of file
diff --git a/src/frontend/MySysYParserVisitor.cc b/src/frontend/MySysYParserVisitor.cc
index 93f118b552b7b74b7cb75af89b6add5221d8c91d..eb4509ffe7aa1de1b9cef49c8caf76cc0186e6ad 100644
--- a/src/frontend/MySysYParserVisitor.cc
+++ b/src/frontend/MySysYParserVisitor.cc
@@ -1124,8 +1124,17 @@ void MySysYParserVisitor::init_extern_function() {
   function = new Function(funcType, true, "_sysy_stoptime");
   current->put("stoptime", function);
 
+  // int antpie_multimod(int x, int y, int m)
+  vector<Argument*> mmArgs = {new Argument("x", i32Type),
+                              new Argument("y", i32Type),
+                              new Argument("m", i32Type)};
+  funcType = Type::getFuncType(i32Type, mmArgs);
+  function = new Function(funcType, true, "antpie_multimod");
+  externFunctions.push_back(function);
+  
   for (Function* function : externFunctions) {
     current->put(function->getName(), function);
+    module.addLibFunction(function);
   }
 }
 
diff --git a/src/ir/Module.cc b/src/ir/Module.cc
index 53c4182c68daf869afd2fe6e55259a6e3c9516e4..80d4440c9ecd0bec8520f13cefcf6b8002626b3b 100644
--- a/src/ir/Module.cc
+++ b/src/ir/Module.cc
@@ -311,9 +311,14 @@ void Module::irOptimize() {
   optimizations.pushBack(new LoopSimplify(false));
   optimizations.pushBack(new LoopInvariantCodeMotion());
   optimizations.pushBack(new Reassociate());
+
   optimizations.pushBack(new GEPSimplify());
+
+  optimizations.pushBack(new StrengthReduction());
   optimizations.pushBack(new TailRecursionElimination());
   optimizations.pushBack(new MergeBlock());
+  optimizations.pushBack(new LoadElimination());
+  optimizations.pushBack(new ConstantFolding());
   optimizations.pushBack(new CFGSimplify());
   optimizations.pushBack(new DeadCodeElimination());
 
@@ -322,6 +327,7 @@ void Module::irOptimize() {
     // if (dynamic_cast<Reassociate*>(pass)) printIR(std::cout);
 
     pass->runOnModule(this);
+    // if (dynamic_cast<Reassociate*>(pass)) printIR(std::cout);
   }
 
   for (Function* func : functions) {
diff --git a/src/opt/Reassociate.cc b/src/opt/Reassociate.cc
index 7af38108f5e5907d724cf07024db07286a3b97fa..6fbc5945666a9b7ded48aa8058063a29d79c56bb 100644
--- a/src/opt/Reassociate.cc
+++ b/src/opt/Reassociate.cc
@@ -58,7 +58,11 @@ bool Reassociate::runOnBasicBlock(BasicBlock* block) {
         break;
       }
     }
-
+    unordered_map<const Value*, int> idx;
+    int i = 0;
+    for (auto arg : args) {
+      idx[arg] = i++;
+    }
     if (!flag) {
       changed = true;
       std::sort(args.begin(), args.end(),
@@ -67,7 +71,10 @@ bool Reassociate::runOnBasicBlock(BasicBlock* block) {
                     return true;
                   if (rhs->isa(VT_INTCONST) && !lhs->isa(VT_INTCONST))
                     return false;
-                  return lhs < rhs;
+                  if (lhs->isa(VT_PHI) && !rhs->isa(VT_PHI)) return false;
+                  if (!lhs->isa(VT_PHI) && rhs->isa(VT_PHI)) return true;
+
+                  return idx[lhs] < idx[rhs];
                 });
       int constValue = 0;
       int initValue = 0;