diff options
author | Yingwei Zheng <dtcxzyw2333@gmail.com> | 2023-11-17 14:02:47 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-17 14:02:47 +0800 |
commit | 865c1fda6f3e258b47a4f7992bb19ca2e9edcfa1 (patch) | |
tree | eabe757c8c51468016e38d14c5e80bd2e07ce8b7 | |
parent | 5353d3f509814a44093a61c2725fdfe7273aa25a (diff) | |
download | llvm-865c1fda6f3e258b47a4f7992bb19ca2e9edcfa1.zip llvm-865c1fda6f3e258b47a4f7992bb19ca2e9edcfa1.tar.gz llvm-865c1fda6f3e258b47a4f7992bb19ca2e9edcfa1.tar.bz2 |
[InstCombine] Preserve NSW flags for neg instructions (#72548)
Alive2: https://alive2.llvm.org/ce/z/F9HG3M
This missed optimization is discovered with the help of
https://github.com/AliveToolkit/alive2/pull/962.
3 files changed, 13 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index d6fac88..4015672 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1433,7 +1433,7 @@ Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) { // sdiv Op0, (sext i1 X) --> -Op0 (because if X is 0, the op is undefined) if (match(Op1, m_AllOnes()) || (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))) - return BinaryOperator::CreateNeg(Op0); + return BinaryOperator::CreateNSWNeg(Op0); // X / INT_MIN --> X == INT_MIN if (match(Op1, m_SignMask())) @@ -1456,7 +1456,7 @@ Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) { Constant *NegPow2C = ConstantExpr::getNeg(cast<Constant>(Op1)); Constant *C = ConstantExpr::getExactLogBase2(NegPow2C); Value *Ashr = Builder.CreateAShr(Op0, C, I.getName() + ".neg", true); - return BinaryOperator::CreateNeg(Ashr); + return BinaryOperator::CreateNSWNeg(Ashr); } } diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll index 844b357..cd17d10 100644 --- a/llvm/test/Transforms/InstCombine/div.ll +++ b/llvm/test/Transforms/InstCombine/div.ll @@ -22,7 +22,7 @@ define i32 @test2(i32 %A) { define i32 @sdiv_by_minus1(i32 %A) { ; CHECK-LABEL: @sdiv_by_minus1( -; CHECK-NEXT: [[B:%.*]] = sub i32 0, [[A:%.*]] +; CHECK-NEXT: [[B:%.*]] = sub nsw i32 0, [[A:%.*]] ; CHECK-NEXT: ret i32 [[B]] ; %B = sdiv i32 %A, -1 @@ -31,7 +31,7 @@ define i32 @sdiv_by_minus1(i32 %A) { define <2 x i64> @sdiv_by_minus1_vec(<2 x i64> %x) { ; CHECK-LABEL: @sdiv_by_minus1_vec( -; CHECK-NEXT: [[DIV:%.*]] = sub <2 x i64> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[DIV:%.*]] = sub nsw <2 x i64> zeroinitializer, [[X:%.*]] ; CHECK-NEXT: ret <2 x i64> [[DIV]] ; %div = sdiv <2 x i64> %x, <i64 -1, i64 -1> @@ -48,7 +48,7 @@ define <2 x i64> @sdiv_by_minus1_vec_poison_elt(<2 x i64> %x) { define i32 @sdiv_by_sext_minus1(i1 %x, i32 %y) { ; CHECK-LABEL: @sdiv_by_sext_minus1( -; CHECK-NEXT: [[DIV:%.*]] = sub i32 0, [[Y:%.*]] +; CHECK-NEXT: [[DIV:%.*]] = sub nsw i32 0, [[Y:%.*]] ; CHECK-NEXT: ret i32 [[DIV]] ; %sext = sext i1 %x to i32 @@ -58,7 +58,7 @@ define i32 @sdiv_by_sext_minus1(i1 %x, i32 %y) { define <2 x i32> @sdiv_by_sext_minus1_vec(<2 x i1> %x, <2 x i32> %y) { ; CHECK-LABEL: @sdiv_by_sext_minus1_vec( -; CHECK-NEXT: [[DIV:%.*]] = sub <2 x i32> zeroinitializer, [[Y:%.*]] +; CHECK-NEXT: [[DIV:%.*]] = sub nsw <2 x i32> zeroinitializer, [[Y:%.*]] ; CHECK-NEXT: ret <2 x i32> [[DIV]] ; %sext = sext <2 x i1> %x to <2 x i32> @@ -1308,8 +1308,8 @@ define i32 @udiv_select_of_constants_divisor(i1 %b, i32 %x) { define i1 @sdiv_one_icmpeq_one(i32 %x) { ; CHECK-LABEL: @sdiv_one_icmpeq_one( ; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[X_FR]], 1 -; CHECK-NEXT: ret i1 [[B]] +; CHECK-NEXT: [[B1:%.*]] = icmp eq i32 [[X_FR]], 1 +; CHECK-NEXT: ret i1 [[B1]] ; %A = sdiv i32 1, %x %B = icmp eq i32 %A, 1 @@ -1319,8 +1319,8 @@ define i1 @sdiv_one_icmpeq_one(i32 %x) { define i1 @sdiv_one_icmpeq_negone(i32 %x) { ; CHECK-LABEL: @sdiv_one_icmpeq_negone( ; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[X_FR]], -1 -; CHECK-NEXT: ret i1 [[B]] +; CHECK-NEXT: [[B1:%.*]] = icmp eq i32 [[X_FR]], -1 +; CHECK-NEXT: ret i1 [[B1]] ; %A = sdiv i32 1, %x %B = icmp eq i32 %A, -1 diff --git a/llvm/test/Transforms/InstCombine/sdiv-exact-by-negative-power-of-two.ll b/llvm/test/Transforms/InstCombine/sdiv-exact-by-negative-power-of-two.ll index 81f22bb..3451c5e 100644 --- a/llvm/test/Transforms/InstCombine/sdiv-exact-by-negative-power-of-two.ll +++ b/llvm/test/Transforms/InstCombine/sdiv-exact-by-negative-power-of-two.ll @@ -38,7 +38,7 @@ define <2 x i8> @t2_vec_splat(<2 x i8> %x) { define <2 x i8> @t3_vec(<2 x i8> %x) { ; CHECK-LABEL: @t3_vec( ; CHECK-NEXT: [[DIV_NEG:%.*]] = ashr exact <2 x i8> [[X:%.*]], <i8 5, i8 4> -; CHECK-NEXT: [[DIV:%.*]] = sub <2 x i8> zeroinitializer, [[DIV_NEG]] +; CHECK-NEXT: [[DIV:%.*]] = sub nsw <2 x i8> zeroinitializer, [[DIV_NEG]] ; CHECK-NEXT: ret <2 x i8> [[DIV]] ; %div = sdiv exact <2 x i8> %x, <i8 -32, i8 -16> @@ -76,8 +76,8 @@ define i8 @prove_exact_with_high_mask(i8 %x, i8 %y) { define i8 @prove_exact_with_high_mask_limit(i8 %x, i8 %y) { ; CHECK-LABEL: @prove_exact_with_high_mask_limit( -; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 5 -; CHECK-NEXT: [[D:%.*]] = sub nsw i8 0, [[A]] +; CHECK-NEXT: [[D_NEG:%.*]] = ashr i8 [[X:%.*]], 5 +; CHECK-NEXT: [[D:%.*]] = sub nsw i8 0, [[D_NEG]] ; CHECK-NEXT: ret i8 [[D]] ; %a = and i8 %x, -32 |