[llvm] 4966d8e - [InstCombine] distribute div over add with matching mul-by-constant
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 20 11:06:03 PST 2023
Author: Sanjay Patel
Date: 2023-02-20T13:45:06-05:00
New Revision: 4966d8ebe1bbe5bd6a4d28b36efdbe6dd1659b3f
URL: https://github.com/llvm/llvm-project/commit/4966d8ebe1bbe5bd6a4d28b36efdbe6dd1659b3f
DIFF: https://github.com/llvm/llvm-project/commit/4966d8ebe1bbe5bd6a4d28b36efdbe6dd1659b3f.diff
LOG: [InstCombine] distribute div over add with matching mul-by-constant
((X * C2) + C1) / C2 --> X + C1/C2
https://alive2.llvm.org/ce/z/P66io8
https://alive2.llvm.org/ce/z/vghegw
This could be made more general -- the multiplier could be a
multiple of the divisor -- but this is the pattern from
issue #60754.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
llvm/test/Transforms/InstCombine/div.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index fbf229386701e..8ca99db8f4761 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -976,9 +976,9 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
ConstantInt::get(Ty, Product));
}
+ APInt Quotient(C2->getBitWidth(), /*val=*/0ULL, IsSigned);
if ((IsSigned && match(Op0, m_NSWMul(m_Value(X), m_APInt(C1)))) ||
(!IsSigned && match(Op0, m_NUWMul(m_Value(X), m_APInt(C1))))) {
- APInt Quotient(C1->getBitWidth(), /*val=*/0ULL, IsSigned);
// (X * C1) / C2 -> X / (C2 / C1) if C2 is a multiple of C1.
if (isMultiple(*C2, *C1, Quotient, IsSigned)) {
@@ -1003,7 +1003,6 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
C1->ult(C1->getBitWidth() - 1)) ||
(!IsSigned && match(Op0, m_NUWShl(m_Value(X), m_APInt(C1))) &&
C1->ult(C1->getBitWidth()))) {
- APInt Quotient(C1->getBitWidth(), /*val=*/0ULL, IsSigned);
APInt C1Shifted = APInt::getOneBitSet(
C1->getBitWidth(), static_cast<unsigned>(C1->getZExtValue()));
@@ -1026,6 +1025,19 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
}
}
+ // Distribute div over add to eliminate a matching div/mul pair:
+ // ((X * C2) + C1) / C2 --> X + C1/C2
+ if (IsSigned &&
+ match(Op0, m_NSWAdd(m_NSWMul(m_Value(X), m_SpecificInt(*C2)),
+ m_APInt(C1))) &&
+ isMultiple(*C1, *C2, Quotient, IsSigned))
+ return BinaryOperator::CreateNSWAdd(X, ConstantInt::get(Ty, Quotient));
+ if (!IsSigned &&
+ match(Op0, m_NUWAdd(m_NUWMul(m_Value(X), m_SpecificInt(*C2)),
+ m_APInt(C1))) &&
+ isMultiple(*C1, *C2, Quotient, IsSigned))
+ return BinaryOperator::CreateNUWAdd(X, ConstantInt::get(Ty, Quotient));
+
if (!C2->isZero()) // avoid X udiv 0
if (Instruction *FoldedDiv = foldBinOpIntoSelectOrPhi(I))
return FoldedDiv;
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index a31e8db4bb621..3f0b593d85810 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -1492,11 +1492,11 @@ define i8 @sdiv_udiv_mul_nsw(i8 %x, i8 %y, i8 %z) {
ret i8 %r
}
+; ((X * C2) + C1) / C2 --> X + C1/C2
+
define i6 @sdiv_distribute_mul_nsw_add_nsw(i6 %x) {
; CHECK-LABEL: @sdiv_distribute_mul_nsw_add_nsw(
-; CHECK-NEXT: [[MUL:%.*]] = mul nsw i6 [[X:%.*]], 3
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i6 [[MUL]], -15
-; CHECK-NEXT: [[DIV:%.*]] = sdiv i6 [[ADD]], 3
+; CHECK-NEXT: [[DIV:%.*]] = add nsw i6 [[X:%.*]], -5
; CHECK-NEXT: ret i6 [[DIV]]
;
%mul = mul nsw i6 %x, 3
@@ -1505,13 +1505,15 @@ define i6 @sdiv_distribute_mul_nsw_add_nsw(i6 %x) {
ret i6 %div
}
+; extra uses are ok
+
define i32 @sdiv_distribute_mul_nsw_add_nsw_uses(i32 %x) {
; CHECK-LABEL: @sdiv_distribute_mul_nsw_add_nsw_uses(
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], 42
; CHECK-NEXT: call void @use(i32 [[MUL]])
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[MUL]], 126
; CHECK-NEXT: call void @use(i32 [[ADD]])
-; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ADD]], 42
+; CHECK-NEXT: [[DIV:%.*]] = add nsw i32 [[X]], 3
; CHECK-NEXT: ret i32 [[DIV]]
;
%mul = mul nsw i32 %x, 42
@@ -1522,11 +1524,11 @@ define i32 @sdiv_distribute_mul_nsw_add_nsw_uses(i32 %x) {
ret i32 %div
}
+; vector splats work
+
define <2 x i6> @udiv_distribute_mul_nuw_add_nuw(<2 x i6> %x) {
; CHECK-LABEL: @udiv_distribute_mul_nuw_add_nuw(
-; CHECK-NEXT: [[MUL:%.*]] = mul nuw <2 x i6> [[X:%.*]], <i6 3, i6 3>
-; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i6> [[MUL]], <i6 15, i6 15>
-; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i6> [[ADD]], <i6 3, i6 3>
+; CHECK-NEXT: [[DIV:%.*]] = add nuw <2 x i6> [[X:%.*]], <i6 5, i6 5>
; CHECK-NEXT: ret <2 x i6> [[DIV]]
;
%mul = mul nuw <2 x i6> %x, <i6 3, i6 3>
@@ -1535,6 +1537,8 @@ define <2 x i6> @udiv_distribute_mul_nuw_add_nuw(<2 x i6> %x) {
ret <2 x i6> %div
}
+; negative test - constants must be evenly divisible
+
define i6 @sdiv_distribute_mul_nsw_add_nsw_not_multiple_offset(i6 %x) {
; CHECK-LABEL: @sdiv_distribute_mul_nsw_add_nsw_not_multiple_offset(
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i6 [[X:%.*]], 3
@@ -1548,6 +1552,8 @@ define i6 @sdiv_distribute_mul_nsw_add_nsw_not_multiple_offset(i6 %x) {
ret i6 %div
}
+; negative test - constants must be evenly divisible
+
define i6 @udiv_distribute_mul_nuw_add_nuw_not_multiple_offset(i6 %x) {
; CHECK-LABEL: @udiv_distribute_mul_nuw_add_nuw_not_multiple_offset(
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i6 [[X:%.*]], 3
@@ -1561,6 +1567,8 @@ define i6 @udiv_distribute_mul_nuw_add_nuw_not_multiple_offset(i6 %x) {
ret i6 %div
}
+; negative test - wrong no-wrap
+
define i6 @sdiv_distribute_mul_nuw_add_nsw(i6 %x) {
; CHECK-LABEL: @sdiv_distribute_mul_nuw_add_nsw(
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i6 [[X:%.*]], 3
@@ -1574,6 +1582,8 @@ define i6 @sdiv_distribute_mul_nuw_add_nsw(i6 %x) {
ret i6 %div
}
+; negative test - wrong no-wrap
+
define i6 @udiv_distribute_mul_nsw_add_nuw(i6 %x) {
; CHECK-LABEL: @udiv_distribute_mul_nsw_add_nuw(
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i6 [[X:%.*]], 3
More information about the llvm-commits
mailing list