diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Utils/BypassSlowDivision.cpp')
-rw-r--r-- | contrib/llvm/lib/Transforms/Utils/BypassSlowDivision.cpp | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/contrib/llvm/lib/Transforms/Utils/BypassSlowDivision.cpp b/contrib/llvm/lib/Transforms/Utils/BypassSlowDivision.cpp index 42287d3..bc2cef2 100644 --- a/contrib/llvm/lib/Transforms/Utils/BypassSlowDivision.cpp +++ b/contrib/llvm/lib/Transforms/Utils/BypassSlowDivision.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" +#include "llvm/Transforms/Utils/Local.h" using namespace llvm; @@ -82,13 +83,17 @@ static bool insertFastDiv(Instruction *I, IntegerType *BypassType, Value *Dividend = I->getOperand(0); Value *Divisor = I->getOperand(1); - if (isa<ConstantInt>(Divisor) || - (isa<ConstantInt>(Dividend) && isa<ConstantInt>(Divisor))) { - // Operations with immediate values should have - // been solved and replaced during compile time. + if (isa<ConstantInt>(Divisor)) { + // Division by a constant should have been been solved and replaced earlier + // in the pipeline. return false; } + // If the numerator is a constant, bail if it doesn't fit into BypassType. + if (ConstantInt *ConstDividend = dyn_cast<ConstantInt>(Dividend)) + if (ConstDividend->getValue().getActiveBits() > BypassType->getBitWidth()) + return false; + // Basic Block is split before divide BasicBlock *MainBB = &*I->getParent(); BasicBlock *SuccessorBB = MainBB->splitBasicBlock(I); @@ -120,8 +125,7 @@ static bool insertFastDiv(Instruction *I, IntegerType *BypassType, BypassType); // udiv/urem because optimization only handles positive numbers - Value *ShortQuotientV = FastBuilder.CreateExactUDiv(ShortDividendV, - ShortDivisorV); + Value *ShortQuotientV = FastBuilder.CreateUDiv(ShortDividendV, ShortDivisorV); Value *ShortRemainderV = FastBuilder.CreateURem(ShortDividendV, ShortDivisorV); Value *FastQuotientV = FastBuilder.CreateCast(Instruction::ZExt, @@ -151,7 +155,17 @@ static bool insertFastDiv(Instruction *I, IntegerType *BypassType, // Combine operands into a single value with OR for value testing below MainBB->getInstList().back().eraseFromParent(); IRBuilder<> MainBuilder(MainBB, MainBB->end()); - Value *OrV = MainBuilder.CreateOr(Dividend, Divisor); + + // We should have bailed out above if the divisor is a constant, but the + // dividend may still be a constant. Set OrV to our non-constant operands + // OR'ed together. + assert(!isa<ConstantInt>(Divisor)); + + Value *OrV; + if (!isa<ConstantInt>(Dividend)) + OrV = MainBuilder.CreateOr(Dividend, Divisor); + else + OrV = Divisor; // BitMask is inverted to check if the operands are // larger than the bypass type @@ -247,5 +261,12 @@ bool llvm::bypassSlowDivision( MadeChange |= reuseOrInsertFastDiv(I, BT, UseDivOp, UseSignedOp, DivCache); } + // Above we eagerly create divs and rems, as pairs, so that we can efficiently + // create divrem machine instructions. Now erase any unused divs / rems so we + // don't leave extra instructions sitting around. + for (auto &KV : DivCache) + for (Instruction *Phi : {KV.second.Quotient, KV.second.Remainder}) + RecursivelyDeleteTriviallyDeadInstructions(Phi); + return MadeChange; } |