[llvm] [InstCombine] Preserve NSW flags for neg instructions (PR #72548)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 16 10:14:02 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Yingwei Zheng (dtcxzyw)
<details>
<summary>Changes</summary>
Alive2: https://alive2.llvm.org/ce/z/F9HG3M
This missed optimization is discovered with the help of https://github.com/AliveToolkit/alive2/pull/962.
---
Full diff: https://github.com/llvm/llvm-project/pull/72548.diff
3 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (+2-2)
- (modified) llvm/test/Transforms/InstCombine/div.ll (+8-8)
- (modified) llvm/test/Transforms/InstCombine/sdiv-exact-by-negative-power-of-two.ll (+3-3)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index d6fac88a39d01be..40156726c7038b9 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 844b35723b135c9..cd17d10d0e1de07 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 81f22bb3c6646f7..3451c5e626f308b 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
``````````
</details>
https://github.com/llvm/llvm-project/pull/72548
More information about the llvm-commits
mailing list