Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: lib/Transforms/NaCl/InsertDivideCheck.cpp

Issue 14607004: Insert denominator zero checks for NaCl (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Moved to Transforms/NaCl, added opt invocation to test Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //===- InsertDivideCheck.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 before every integer DIV or REM.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "add-divide-check"
15 #include "llvm/ADT/SmallPtrSet.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/Pass.h"
24 #include "llvm/Support/CFG.h"
25 #include "llvm/Transforms/NaCl.h"
26
27 using namespace llvm;
28
29 namespace {
30 class InsertDivideCheck : public FunctionPass {
31 public:
32 static char ID;
33 InsertDivideCheck() : FunctionPass(ID) {
34 initializeInsertDivideCheckPass(*PassRegistry::getPassRegistry());
35 }
36
37 bool runOnFunction(Function &F);
38 };
39 }
40
41 static BasicBlock *CreateTrapBlock(Function &F, DebugLoc dl) {
42 BasicBlock *TrapBlock = BasicBlock::Create(F.getContext(), "divrem.by.zero",
43 &F);
44 Value *TrapFn = Intrinsic::getDeclaration(F.getParent(), Intrinsic::trap);
45 CallInst::Create(TrapFn, "", TrapBlock)->setDebugLoc(dl);
46 (new UnreachableInst(F.getContext(), TrapBlock))->setDebugLoc(dl);
47 return TrapBlock;
48 }
49
50 bool InsertDivideCheck::runOnFunction(Function &F) {
51 SmallPtrSet<Instruction*, 8> GuardedDivs;
52 // If the pass finds a DIV/REM that needs to be checked for zero denominator,
53 // it will insert a new "trap" block, and split the block that contains the
54 // DIV/REM into two blocks. The new BasicBlocks are added after the current
55 // BasicBlock, so that if there is more than one DIV/REM in the same block,
56 // all are visited.
57 for (Function::iterator I = F.begin(); I != F.end(); I++) {
58 BasicBlock *BB = I;
59
60 for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
61 BI != BE; BI++) {
62 BinaryOperator *DivInst = dyn_cast<BinaryOperator>(BI);
63 if (!DivInst || (GuardedDivs.count(DivInst) != 0))
64 continue;
65 unsigned Opcode = DivInst->getOpcode();
66 if (Opcode != Instruction::SDiv && Opcode != Instruction::UDiv &&
67 Opcode != Instruction::SRem && Opcode != Instruction::URem)
68 continue;
69 Value *Denominator = DivInst->getOperand(1);
70 if (!Denominator->getType()->isIntegerTy())
71 continue;
72 DebugLoc dl = DivInst->getDebugLoc();
73 if (ConstantInt *DenomConst = dyn_cast<ConstantInt>(Denominator)) {
74 // Divides by constants do not need a denominator test.
75 if (DenomConst->isZero()) {
76 // For explicit divides by zero, insert a trap before DIV/REM
77 Value *TrapFn = Intrinsic::getDeclaration(F.getParent(),
78 Intrinsic::trap);
79 CallInst::Create(TrapFn, "", DivInst)->setDebugLoc(dl);
80 }
81 continue;
82 }
83 // Create a trap block.
84 BasicBlock *TrapBlock = CreateTrapBlock(F, dl);
85 // Move instructions in BB from DivInst to BB's end to a new block.
86 BasicBlock *Successor = BB->splitBasicBlock(BI, "guarded.divrem");
87 // Remove the unconditional branch inserted by splitBasicBlock.
88 BB->getTerminator()->eraseFromParent();
89 // Remember that DivInst was already processed, so that when we process
90 // inserted blocks later, we do not attempt to again guard it.
91 GuardedDivs.insert(DivInst);
92 // Compare the denominator with zero.
93 Value *Zero = ConstantInt::get(Denominator->getType(), 0);
94 Value *DenomIsZero = new ICmpInst(*BB, ICmpInst::ICMP_EQ, Denominator,
95 Zero, "");
96 // Put in a condbranch to the trap block.
97 BranchInst::Create(TrapBlock, Successor, DenomIsZero, BB);
98 // BI is invalidated when we split. Stop the BasicBlock iterator.
99 break;
100 }
101 }
102
103 return false;
104 }
105
106 char InsertDivideCheck::ID = 0;
107 INITIALIZE_PASS(InsertDivideCheck, "insert-divide-check",
108 "Insert divide by zero checks", false, false)
109
110 FunctionPass *llvm::createInsertDivideCheckPass() {
111 return new InsertDivideCheck();
112 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698