From 7a2949647a3c6bbeebe439a078d66b986e12fce2 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Tue, 12 Oct 2021 12:18:29 -0400 Subject: [PATCH] [InstCombine] propagate no-wrap flag through select-of-mul fold This may not be obvious, but Alive2 agrees: https://alive2.llvm.org/ce/z/Ld9qNT If the mul has "nsw", then -1 * INT_MIN is poison, so the negate can also have "nsw" because 0 - INT_MIN is poison. If the mul has "nuw", then that means the "OtherOp" can only be 0 or 1 (anything else multiplied by 0xfff... would wrap). So the replacement negate must be "nsw" because it is either "0-0" or "0-1". This is another regression noticed with a planned follow-up to D111410. --- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 15 ++++++++++----- llvm/test/Transforms/InstCombine/mul-inseltpoison.ll | 8 ++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 0f96377..779d298 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -107,14 +107,19 @@ static Value *foldMulSelectToNegate(BinaryOperator &I, // mul (select Cond, 1, -1), OtherOp --> select Cond, OtherOp, -OtherOp // mul OtherOp, (select Cond, 1, -1) --> select Cond, OtherOp, -OtherOp if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_One(), m_AllOnes())), - m_Value(OtherOp)))) - return Builder.CreateSelect(Cond, OtherOp, Builder.CreateNeg(OtherOp)); - + m_Value(OtherOp)))) { + bool HasAnyNoWrap = I.hasNoSignedWrap() || I.hasNoUnsignedWrap(); + Value *Neg = Builder.CreateNeg(OtherOp, "", false, HasAnyNoWrap); + return Builder.CreateSelect(Cond, OtherOp, Neg); + } // mul (select Cond, -1, 1), OtherOp --> select Cond, -OtherOp, OtherOp // mul OtherOp, (select Cond, -1, 1) --> select Cond, -OtherOp, OtherOp if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_AllOnes(), m_One())), - m_Value(OtherOp)))) - return Builder.CreateSelect(Cond, Builder.CreateNeg(OtherOp), OtherOp); + m_Value(OtherOp)))) { + bool HasAnyNoWrap = I.hasNoSignedWrap() || I.hasNoUnsignedWrap(); + Value *Neg = Builder.CreateNeg(OtherOp, "", false, HasAnyNoWrap); + return Builder.CreateSelect(Cond, Neg, OtherOp); + } // fmul (select Cond, 1.0, -1.0), OtherOp --> select Cond, OtherOp, -OtherOp // fmul OtherOp, (select Cond, 1.0, -1.0) --> select Cond, OtherOp, -OtherOp diff --git a/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll b/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll index 5c66ea0..7d2038e 100644 --- a/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll +++ b/llvm/test/Transforms/InstCombine/mul-inseltpoison.ll @@ -720,7 +720,7 @@ define i32 @negate_if_false(i32 %x, i1 %cond) { define i32 @negate_if_true_nsw(i32 %x, i1 %cond) { ; CHECK-LABEL: @negate_if_true_nsw( -; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[X:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[X]] ; CHECK-NEXT: ret i32 [[TMP2]] ; @@ -731,7 +731,7 @@ define i32 @negate_if_true_nsw(i32 %x, i1 %cond) { define i32 @negate_if_true_nuw(i32 %x, i1 %cond) { ; CHECK-LABEL: @negate_if_true_nuw( -; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[X:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[X]] ; CHECK-NEXT: ret i32 [[TMP2]] ; @@ -742,7 +742,7 @@ define i32 @negate_if_true_nuw(i32 %x, i1 %cond) { define i32 @negate_if_false_nsw(i32 %x, i1 %cond) { ; CHECK-LABEL: @negate_if_false_nsw( -; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[X:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[COND:%.*]], i32 [[X]], i32 [[TMP1]] ; CHECK-NEXT: ret i32 [[TMP2]] ; @@ -753,7 +753,7 @@ define i32 @negate_if_false_nsw(i32 %x, i1 %cond) { define i32 @negate_if_false_nuw(i32 %x, i1 %cond) { ; CHECK-LABEL: @negate_if_false_nuw( -; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i32 0, [[X:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[COND:%.*]], i32 [[X]], i32 [[TMP1]] ; CHECK-NEXT: ret i32 [[TMP2]] ; -- 2.7.4