[llvm] r219634 - InstCombine: Don't miscompile (x lshr C1) udiv C2
Bob Wilson
bob.wilson at apple.com
Wed Oct 15 09:10:30 PDT 2014
Are you talking about a performance regression or a correctness problem?
> On Oct 14, 2014, at 5:48 AM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
>
> This has regressed on our internal build, I'll send you the details off the list.
>
> 2014-10-14 1:48 GMT+04:00 David Majnemer <david.majnemer at gmail.com <mailto:david.majnemer at gmail.com>>:
> Author: majnemer
> Date: Mon Oct 13 16:48:30 2014
> New Revision: 219634
>
> URL: http://llvm.org/viewvc/llvm-project?rev=219634&view=rev <http://llvm.org/viewvc/llvm-project?rev=219634&view=rev>
> Log:
> 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.
>
> Modified:
> llvm/trunk/include/llvm/ADT/APInt.h
> llvm/trunk/lib/Support/APInt.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
> llvm/trunk/test/Transforms/InstCombine/div.ll
>
> Modified: llvm/trunk/include/llvm/ADT/APInt.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=219634&r1=219633&r2=219634&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=219634&r1=219633&r2=219634&view=diff>
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/APInt.h (original)
> +++ llvm/trunk/include/llvm/ADT/APInt.h Mon Oct 13 16:48:30 2014
> @@ -945,7 +945,8 @@ public:
> APInt sdiv_ov(const APInt &RHS, bool &Overflow) const;
> APInt smul_ov(const APInt &RHS, bool &Overflow) const;
> APInt umul_ov(const APInt &RHS, bool &Overflow) const;
> - APInt sshl_ov(unsigned Amt, bool &Overflow) const;
> + APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
> + APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
>
> /// \brief Array-indexing support.
> ///
>
> Modified: llvm/trunk/lib/Support/APInt.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=219634&r1=219633&r2=219634&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=219634&r1=219633&r2=219634&view=diff>
> ==============================================================================
> --- llvm/trunk/lib/Support/APInt.cpp (original)
> +++ llvm/trunk/lib/Support/APInt.cpp Mon Oct 13 16:48:30 2014
> @@ -2064,19 +2064,29 @@ APInt APInt::umul_ov(const APInt &RHS, b
> return Res;
> }
>
> -APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const {
> - Overflow = ShAmt >= getBitWidth();
> +APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const {
> + Overflow = ShAmt.uge(getBitWidth());
> if (Overflow)
> - ShAmt = getBitWidth()-1;
> + return APInt(BitWidth, 0);
>
> if (isNonNegative()) // Don't allow sign change.
> - Overflow = ShAmt >= countLeadingZeros();
> + Overflow = ShAmt.uge(countLeadingZeros());
> else
> - Overflow = ShAmt >= countLeadingOnes();
> + Overflow = ShAmt.uge(countLeadingOnes());
>
> return *this << ShAmt;
> }
>
> +APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const {
> + Overflow = ShAmt.uge(getBitWidth());
> + if (Overflow)
> + return APInt(BitWidth, 0);
> +
> + Overflow = ShAmt.ugt(countLeadingZeros());
> +
> + return *this << ShAmt;
> +}
> +
>
>
>
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=219634&r1=219633&r2=219634&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=219634&r1=219633&r2=219634&view=diff>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Mon Oct 13 16:48:30 2014
> @@ -965,11 +965,17 @@ Instruction *InstCombiner::visitUDiv(Bin
> 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)
>
> Modified: llvm/trunk/test/Transforms/InstCombine/div.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/div.ll?rev=219634&r1=219633&r2=219634&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/div.ll?rev=219634&r1=219633&r2=219634&view=diff>
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstCombine/div.ll (original)
> +++ llvm/trunk/test/Transforms/InstCombine/div.ll Mon Oct 13 16:48:30 2014
> @@ -132,11 +132,11 @@ define i32 @test15(i32 %a, i32 %b) nounw
> }
>
> define <2 x i64> @test16(<2 x i64> %x) nounwind {
> - %shr = lshr <2 x i64> %x, <i64 3, i64 5>
> - %div = udiv <2 x i64> %shr, <i64 4, i64 6>
> + %shr = lshr <2 x i64> %x, <i64 5, i64 5>
> + %div = udiv <2 x i64> %shr, <i64 6, i64 6>
> ret <2 x i64> %div
> ; CHECK-LABEL: @test16(
> -; CHECK-NEXT: udiv <2 x i64> %x, <i64 32, i64 192>
> +; CHECK-NEXT: udiv <2 x i64> %x, <i64 192, i64 192>
> ; CHECK-NEXT: ret <2 x i64>
> }
>
> @@ -264,3 +264,13 @@ define i32 @test30(i32 %a) {
> ; CHECK-LABEL: @test30(
> ; CHECK-NEXT: ret i32 %a
> }
> +
> +define <2 x i32> @test31(<2 x i32> %x) nounwind {
> + %shr = lshr <2 x i32> %x, <i32 31, i32 31>
> + %div = udiv <2 x i32> %shr, <i32 2147483647, i32 2147483647>
> + ret <2 x i32> %div
> +; CHECK-LABEL: @test31(
> +; CHECK-NEXT: %[[shr:.*]] = lshr <2 x i32> %x, <i32 31, i32 31>
> +; CHECK-NEXT: udiv <2 x i32> %[[shr]], <i32 2147483647, i32 2147483647>
> +; CHECK-NEXT: ret <2 x i32>
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu <mailto:llvm-commits at cs.uiuc.edu>
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits <http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141015/01a5ea62/attachment.html>
More information about the llvm-commits
mailing list