diff options
Diffstat (limited to 'llvm_mode/split-compares-pass.so.cc')
-rw-r--r-- | llvm_mode/split-compares-pass.so.cc | 338 |
1 files changed, 202 insertions, 136 deletions
diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index a74b60fa..1e9d6542 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -27,117 +27,126 @@ using namespace llvm; namespace { - class SplitComparesTransform : public ModulePass { - public: - static char ID; - SplitComparesTransform() : ModulePass(ID) {} - bool runOnModule(Module &M) override; +class SplitComparesTransform : public ModulePass { + + public: + static char ID; + SplitComparesTransform() : ModulePass(ID) { + + } + + bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR >= 4 - StringRef getPassName() const override { + StringRef getPassName() const override { + #else - const char * getPassName() const override { + const char *getPassName() const override { + #endif - return "simplifies and splits ICMP instructions"; - } - private: - bool splitCompares(Module &M, unsigned bitw); - bool simplifyCompares(Module &M); - bool simplifySignedness(Module &M); + return "simplifies and splits ICMP instructions"; - }; -} + } + + private: + bool splitCompares(Module &M, unsigned bitw); + bool simplifyCompares(Module &M); + bool simplifySignedness(Module &M); + +}; + +} // namespace char SplitComparesTransform::ID = 0; -/* This function splits ICMP instructions with xGE or xLE predicates into two +/* This function splits ICMP instructions with xGE or xLE predicates into two * ICMP instructions with predicate xGT or xLT and EQ */ bool SplitComparesTransform::simplifyCompares(Module &M) { - LLVMContext &C = M.getContext(); - std::vector<Instruction*> icomps; - IntegerType *Int1Ty = IntegerType::getInt1Ty(C); + + LLVMContext & C = M.getContext(); + std::vector<Instruction *> icomps; + IntegerType * Int1Ty = IntegerType::getInt1Ty(C); /* iterate over all functions, bbs and instruction and add * all integer comparisons with >= and <= predicates to the icomps vector */ for (auto &F : M) { + for (auto &BB : F) { - for (auto &IN: BB) { - CmpInst* selectcmpInst = nullptr; + + for (auto &IN : BB) { + + CmpInst *selectcmpInst = nullptr; if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) { if (selectcmpInst->getPredicate() != CmpInst::ICMP_UGE && selectcmpInst->getPredicate() != CmpInst::ICMP_SGE && selectcmpInst->getPredicate() != CmpInst::ICMP_ULE && - selectcmpInst->getPredicate() != CmpInst::ICMP_SLE ) { + selectcmpInst->getPredicate() != CmpInst::ICMP_SLE) { + continue; + } auto op0 = selectcmpInst->getOperand(0); auto op1 = selectcmpInst->getOperand(1); - IntegerType* intTyOp0 = dyn_cast<IntegerType>(op0->getType()); - IntegerType* intTyOp1 = dyn_cast<IntegerType>(op1->getType()); + IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType()); + IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType()); /* this is probably not needed but we do it anyway */ - if (!intTyOp0 || !intTyOp1) { - continue; - } + if (!intTyOp0 || !intTyOp1) { continue; } icomps.push_back(selectcmpInst); + } + } + } - } - if (!icomps.size()) { - return false; } + if (!icomps.size()) { return false; } + + for (auto &IcmpInst : icomps) { - for (auto &IcmpInst: icomps) { - BasicBlock* bb = IcmpInst->getParent(); + BasicBlock *bb = IcmpInst->getParent(); auto op0 = IcmpInst->getOperand(0); auto op1 = IcmpInst->getOperand(1); /* find out what the new predicate is going to be */ - auto pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate(); + auto pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate(); CmpInst::Predicate new_pred; - switch(pred) { - case CmpInst::ICMP_UGE: - new_pred = CmpInst::ICMP_UGT; - break; - case CmpInst::ICMP_SGE: - new_pred = CmpInst::ICMP_SGT; - break; - case CmpInst::ICMP_ULE: - new_pred = CmpInst::ICMP_ULT; - break; - case CmpInst::ICMP_SLE: - new_pred = CmpInst::ICMP_SLT; - break; - default: // keep the compiler happy + switch (pred) { + + case CmpInst::ICMP_UGE: new_pred = CmpInst::ICMP_UGT; break; + case CmpInst::ICMP_SGE: new_pred = CmpInst::ICMP_SGT; break; + case CmpInst::ICMP_ULE: new_pred = CmpInst::ICMP_ULT; break; + case CmpInst::ICMP_SLE: new_pred = CmpInst::ICMP_SLT; break; + default: // keep the compiler happy continue; + } /* split before the icmp instruction */ - BasicBlock* end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst)); + BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst)); /* the old bb now contains a unconditional jump to the new one (end_bb) * we need to delete it later */ /* create the ICMP instruction with new_pred and add it to the old basic * block bb it is now at the position where the old IcmpInst was */ - Instruction* icmp_np; + Instruction *icmp_np; icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1); bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_np); /* create a new basic block which holds the new EQ icmp */ Instruction *icmp_eq; /* insert middle_bb before end_bb */ - BasicBlock* middle_bb = BasicBlock::Create(C, "injected", - end_bb->getParent(), end_bb); + BasicBlock *middle_bb = + BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1); middle_bb->getInstList().push_back(icmp_eq); /* add an unconditional branch to the end of middle_bb with destination @@ -150,7 +159,6 @@ bool SplitComparesTransform::simplifyCompares(Module &M) { BranchInst::Create(end_bb, middle_bb, icmp_np, bb); term->eraseFromParent(); - /* replace the old IcmpInst (which is the first inst in end_bb) with a PHI * inst to wire up the loose ends */ PHINode *PN = PHINode::Create(Int1Ty, 2, ""); @@ -162,118 +170,139 @@ bool SplitComparesTransform::simplifyCompares(Module &M) { /* replace the old IcmpInst with our new and shiny PHI inst */ BasicBlock::iterator ii(IcmpInst); ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN); + } return true; + } /* this function transforms signed compares to equivalent unsigned compares */ bool SplitComparesTransform::simplifySignedness(Module &M) { - LLVMContext &C = M.getContext(); - std::vector<Instruction*> icomps; - IntegerType *Int1Ty = IntegerType::getInt1Ty(C); + + LLVMContext & C = M.getContext(); + std::vector<Instruction *> icomps; + IntegerType * Int1Ty = IntegerType::getInt1Ty(C); /* iterate over all functions, bbs and instruction and add * all signed compares to icomps vector */ for (auto &F : M) { + for (auto &BB : F) { - for(auto &IN: BB) { - CmpInst* selectcmpInst = nullptr; + + for (auto &IN : BB) { + + CmpInst *selectcmpInst = nullptr; if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) { if (selectcmpInst->getPredicate() != CmpInst::ICMP_SGT && - selectcmpInst->getPredicate() != CmpInst::ICMP_SLT - ) { + selectcmpInst->getPredicate() != CmpInst::ICMP_SLT) { + continue; + } auto op0 = selectcmpInst->getOperand(0); auto op1 = selectcmpInst->getOperand(1); - IntegerType* intTyOp0 = dyn_cast<IntegerType>(op0->getType()); - IntegerType* intTyOp1 = dyn_cast<IntegerType>(op1->getType()); + IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType()); + IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType()); /* see above */ - if (!intTyOp0 || !intTyOp1) { - continue; - } + if (!intTyOp0 || !intTyOp1) { continue; } /* i think this is not possible but to lazy to look it up */ - if (intTyOp0->getBitWidth() != intTyOp1->getBitWidth()) { - continue; - } + if (intTyOp0->getBitWidth() != intTyOp1->getBitWidth()) { continue; } icomps.push_back(selectcmpInst); + } + } + } - } - if (!icomps.size()) { - return false; } - for (auto &IcmpInst: icomps) { - BasicBlock* bb = IcmpInst->getParent(); + if (!icomps.size()) { return false; } + + for (auto &IcmpInst : icomps) { + + BasicBlock *bb = IcmpInst->getParent(); auto op0 = IcmpInst->getOperand(0); auto op1 = IcmpInst->getOperand(1); - IntegerType* intTyOp0 = dyn_cast<IntegerType>(op0->getType()); - unsigned bitw = intTyOp0->getBitWidth(); + IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType()); + unsigned bitw = intTyOp0->getBitWidth(); IntegerType *IntType = IntegerType::get(C, bitw); - /* get the new predicate */ - auto pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate(); + auto pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate(); CmpInst::Predicate new_pred; if (pred == CmpInst::ICMP_SGT) { + new_pred = CmpInst::ICMP_UGT; + } else { + new_pred = CmpInst::ICMP_ULT; + } - BasicBlock* end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst)); + BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst)); /* create a 1 bit compare for the sign bit. to do this shift and trunc * the original operands so only the first bit remains.*/ Instruction *s_op0, *t_op0, *s_op1, *t_op1, *icmp_sign_bit; - s_op0 = BinaryOperator::Create(Instruction::LShr, op0, ConstantInt::get(IntType, bitw - 1)); + s_op0 = BinaryOperator::Create(Instruction::LShr, op0, + ConstantInt::get(IntType, bitw - 1)); bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op0); t_op0 = new TruncInst(s_op0, Int1Ty); bb->getInstList().insert(bb->getTerminator()->getIterator(), t_op0); - s_op1 = BinaryOperator::Create(Instruction::LShr, op1, ConstantInt::get(IntType, bitw - 1)); + s_op1 = BinaryOperator::Create(Instruction::LShr, op1, + ConstantInt::get(IntType, bitw - 1)); bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op1); t_op1 = new TruncInst(s_op1, Int1Ty); bb->getInstList().insert(bb->getTerminator()->getIterator(), t_op1); /* compare of the sign bits */ - icmp_sign_bit = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_op0, t_op1); + icmp_sign_bit = + CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_op0, t_op1); bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_sign_bit); /* create a new basic block which is executed if the signedness bit is - * different */ + * different */ Instruction *icmp_inv_sig_cmp; - BasicBlock* sign_bb = BasicBlock::Create(C, "sign", end_bb->getParent(), end_bb); + BasicBlock * sign_bb = + BasicBlock::Create(C, "sign", end_bb->getParent(), end_bb); if (pred == CmpInst::ICMP_SGT) { + /* if we check for > and the op0 positive and op1 negative then the final * result is true. if op0 negative and op1 pos, the cmp must result * in false */ - icmp_inv_sig_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_op0, t_op1); + icmp_inv_sig_cmp = + CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_op0, t_op1); + } else { + /* just the inverse of the above statement */ - icmp_inv_sig_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_op0, t_op1); + icmp_inv_sig_cmp = + CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_op0, t_op1); + } + sign_bb->getInstList().push_back(icmp_inv_sig_cmp); BranchInst::Create(end_bb, sign_bb); /* create a new bb which is executed if signedness is equal */ Instruction *icmp_usign_cmp; - BasicBlock* middle_bb = BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); + BasicBlock * middle_bb = + BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); /* we can do a normal unsigned compare now */ icmp_usign_cmp = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1); middle_bb->getInstList().push_back(icmp_usign_cmp); @@ -285,7 +314,6 @@ bool SplitComparesTransform::simplifySignedness(Module &M) { BranchInst::Create(middle_bb, sign_bb, icmp_sign_bit, bb); term->eraseFromParent(); - PHINode *PN = PHINode::Create(Int1Ty, 2, ""); PN->addIncoming(icmp_usign_cmp, middle_bb); @@ -293,91 +321,100 @@ bool SplitComparesTransform::simplifySignedness(Module &M) { BasicBlock::iterator ii(IcmpInst); ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN); + } return true; + } /* splits icmps of size bitw into two nested icmps with bitw/2 size each */ bool SplitComparesTransform::splitCompares(Module &M, unsigned bitw) { + LLVMContext &C = M.getContext(); IntegerType *Int1Ty = IntegerType::getInt1Ty(C); IntegerType *OldIntType = IntegerType::get(C, bitw); IntegerType *NewIntType = IntegerType::get(C, bitw / 2); - std::vector<Instruction*> icomps; + std::vector<Instruction *> icomps; - if (bitw % 2) { - return false; - } + if (bitw % 2) { return false; } /* not supported yet */ - if (bitw > 64) { - return false; - } + if (bitw > 64) { return false; } - /* get all EQ, NE, UGT, and ULT icmps of width bitw. if the other two + /* get all EQ, NE, UGT, and ULT icmps of width bitw. if the other two * unctions were executed only these four predicates should exist */ for (auto &F : M) { + for (auto &BB : F) { - for(auto &IN: BB) { - CmpInst* selectcmpInst = nullptr; + + for (auto &IN : BB) { + + CmpInst *selectcmpInst = nullptr; if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) { - if(selectcmpInst->getPredicate() != CmpInst::ICMP_EQ && - selectcmpInst->getPredicate() != CmpInst::ICMP_NE && - selectcmpInst->getPredicate() != CmpInst::ICMP_UGT && - selectcmpInst->getPredicate() != CmpInst::ICMP_ULT - ) { + if (selectcmpInst->getPredicate() != CmpInst::ICMP_EQ && + selectcmpInst->getPredicate() != CmpInst::ICMP_NE && + selectcmpInst->getPredicate() != CmpInst::ICMP_UGT && + selectcmpInst->getPredicate() != CmpInst::ICMP_ULT) { + continue; + } auto op0 = selectcmpInst->getOperand(0); auto op1 = selectcmpInst->getOperand(1); - IntegerType* intTyOp0 = dyn_cast<IntegerType>(op0->getType()); - IntegerType* intTyOp1 = dyn_cast<IntegerType>(op1->getType()); + IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType()); + IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType()); - if (!intTyOp0 || !intTyOp1) { - continue; - } + if (!intTyOp0 || !intTyOp1) { continue; } /* check if the bitwidths are the one we are looking for */ - if (intTyOp0->getBitWidth() != bitw || intTyOp1->getBitWidth() != bitw) { + if (intTyOp0->getBitWidth() != bitw || + intTyOp1->getBitWidth() != bitw) { + continue; + } icomps.push_back(selectcmpInst); + } + } + } - } - if (!icomps.size()) { - return false; } - for (auto &IcmpInst: icomps) { - BasicBlock* bb = IcmpInst->getParent(); + if (!icomps.size()) { return false; } + + for (auto &IcmpInst : icomps) { + + BasicBlock *bb = IcmpInst->getParent(); auto op0 = IcmpInst->getOperand(0); auto op1 = IcmpInst->getOperand(1); auto pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate(); - BasicBlock* end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst)); + BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst)); /* create the comparison of the top halves of the original operands */ Instruction *s_op0, *op0_high, *s_op1, *op1_high, *icmp_high; - s_op0 = BinaryOperator::Create(Instruction::LShr, op0, ConstantInt::get(OldIntType, bitw / 2)); + s_op0 = BinaryOperator::Create(Instruction::LShr, op0, + ConstantInt::get(OldIntType, bitw / 2)); bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op0); op0_high = new TruncInst(s_op0, NewIntType); bb->getInstList().insert(bb->getTerminator()->getIterator(), op0_high); - s_op1 = BinaryOperator::Create(Instruction::LShr, op1, ConstantInt::get(OldIntType, bitw / 2)); + s_op1 = BinaryOperator::Create(Instruction::LShr, op1, + ConstantInt::get(OldIntType, bitw / 2)); bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op1); op1_high = new TruncInst(s_op1, NewIntType); bb->getInstList().insert(bb->getTerminator()->getIterator(), op1_high); @@ -387,11 +424,13 @@ bool SplitComparesTransform::splitCompares(Module &M, unsigned bitw) { /* now we have to destinguish between == != and > < */ if (pred == CmpInst::ICMP_EQ || pred == CmpInst::ICMP_NE) { + /* transformation for == and != icmps */ /* create a compare for the lower half of the original operands */ Instruction *op0_low, *op1_low, *icmp_low; - BasicBlock* cmp_low_bb = BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); + BasicBlock * cmp_low_bb = + BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); op0_low = new TruncInst(op0, NewIntType); cmp_low_bb->getInstList().push_back(op0_low); @@ -407,21 +446,30 @@ bool SplitComparesTransform::splitCompares(Module &M, unsigned bitw) { * the comparison */ auto term = bb->getTerminator(); if (pred == CmpInst::ICMP_EQ) { + BranchInst::Create(cmp_low_bb, end_bb, icmp_high, bb); + } else { + /* CmpInst::ICMP_NE */ BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb); + } + term->eraseFromParent(); /* create the PHI and connect the edges accordingly */ PHINode *PN = PHINode::Create(Int1Ty, 2, ""); PN->addIncoming(icmp_low, cmp_low_bb); if (pred == CmpInst::ICMP_EQ) { + PN->addIncoming(ConstantInt::get(Int1Ty, 0), bb); + } else { + /* CmpInst::ICMP_NE */ PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb); + } /* replace the old icmp with the new PHI */ @@ -429,19 +477,28 @@ bool SplitComparesTransform::splitCompares(Module &M, unsigned bitw) { ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN); } else { + /* CmpInst::ICMP_UGT and CmpInst::ICMP_ULT */ /* transformations for < and > */ - /* create a basic block which checks for the inverse predicate. + /* create a basic block which checks for the inverse predicate. * if this is true we can go to the end if not we have to got to the * bb which checks the lower half of the operands */ Instruction *icmp_inv_cmp, *op0_low, *op1_low, *icmp_low; - BasicBlock* inv_cmp_bb = BasicBlock::Create(C, "inv_cmp", end_bb->getParent(), end_bb); + BasicBlock * inv_cmp_bb = + BasicBlock::Create(C, "inv_cmp", end_bb->getParent(), end_bb); if (pred == CmpInst::ICMP_UGT) { - icmp_inv_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, op0_high, op1_high); + + icmp_inv_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, + op0_high, op1_high); + } else { - icmp_inv_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, op0_high, op1_high); + + icmp_inv_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, + op0_high, op1_high); + } + inv_cmp_bb->getInstList().push_back(icmp_inv_cmp); auto term = bb->getTerminator(); @@ -449,7 +506,8 @@ bool SplitComparesTransform::splitCompares(Module &M, unsigned bitw) { BranchInst::Create(end_bb, inv_cmp_bb, icmp_high, bb); /* create a bb which handles the cmp of the lower halves */ - BasicBlock* cmp_low_bb = BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); + BasicBlock *cmp_low_bb = + BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); op0_low = new TruncInst(op0, NewIntType); cmp_low_bb->getInstList().push_back(op0_low); op1_low = new TruncInst(op1, NewIntType); @@ -468,57 +526,64 @@ bool SplitComparesTransform::splitCompares(Module &M, unsigned bitw) { BasicBlock::iterator ii(IcmpInst); ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN); + } + } - return true; + + return true; + } bool SplitComparesTransform::runOnModule(Module &M) { + int bitw = 64; - char* bitw_env = getenv("LAF_SPLIT_COMPARES_BITW"); - if (!bitw_env) - bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW"); - if (bitw_env) { - bitw = atoi(bitw_env); - } + char *bitw_env = getenv("LAF_SPLIT_COMPARES_BITW"); + if (!bitw_env) bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW"); + if (bitw_env) { bitw = atoi(bitw_env); } simplifyCompares(M); simplifySignedness(M); if (getenv("AFL_QUIET") == NULL) - errs() << "Split-compare-pass by laf.intel@gmail.com\n"; + errs() << "Split-compare-pass by laf.intel@gmail.com\n"; switch (bitw) { + case 64: - errs() << "Running split-compare-pass " << 64 << "\n"; + errs() << "Running split-compare-pass " << 64 << "\n"; splitCompares(M, 64); - [[clang::fallthrough]]; /*FALLTHRU*/ /* FALLTHROUGH */ + [[clang::fallthrough]]; /*FALLTHRU*/ /* FALLTHROUGH */ case 32: - errs() << "Running split-compare-pass " << 32 << "\n"; + errs() << "Running split-compare-pass " << 32 << "\n"; splitCompares(M, 32); - [[clang::fallthrough]]; /*FALLTHRU*/ /* FALLTHROUGH */ + [[clang::fallthrough]]; /*FALLTHRU*/ /* FALLTHROUGH */ case 16: - errs() << "Running split-compare-pass " << 16 << "\n"; + errs() << "Running split-compare-pass " << 16 << "\n"; splitCompares(M, 16); break; default: - errs() << "NOT Running split-compare-pass \n"; + errs() << "NOT Running split-compare-pass \n"; return false; break; + } verifyModule(M); return true; + } static void registerSplitComparesPass(const PassManagerBuilder &, - legacy::PassManagerBase &PM) { + legacy::PassManagerBase &PM) { + PM.add(new SplitComparesTransform()); + } static RegisterStandardPasses RegisterSplitComparesPass( @@ -526,3 +591,4 @@ static RegisterStandardPasses RegisterSplitComparesPass( static RegisterStandardPasses RegisterSplitComparesTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass); + |