diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-10-13 21:48:30 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-10-13 21:48:30 +0000 |
commit | a252138942d8d48eb31234e0da09d3d97cb6abad (patch) | |
tree | eaabf3357117fd540cd950b358b119366ae26c27 /llvm/lib/Transforms | |
parent | a562b46db736bdaa74e7c52a1eb7415561613836 (diff) | |
download | bcm5719-llvm-a252138942d8d48eb31234e0da09d3d97cb6abad.tar.gz bcm5719-llvm-a252138942d8d48eb31234e0da09d3d97cb6abad.zip |
InstCombine: Don't miscompile (x lshr C1) udiv C2
We have a transform that changes:
(x lshr C1) udiv C2
into:
x udiv (C2 << C1)
However, it is unsafe to do so if C2 << C1 discards any of C2's bits.
This fixes PR21255.
llvm-svn: 219634
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index dad2c2d256d..846a3640930 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -965,11 +965,17 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) { return Common; // (x lshr C1) udiv C2 --> x udiv (C2 << C1) - if (Constant *C2 = dyn_cast<Constant>(Op1)) { + { Value *X; - Constant *C1; - if (match(Op0, m_LShr(m_Value(X), m_Constant(C1)))) - return BinaryOperator::CreateUDiv(X, ConstantExpr::getShl(C2, C1)); + const APInt *C1, *C2; + if (match(Op0, m_LShr(m_Value(X), m_APInt(C1))) && + match(Op1, m_APInt(C2))) { + bool Overflow; + APInt C2ShlC1 = C2->ushl_ov(*C1, Overflow); + if (!Overflow) + return BinaryOperator::CreateUDiv( + X, ConstantInt::get(X->getType(), C2ShlC1)); + } } // (zext A) udiv (zext B) --> zext (A udiv B) |