Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 //===- ARMNaClDivideCheck.cpp - Add divide by zero checks ----------------===// | |
| 2 // | |
| 3 // The LLVM Compiler Infrastructure | |
| 4 // | |
| 5 // This file is distributed under the University of Illinois Open Source | |
| 6 // License. See LICENSE.TXT for details. | |
| 7 // | |
| 8 //===----------------------------------------------------------------------===// | |
| 9 // | |
| 10 // This pass adds a check for divide by zero after every integer DIV or REM. | |
|
eliben
2013/05/02 21:47:31
after?
sehr
2013/05/03 20:33:07
I changed the code to put the branch before.
| |
| 11 // | |
| 12 //===----------------------------------------------------------------------===// | |
| 13 | |
| 14 #define DEBUG_TYPE "add-divide-check" | |
| 15 #include "ARM.h" | |
| 16 #include "llvm/ADT/STLExtras.h" | |
| 17 #include "llvm/IR/BasicBlock.h" | |
| 18 #include "llvm/IR/Constants.h" | |
| 19 #include "llvm/IR/Function.h" | |
| 20 #include "llvm/IR/Instructions.h" | |
| 21 #include "llvm/IR/Intrinsics.h" | |
| 22 #include "llvm/IR/LLVMContext.h" | |
| 23 #include "llvm/Support/CFG.h" | |
| 24 | |
| 25 using namespace llvm; | |
| 26 | |
| 27 namespace llvm { | |
| 28 void initializeARMNaClDivideCheckPass(PassRegistry&); | |
| 29 } | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 class ARMNaClDivideCheck : public FunctionPass { | |
| 34 | |
| 35 public: | |
| 36 static char ID; | |
| 37 ARMNaClDivideCheck() : FunctionPass(ID) { | |
| 38 initializeARMNaClDivideCheckPass(*PassRegistry::getPassRegistry()); | |
| 39 } | |
| 40 | |
| 41 bool runOnFunction(Function &F); | |
| 42 }; | |
| 43 } | |
| 44 | |
| 45 | |
| 46 bool ARMNaClDivideCheck::runOnFunction(Function &F) { | |
| 47 Module *M = F.getParent(); | |
| 48 BasicBlock *TrapBlock = NULL; | |
| 49 // BasicBlock list is being appended to during the optimization. | |
|
eliben
2013/05/02 21:47:31
I'd prefer to see a beefier comment explaining tha
sehr
2013/05/03 20:33:07
Done.
| |
| 50 for (Function::iterator I = F.begin(); I != F.end(); I++) { | |
| 51 BasicBlock *BB = I; | |
| 52 | |
| 53 for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { | |
| 54 BinaryOperator *DivInst = dyn_cast<BinaryOperator>(BI++); | |
| 55 if (!DivInst) | |
| 56 continue; | |
| 57 unsigned Opcode = DivInst->getOpcode(); | |
| 58 if (Opcode != Instruction::SDiv && Opcode != Instruction::UDiv && | |
| 59 Opcode != Instruction::SRem && Opcode != Instruction::URem) | |
| 60 continue; | |
| 61 // Create a single trap block. | |
|
Jim Stichnoth
2013/05/02 21:37:16
You might want to check whether the denominator is
sehr
2013/05/03 20:33:07
Done. I insert a trap before any explicit divide
| |
| 62 if (TrapBlock == NULL) { | |
|
eliben
2013/05/02 21:47:31
Put the trap block creation into a helper method?
sehr
2013/05/03 20:33:07
Done.
| |
| 63 TrapBlock = BasicBlock::Create(F.getContext(), "divrem.by.zero", | |
| 64 &F, NULL); | |
|
eliben
2013/05/02 21:47:31
No need for explicit NULL here
sehr
2013/05/03 20:33:07
Done.
| |
| 65 Value *TrapFn = Intrinsic::getDeclaration(M, Intrinsic::trap); | |
| 66 CallInst::Create(TrapFn, "", TrapBlock); | |
| 67 new UnreachableInst(DivInst->getContext(), TrapBlock); | |
| 68 } | |
| 69 // Move all of the instructions from BB after DivInst to a new block. | |
| 70 BasicBlock *Successor = BB->splitBasicBlock(BI, ""); | |
|
eliben
2013/05/02 21:47:31
suggested tests: the div/rem is first / last instr
sehr
2013/05/03 20:33:07
Done.
| |
| 71 BB->getTerminator()->eraseFromParent(); | |
| 72 // Compare the denominator with zero. | |
| 73 Value *Denominator = DivInst->getOperand(1); | |
| 74 Value *Zero = ConstantInt::get(Denominator->getType(), 0); | |
| 75 Value *DenomIsZero = new ICmpInst(DivInst, ICmpInst::ICMP_EQ, Denominator, | |
| 76 Zero, ""); | |
| 77 // Put in a condbranch to the trap block. | |
| 78 BranchInst::Create(TrapBlock, Successor, DenomIsZero, BB); | |
| 79 // BI became invalid when we split. Stop BasicBlock iterator. | |
| 80 break; | |
| 81 } | |
| 82 } | |
| 83 | |
| 84 return false; | |
| 85 } | |
| 86 | |
| 87 char ARMNaClDivideCheck::ID = 0; | |
| 88 INITIALIZE_PASS(ARMNaClDivideCheck, "arm-nacl-divide-check", | |
| 89 "Add divide by zero checks", false, false) | |
| 90 | |
| 91 FunctionPass *llvm::createARMNaClDivideCheckPass() { | |
| 92 return new ARMNaClDivideCheck(); | |
| 93 } | |
| OLD | NEW |