diff options
author | Chris Lattner <sabre@nondot.org> | 2011-05-22 18:18:41 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2011-05-22 18:18:41 +0000 |
commit | 7c99f19d9f5919dd4809aa5a5c84f5ff7807aafd (patch) | |
tree | 1829d813a8d7fe63cc5f658ea93321410f91f65f /llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | |
parent | a0c9c75df216feb7299f2be6157c44b322573474 (diff) | |
download | bcm5719-llvm-7c99f19d9f5919dd4809aa5a5c84f5ff7807aafd.tar.gz bcm5719-llvm-7c99f19d9f5919dd4809aa5a5c84f5ff7807aafd.zip |
Carve out a place in instcombine to put transformations which work knowing that their
result is non-zero. Implement an example optimization (PR9814), which allows us to
transform:
A / ((1 << B) >>u 2)
into:
A >>u (B-2)
which we compile into:
_divu3: ## @divu3
leal -2(%rsi), %ecx
shrl %cl, %edi
movl %edi, %eax
ret
instead of:
_divu3: ## @divu3
movb %sil, %cl
movl $1, %esi
shll %cl, %esi
shrl $2, %esi
movl %edi, %eax
xorl %edx, %edx
divl %esi, %eax
ret
llvm-svn: 131860
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index c4dee6a6f00..c96741aacd2 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -19,6 +19,31 @@ using namespace llvm; using namespace PatternMatch; + +/// simplifyValueKnownNonZero - The specific integer value is used in a context +/// where it is known to be non-zero. If this allows us to simplify the +/// computation, do so and return the new operand, otherwise return null. +static Value *simplifyValueKnownNonZero(Value *V, InstCombiner &IC) { + // If V has multiple uses, then we would have to do more analysis to determine + // if this is safe. For example, the use could be in dynamically unreached + // code. + if (!V->hasOneUse()) return 0; + + // ((1 << A) >>u B) --> (1 << (A-B)) + // Because V cannot be zero, we know that B is less than A. + Value *A = 0, *B = 0; ConstantInt *One = 0; + if (match(V, m_LShr(m_OneUse(m_Shl(m_ConstantInt(One), m_Value(A))), + m_Value(B))) && + // The "1" can be any value known to be a power of 2. + One->getValue().isPowerOf2()) { + A = IC.Builder->CreateSub(A, B, "tmp"); + return IC.Builder->CreateShl(One, A); + } + + return 0; +} + + /// MultiplyOverflows - True if the multiply can not be expressed in an int /// this size. static bool MultiplyOverflows(ConstantInt *C1, ConstantInt *C2, bool sign) { @@ -293,6 +318,12 @@ bool InstCombiner::SimplifyDivRemOfSelect(BinaryOperator &I) { Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + // The RHS is known non-zero. + if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this)) { + I.setOperand(1, V); + return &I; + } + // Handle cases involving: [su]div X, (select Cond, Y, Z) // This does not apply for fdiv. if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I)) @@ -499,6 +530,12 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + // The RHS is known non-zero. + if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this)) { + I.setOperand(1, V); + return &I; + } + // Handle cases involving: rem X, (select Cond, Y, Z) if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I)) return &I; |