[llvm] [InstCombine] simplify `(X * C0) / (X * C1)` into `C0 / C1`. (PR #73204)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 26 22:14:31 PST 2023
https://github.com/Z572 updated https://github.com/llvm/llvm-project/pull/73204
>From 6a4b73675ea03e85ff2ba1f46620b9f2da8a0381 Mon Sep 17 00:00:00 2001
From: Zheng Junjie <zhengjunjie at iscas.ac.cn>
Date: Thu, 23 Nov 2023 11:30:54 +0800
Subject: [PATCH 1/3] [InstCombine] Simplify `(X * C0) / (X * C1)` into `C0 /
C1`.
proof: https://alive2.llvm.org/ce/z/IIEKgf
---
.../InstCombine/InstCombineMulDivRem.cpp | 12 +++
llvm/test/Transforms/InstCombine/div.ll | 93 +++++++++++++++++++
2 files changed, 105 insertions(+)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 40156726c7038b9..0032422cd3ce7c7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1207,6 +1207,18 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
}
}
+ // (X * C0) / (X * C1) --> C0 / C1
+ Constant *C0, *C1;
+ if (match(Op0, m_c_Mul(m_Value(X), m_Constant(C0))) &&
+ match(Op1, m_c_Mul(m_Specific(X), m_Constant(C1)))) {
+ auto OB0HasNSW = cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap();
+ auto OB0HasNUW = cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap();
+ if ((IsSigned && OB0HasNSW) || (!IsSigned && OB0HasNUW)) {
+ replaceOperand(I, 0, C0);
+ replaceOperand(I, 1, C1);
+ return &I;
+ };
+ }
return nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index cd17d10d0e1de07..2fb4873c72f5832 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -1432,6 +1432,99 @@ define <2 x i8> @sdiv_sdiv_mul_nsw(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
ret <2 x i8> %r
}
+; (X * C0) / (X * C1) --> C0 / C1
+define i8 @sdiv_mul_nsw_mul(i8 %x) {
+; CHECK-LABEL: @sdiv_mul_nsw_mul(
+; CHECK-NEXT: ret i8 2
+;
+ %add4 = mul i8 %x, 6
+ %add5 = mul nsw i8 %x, 12
+ %div = sdiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @sdiv_mul_nsw_mul_nsw(i8 %x) {
+; CHECK-LABEL: @sdiv_mul_nsw_mul_nsw(
+; CHECK-NEXT: ret i8 2
+;
+ %add4 = mul nsw i8 %x, 5
+ %add5 = mul nsw i8 %x, 10
+ %div = sdiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @sdiv_mul_mul_nsw(i8 %x) {
+; CHECK-LABEL: @sdiv_mul_mul_nsw(
+; CHECK-NEXT: [[ADD4:%.*]] = mul nsw i8 [[X:%.*]], 10
+; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], 20
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul nsw i8 %x, 10
+ %add5 = mul i8 %x, 20
+ %div = sdiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @sdiv_mul_mul(i8 %x) {
+; CHECK-LABEL: @sdiv_mul_mul(
+; CHECK-NEXT: [[ADD4:%.*]] = mul i8 [[X:%.*]], 10
+; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], 20
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul i8 %x, 10
+ %add5 = mul i8 %x, 20
+ %div = sdiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @udiv_mul_mul(i8 %x) {
+; CHECK-LABEL: @udiv_mul_mul(
+; CHECK-NEXT: [[ADD4:%.*]] = mul i8 [[X:%.*]], 10
+; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], 20
+; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul i8 %x, 10
+ %add5 = mul i8 %x, 20
+ %div = udiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @udiv_mul_nuw_mul_nuw(i8 %x) {
+; CHECK-LABEL: @udiv_mul_nuw_mul_nuw(
+; CHECK-NEXT: ret i8 1
+;
+ %add4 = mul nuw i8 %x, 10
+ %add5 = mul nuw i8 %x, 10
+ %div = udiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @udiv_mul_mul_nuw(i8 %x) {
+; CHECK-LABEL: @udiv_mul_mul_nuw(
+; CHECK-NEXT: [[ADD4:%.*]] = mul nuw i8 [[X:%.*]], 10
+; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], 20
+; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul nuw i8 %x, 10
+ %add5 = mul i8 %x, 20
+ %div = udiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @udiv_mul_nuw_mul(i8 %x) {
+; CHECK-LABEL: @udiv_mul_nuw_mul(
+; CHECK-NEXT: ret i8 2
+;
+ %add4 = mul i8 %x, 10
+ %add5 = mul nuw i8 %x, 20
+ %div = udiv i8 %add5, %add4
+ ret i8 %div
+}
+
define i32 @sdiv_sub1(i32 %arg) {
; CHECK-LABEL: @sdiv_sub1(
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG:%.*]], -2147483648
>From 1f11ac9597330b8202cc4c372ac345c2fe8db8d1 Mon Sep 17 00:00:00 2001
From: Zheng Junjie <zhengjunjie at iscas.ac.cn>
Date: Fri, 24 Nov 2023 13:07:51 +0800
Subject: [PATCH 2/3] fixup! [InstCombine] Simplify `(X * C0) / (X * C1)` into
`C0 / C1`.
---
.../InstCombine/InstCombineMulDivRem.cpp | 55 +++++---
llvm/test/Transforms/InstCombine/div.ll | 132 ++++++++++++++++--
2 files changed, 151 insertions(+), 36 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 0032422cd3ce7c7..76f822c3b2e10f9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1207,17 +1207,43 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
}
}
- // (X * C0) / (X * C1) --> C0 / C1
- Constant *C0, *C1;
- if (match(Op0, m_c_Mul(m_Value(X), m_Constant(C0))) &&
- match(Op1, m_c_Mul(m_Specific(X), m_Constant(C1)))) {
+ // (X * Y) / (X * Z) --> Y / X (and commuted variants)
+ if (match(Op0, m_Mul(m_Value(X), m_Value(Y)))) {
auto OB0HasNSW = cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap();
auto OB0HasNUW = cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap();
- if ((IsSigned && OB0HasNSW) || (!IsSigned && OB0HasNUW)) {
- replaceOperand(I, 0, C0);
- replaceOperand(I, 1, C1);
- return &I;
+
+ auto CreateDivOrNull = [&](Value *A) -> Instruction * {
+ auto OB1HasNSW = cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap();
+ auto OB1HasNUW =
+ cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap();
+
+ // if (IsSigned && OB0HasNSW && OB1HasNSW) {
+ // return BinaryOperator::CreateSDiv(A, Z);
+ // }
+ if (!IsSigned && OB0HasNUW && OB1HasNUW) {
+ return BinaryOperator::CreateUDiv(A, Z);
+ };
+ if (isa<Constant>(A) && isa<Constant>(Z)) {
+ if (IsSigned && OB0HasNSW) {
+ return BinaryOperator::CreateSDiv(A, Z);
+ }
+ if (!IsSigned && OB0HasNUW) {
+ return BinaryOperator::CreateUDiv(A, Z);
+ };
+ };
+ return nullptr;
};
+
+ if (match(Op1, m_c_Mul(m_Specific(X), m_Value(Z)))) {
+ auto *Val = CreateDivOrNull(Y);
+ if (Val)
+ return Val;
+ };
+ if (match(Op1, m_c_Mul(m_Specific(Y), m_Value(Z)))) {
+ auto *Val = CreateDivOrNull(X);
+ if (Val)
+ return Val;
+ }
}
return nullptr;
}
@@ -1389,20 +1415,7 @@ Instruction *InstCombinerImpl::visitUDiv(BinaryOperator &I) {
if (Instruction *NarrowDiv = narrowUDivURem(I, *this))
return NarrowDiv;
- // If the udiv operands are non-overflowing multiplies with a common operand,
- // then eliminate the common factor:
- // (A * B) / (A * X) --> B / X (and commuted variants)
- // TODO: The code would be reduced if we had m_c_NUWMul pattern matching.
- // TODO: If -reassociation handled this generally, we could remove this.
Value *A, *B;
- if (match(Op0, m_NUWMul(m_Value(A), m_Value(B)))) {
- if (match(Op1, m_NUWMul(m_Specific(A), m_Value(X))) ||
- match(Op1, m_NUWMul(m_Value(X), m_Specific(A))))
- return BinaryOperator::CreateUDiv(B, X);
- if (match(Op1, m_NUWMul(m_Specific(B), m_Value(X))) ||
- match(Op1, m_NUWMul(m_Value(X), m_Specific(B))))
- return BinaryOperator::CreateUDiv(A, X);
- }
// Look through a right-shift to find the common factor:
// ((Op1 *nuw A) >> B) / Op1 --> A >> B
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index 2fb4873c72f5832..cd4a09e7f4dedb9 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -1433,8 +1433,110 @@ define <2 x i8> @sdiv_sdiv_mul_nsw(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
}
; (X * C0) / (X * C1) --> C0 / C1
-define i8 @sdiv_mul_nsw_mul(i8 %x) {
+define i8 @sdiv_mul_nsw_mul(i8 %x,i8 %y,i8 %z) {
; CHECK-LABEL: @sdiv_mul_nsw_mul(
+; CHECK-NEXT: [[ADD4:%.*]] = mul i8 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[ADD5:%.*]] = mul nsw i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul i8 %x, %z
+ %add5 = mul nsw i8 %x, %y
+ %div = sdiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @sdiv_mul_nsw_mul_nsw(i8 %x,i8 %y,i8 %z) {
+; CHECK-LABEL: @sdiv_mul_nsw_mul_nsw(
+; CHECK-NEXT: [[ADD4:%.*]] = mul nsw i8 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[ADD5:%.*]] = mul nsw i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul nsw i8 %x, %z
+ %add5 = mul nsw i8 %x, %y
+ %div = sdiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @sdiv_mul_mul_nsw(i8 %x,i8 %y,i8 %z) {
+; CHECK-LABEL: @sdiv_mul_mul_nsw(
+; CHECK-NEXT: [[ADD4:%.*]] = mul nsw i8 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul nsw i8 %x, %z
+ %add5 = mul i8 %x, %y
+ %div = sdiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @sdiv_mul_mul(i8 %x,i8 %y,i8 %z) {
+; CHECK-LABEL: @sdiv_mul_mul(
+; CHECK-NEXT: [[ADD4:%.*]] = mul i8 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul i8 %x, %z
+ %add5 = mul i8 %x, %y
+ %div = sdiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @udiv_mul_mul(i8 %x,i8 %y,i8 %z) {
+; CHECK-LABEL: @udiv_mul_mul(
+; CHECK-NEXT: [[ADD4:%.*]] = mul i8 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul i8 %x, %z
+ %add5 = mul i8 %x, %y
+ %div = udiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @udiv_mul_nuw_mul_nuw(i8 %x,i8 %y,i8 %z) {
+; CHECK-LABEL: @udiv_mul_nuw_mul_nuw(
+; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul nuw i8 %x, %z
+ %add5 = mul nuw i8 %x, %y
+ %div = udiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @udiv_mul_mul_nuw(i8 %x,i8 %y,i8 %z) {
+; CHECK-LABEL: @udiv_mul_mul_nuw(
+; CHECK-NEXT: [[ADD4:%.*]] = mul nuw i8 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul nuw i8 %x, %z
+ %add5 = mul i8 %x, %y
+ %div = udiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @udiv_mul_nuw_mul(i8 %x,i8 %y,i8 %z) {
+; CHECK-LABEL: @udiv_mul_nuw_mul(
+; CHECK-NEXT: [[ADD4:%.*]] = mul i8 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[ADD5:%.*]] = mul nuw i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i8 [[DIV]]
+;
+ %add4 = mul i8 %x, %z
+ %add5 = mul nuw i8 %x, %y
+ %div = udiv i8 %add5, %add4
+ ret i8 %div
+}
+
+define i8 @sdiv_mul_nsw_constant_mul_constant(i8 %x) {
+; CHECK-LABEL: @sdiv_mul_nsw_constant_mul_constant(
; CHECK-NEXT: ret i8 2
;
%add4 = mul i8 %x, 6
@@ -1443,8 +1545,8 @@ define i8 @sdiv_mul_nsw_mul(i8 %x) {
ret i8 %div
}
-define i8 @sdiv_mul_nsw_mul_nsw(i8 %x) {
-; CHECK-LABEL: @sdiv_mul_nsw_mul_nsw(
+define i8 @sdiv_mul_nsw_constant_mul_nsw_constant(i8 %x) {
+; CHECK-LABEL: @sdiv_mul_nsw_constant_mul_nsw_constant(
; CHECK-NEXT: ret i8 2
;
%add4 = mul nsw i8 %x, 5
@@ -1453,8 +1555,8 @@ define i8 @sdiv_mul_nsw_mul_nsw(i8 %x) {
ret i8 %div
}
-define i8 @sdiv_mul_mul_nsw(i8 %x) {
-; CHECK-LABEL: @sdiv_mul_mul_nsw(
+define i8 @sdiv_mul_constant_mul_nsw_constant(i8 %x) {
+; CHECK-LABEL: @sdiv_mul_constant_mul_nsw_constant(
; CHECK-NEXT: [[ADD4:%.*]] = mul nsw i8 [[X:%.*]], 10
; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], 20
; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[ADD5]], [[ADD4]]
@@ -1466,8 +1568,8 @@ define i8 @sdiv_mul_mul_nsw(i8 %x) {
ret i8 %div
}
-define i8 @sdiv_mul_mul(i8 %x) {
-; CHECK-LABEL: @sdiv_mul_mul(
+define i8 @sdiv_mul_constant_mul_constant(i8 %x) {
+; CHECK-LABEL: @sdiv_mul_constant_mul_constant(
; CHECK-NEXT: [[ADD4:%.*]] = mul i8 [[X:%.*]], 10
; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], 20
; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[ADD5]], [[ADD4]]
@@ -1479,8 +1581,8 @@ define i8 @sdiv_mul_mul(i8 %x) {
ret i8 %div
}
-define i8 @udiv_mul_mul(i8 %x) {
-; CHECK-LABEL: @udiv_mul_mul(
+define i8 @udiv_mul_constant_mul_constant(i8 %x) {
+; CHECK-LABEL: @udiv_mul_constant_mul_constant(
; CHECK-NEXT: [[ADD4:%.*]] = mul i8 [[X:%.*]], 10
; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], 20
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[ADD5]], [[ADD4]]
@@ -1492,8 +1594,8 @@ define i8 @udiv_mul_mul(i8 %x) {
ret i8 %div
}
-define i8 @udiv_mul_nuw_mul_nuw(i8 %x) {
-; CHECK-LABEL: @udiv_mul_nuw_mul_nuw(
+define i8 @udiv_mul_nuw_constant_mul_nuw_constant(i8 %x) {
+; CHECK-LABEL: @udiv_mul_nuw_constant_mul_nuw_constant(
; CHECK-NEXT: ret i8 1
;
%add4 = mul nuw i8 %x, 10
@@ -1502,8 +1604,8 @@ define i8 @udiv_mul_nuw_mul_nuw(i8 %x) {
ret i8 %div
}
-define i8 @udiv_mul_mul_nuw(i8 %x) {
-; CHECK-LABEL: @udiv_mul_mul_nuw(
+define i8 @udiv_mul_constant_mul_nuw_constant(i8 %x) {
+; CHECK-LABEL: @udiv_mul_constant_mul_nuw_constant(
; CHECK-NEXT: [[ADD4:%.*]] = mul nuw i8 [[X:%.*]], 10
; CHECK-NEXT: [[ADD5:%.*]] = mul i8 [[X]], 20
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[ADD5]], [[ADD4]]
@@ -1515,8 +1617,8 @@ define i8 @udiv_mul_mul_nuw(i8 %x) {
ret i8 %div
}
-define i8 @udiv_mul_nuw_mul(i8 %x) {
-; CHECK-LABEL: @udiv_mul_nuw_mul(
+define i8 @udiv_mul_constant_nuw_mul_constant(i8 %x) {
+; CHECK-LABEL: @udiv_mul_constant_nuw_mul_constant(
; CHECK-NEXT: ret i8 2
;
%add4 = mul i8 %x, 10
>From a63083f690763ff8db6a907c38692186bfd3a346 Mon Sep 17 00:00:00 2001
From: Zheng Junjie <zhengjunjie at iscas.ac.cn>
Date: Mon, 27 Nov 2023 13:48:57 +0800
Subject: [PATCH 3/3] fixup! fixup! [InstCombine] Simplify `(X * C0) / (X *
C1)` into `C0 / C1`.
---
.../InstCombine/InstCombineMulDivRem.cpp | 23 ++++++++++---------
llvm/test/Transforms/InstCombine/div.ll | 23 +++++++++++++++++++
2 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 76f822c3b2e10f9..3bf4844d7f7d00e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1212,35 +1212,36 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
auto OB0HasNSW = cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap();
auto OB0HasNUW = cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap();
- auto CreateDivOrNull = [&](Value *A) -> Instruction * {
+ auto CreateDivOrNull = [&](Value *A, Value *B) -> Instruction * {
auto OB1HasNSW = cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap();
auto OB1HasNUW =
cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap();
-
- // if (IsSigned && OB0HasNSW && OB1HasNSW) {
- // return BinaryOperator::CreateSDiv(A, Z);
- // }
+ const APInt *C;
+ if (IsSigned && OB0HasNSW && OB1HasNSW && (match(A, m_APInt(C))) &&
+ (*C != -1 ||
+ *C != APInt::getSignedMinValue(Ty->getScalarSizeInBits())))
+ return BinaryOperator::CreateSDiv(A, B);
if (!IsSigned && OB0HasNUW && OB1HasNUW) {
- return BinaryOperator::CreateUDiv(A, Z);
+ return BinaryOperator::CreateUDiv(A, B);
};
- if (isa<Constant>(A) && isa<Constant>(Z)) {
+ if (isa<Constant>(A) && isa<Constant>(B)) {
if (IsSigned && OB0HasNSW) {
- return BinaryOperator::CreateSDiv(A, Z);
+ return BinaryOperator::CreateSDiv(A, B);
}
if (!IsSigned && OB0HasNUW) {
- return BinaryOperator::CreateUDiv(A, Z);
+ return BinaryOperator::CreateUDiv(A, B);
};
};
return nullptr;
};
if (match(Op1, m_c_Mul(m_Specific(X), m_Value(Z)))) {
- auto *Val = CreateDivOrNull(Y);
+ auto *Val = CreateDivOrNull(Y, Z);
if (Val)
return Val;
};
if (match(Op1, m_c_Mul(m_Specific(Y), m_Value(Z)))) {
- auto *Val = CreateDivOrNull(X);
+ auto *Val = CreateDivOrNull(X, Z);
if (Val)
return Val;
}
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index cd4a09e7f4dedb9..6128b5cca32e0df 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -1627,6 +1627,29 @@ define i8 @udiv_mul_constant_nuw_mul_constant(i8 %x) {
ret i8 %div
}
+define i4 @sdiv_mul_nsw_mul_nsw_allones(i4 %a, i4 %c2) {
+; CHECK-LABEL: @sdiv_mul_nsw_mul_nsw_allones(
+; CHECK-NEXT: [[ADD4:%.*]] = sub nsw i4 0, [[A:%.*]]
+; CHECK-NEXT: [[ADD5:%.*]] = mul nsw i4 [[A]], [[C2:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i4 [[ADD5]], [[ADD4]]
+; CHECK-NEXT: ret i4 [[DIV]]
+;
+ %add4 = mul nsw i4 %a, -1
+ %add5 = mul nsw i4 %a, %c2
+ %div = sdiv i4 %add5, %add4
+ ret i4 %div
+}
+
+define i4 @sdiv_mul_nsw_mul_signmask(i4 %a, i4 %c2) {
+; CHECK-LABEL: @sdiv_mul_nsw_mul_signmask(
+; CHECK-NEXT: ret i4 poison
+;
+ %add4 = mul nsw i4 %a, 64
+ %add5 = mul nsw i4 %a, %c2
+ %div = sdiv i4 %add5, %add4
+ ret i4 %div
+}
+
define i32 @sdiv_sub1(i32 %arg) {
; CHECK-LABEL: @sdiv_sub1(
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG:%.*]], -2147483648
More information about the llvm-commits
mailing list