Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 //===- ARMNaClDivideCheck.cpp - Add divide by zero checks ----------------===// | |
|
Mark Seaborn
2013/05/03 21:25:36
Add 1 more '-' to line up right-hand edge
sehr
2013/05/03 23:29:05
Done.
| |
| 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 before every integer DIV or REM. | |
|
eliben
2013/05/03 21:18:55
Once this CL is committed, we can check the perfor
sehr
2013/05/03 23:29:05
I know fixing it here is simpler a priori. But on
| |
| 11 // | |
| 12 //===----------------------------------------------------------------------===// | |
| 13 | |
| 14 #define DEBUG_TYPE "add-divide-check" | |
| 15 #include "ARM.h" | |
| 16 #include "llvm/ADT/SmallPtrSet.h" | |
| 17 #include "llvm/ADT/STLExtras.h" | |
| 18 #include "llvm/IR/BasicBlock.h" | |
| 19 #include "llvm/IR/Constants.h" | |
| 20 #include "llvm/IR/Function.h" | |
| 21 #include "llvm/IR/Instructions.h" | |
| 22 #include "llvm/IR/Intrinsics.h" | |
| 23 #include "llvm/IR/LLVMContext.h" | |
| 24 #include "llvm/Support/CFG.h" | |
| 25 | |
| 26 using namespace llvm; | |
| 27 | |
| 28 namespace llvm { | |
| 29 void initializeARMNaClDivideCheckPass(PassRegistry&); | |
| 30 } | |
| 31 | |
| 32 namespace { | |
| 33 | |
|
Mark Seaborn
2013/05/03 21:25:36
Remove this empty line
sehr
2013/05/03 23:29:05
Done.
| |
| 34 class ARMNaClDivideCheck : public FunctionPass { | |
| 35 | |
|
Mark Seaborn
2013/05/03 21:25:36
Remove this empty line
sehr
2013/05/03 23:29:05
Done.
| |
| 36 public: | |
| 37 static char ID; | |
| 38 ARMNaClDivideCheck() : FunctionPass(ID) { | |
| 39 initializeARMNaClDivideCheckPass(*PassRegistry::getPassRegistry()); | |
| 40 } | |
| 41 | |
| 42 bool runOnFunction(Function &F); | |
| 43 }; | |
| 44 } | |
| 45 | |
| 46 static BasicBlock *CreateTrapBlock(Function &F) { | |
| 47 BasicBlock *TrapBlock = BasicBlock::Create(F.getContext(), "divrem.by.zero", | |
| 48 &F); | |
| 49 Value *TrapFn = Intrinsic::getDeclaration(F.getParent(), Intrinsic::trap); | |
| 50 CallInst::Create(TrapFn, "", TrapBlock); | |
| 51 new UnreachableInst(F.getContext(), TrapBlock); | |
| 52 return TrapBlock; | |
| 53 } | |
| 54 | |
| 55 bool ARMNaClDivideCheck::runOnFunction(Function &F) { | |
| 56 SmallPtrSet<Instruction*, 8> GuardedDivs; | |
| 57 BasicBlock *TrapBlock = NULL; | |
| 58 // If the pass finds a DIV/REM that needs to be checked for zero denominator, | |
| 59 // it will insert a new "trap" block, and split the block that contains the | |
| 60 // DIV/REM into two blocks. The new BasicBlocks are added to the end of | |
|
eliben
2013/05/03 21:18:55
I'm not sure I understand the "at the end of the f
sehr
2013/05/03 23:29:05
I changed it to just emphasize the important point
| |
| 61 // the function, so that if there is more than one DIV/REM in the same block, | |
| 62 // all are visited. | |
| 63 for (Function::iterator I = F.begin(); I != F.end(); I++) { | |
| 64 BasicBlock *BB = I; | |
| 65 | |
| 66 for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); | |
| 67 BI != BE; BI++) { | |
| 68 BinaryOperator *DivInst = dyn_cast<BinaryOperator>(BI); | |
| 69 if (!DivInst || (GuardedDivs.count(DivInst) != 0)) | |
| 70 continue; | |
| 71 unsigned Opcode = DivInst->getOpcode(); | |
| 72 if (Opcode != Instruction::SDiv && Opcode != Instruction::UDiv && | |
| 73 Opcode != Instruction::SRem && Opcode != Instruction::URem) | |
| 74 continue; | |
| 75 Value *Denominator = DivInst->getOperand(1); | |
| 76 if (!Denominator->getType()->isIntegerTy()) | |
| 77 continue; | |
| 78 ConstantInt *DenomConst = dyn_cast<ConstantInt>(Denominator); | |
| 79 if (DenomConst) { | |
|
Mark Seaborn
2013/05/03 21:25:36
Write as:
if (ConstantInt *DenomConst = dyn_cast
sehr
2013/05/03 23:29:05
Done.
| |
| 80 // Divides by constants do not need a denominator test. | |
| 81 if (DenomConst->isZero()) { | |
| 82 // For explicit divides by zero, insert a trap before DIV/REM | |
| 83 Value *TrapFn = Intrinsic::getDeclaration(F.getParent(), | |
| 84 Intrinsic::trap); | |
| 85 CallInst::Create(TrapFn, "", DivInst); | |
|
Mark Seaborn
2013/05/03 21:25:36
Preserve debug location:
CallInst::Create(TrapFn,
sehr
2013/05/03 23:29:05
Done.
| |
| 86 } | |
| 87 continue; | |
| 88 } | |
| 89 // Create a single trap block. | |
|
Mark Seaborn
2013/05/03 21:25:36
This could hinder debugging. It would be nice to
sehr
2013/05/03 23:29:05
I was only really interested in code size, and I g
| |
| 90 if (TrapBlock == NULL) { | |
| 91 TrapBlock = CreateTrapBlock(F); | |
| 92 } | |
| 93 // Move instructions in BB from DivInst to BB's end to a new block. | |
| 94 BasicBlock *Successor = BB->splitBasicBlock(BI, ""); | |
| 95 BB->getTerminator()->eraseFromParent(); | |
|
Mark Seaborn
2013/05/03 21:25:36
Comment: "Remove unconditional branch"?
sehr
2013/05/03 23:29:05
Done.
| |
| 96 // Remember that DivInst was already processed, so that when we process | |
| 97 // inserted blocks later, we do not attempt to again guard it. | |
| 98 GuardedDivs.insert(DivInst); | |
| 99 // Compare the denominator with zero. | |
| 100 Value *Zero = ConstantInt::get(Denominator->getType(), 0); | |
| 101 Value *DenomIsZero = new ICmpInst(*BB, ICmpInst::ICMP_EQ, Denominator, | |
| 102 Zero, ""); | |
| 103 // Put in a condbranch to the trap block. | |
| 104 BranchInst::Create(TrapBlock, Successor, DenomIsZero, BB); | |
| 105 // BI is invalidated when we split. Stop the BasicBlock iterator. | |
| 106 break; | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 return false; | |
| 111 } | |
| 112 | |
| 113 char ARMNaClDivideCheck::ID = 0; | |
| 114 INITIALIZE_PASS(ARMNaClDivideCheck, "arm-nacl-divide-check", | |
| 115 "Add divide by zero checks", false, false) | |
| 116 | |
| 117 FunctionPass *llvm::createARMNaClDivideCheckPass() { | |
| 118 return new ARMNaClDivideCheck(); | |
| 119 } | |
| OLD | NEW |