[llvm] 7b9482d - [InstCombine] fold sdiv with common shl amount in operands
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 12 08:32:24 PDT 2022
Author: Sanjay Patel
Date: 2022-10-12T11:32:15-04:00
New Revision: 7b9482df3dde2395608e0d0744c05bff22cff39e
URL: https://github.com/llvm/llvm-project/commit/7b9482df3dde2395608e0d0744c05bff22cff39e
DIFF: https://github.com/llvm/llvm-project/commit/7b9482df3dde2395608e0d0744c05bff22cff39e.diff
LOG: [InstCombine] fold sdiv with common shl amount in operands
(X << Z) / (Y << Z) --> X / Y
https://alive2.llvm.org/ce/z/CLKzqT
This requires a surprising "nuw" constraint because we have
to guard against immediate UB via signed-div overflow with
-1 divisor.
This extends 008a89037a49ca0d9 and is another transform
derived from issue #58137.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
llvm/test/Transforms/InstCombine/div-shift.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index dfa7a6b04f29..cc90ded72f58 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -862,7 +862,11 @@ static Instruction *foldIDivShl(BinaryOperator &I,
if (!IsSigned && Shl0->hasNoUnsignedWrap() && Shl1->hasNoUnsignedWrap())
Ret = BinaryOperator::CreateUDiv(X, Y);
- // TODO: Handle sdiv.
+ // For signed div, we need 'nsw' on both shifts + 'nuw' on the divisor.
+ // (X << Z) / (Y << Z) --> X / Y
+ if (IsSigned && Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap() &&
+ Shl1->hasNoUnsignedWrap())
+ Ret = BinaryOperator::CreateSDiv(X, Y);
}
if (!Ret)
diff --git a/llvm/test/Transforms/InstCombine/div-shift.ll b/llvm/test/Transforms/InstCombine/div-shift.ll
index 075fb51d68c4..0f5d4e72959c 100644
--- a/llvm/test/Transforms/InstCombine/div-shift.ll
+++ b/llvm/test/Transforms/InstCombine/div-shift.ll
@@ -742,13 +742,11 @@ define i8 @sdiv_lshr_mul_nsw(i8 %x, i8 %y, i8 %z) {
ret i8 %div
}
-; TODO: (X << Z) / (Y << Z) --> X / Y
+; (X << Z) / (Y << Z) --> X / Y
define i8 @sdiv_shl_shl_nsw2_nuw(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @sdiv_shl_shl_nsw2_nuw(
-; CHECK-NEXT: [[XZ:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT: [[YZ:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z]]
-; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[XZ]], [[YZ]]
+; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i8 [[D]]
;
%xz = shl nsw i8 %x, %z
@@ -757,12 +755,13 @@ define i8 @sdiv_shl_shl_nsw2_nuw(i8 %x, i8 %y, i8 %z) {
ret i8 %d
}
+; extra uses are ok and 'exact' propagates
+
define i8 @sdiv_shl_shl_nsw2_nuw_exact_use(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @sdiv_shl_shl_nsw2_nuw_exact_use(
; CHECK-NEXT: [[XZ:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]]
; CHECK-NEXT: call void @use(i8 [[XZ]])
-; CHECK-NEXT: [[YZ:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z]]
-; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[XZ]], [[YZ]]
+; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[X]], [[Y:%.*]]
; CHECK-NEXT: ret i8 [[D]]
;
%xz = shl nsw i8 %x, %z
@@ -772,6 +771,8 @@ define i8 @sdiv_shl_shl_nsw2_nuw_exact_use(i8 %x, i8 %y, i8 %z) {
ret i8 %d
}
+; negative test - wrong wrap
+
define i8 @sdiv_shl_shl_nsw_nuw2(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @sdiv_shl_shl_nsw_nuw2(
; CHECK-NEXT: [[XZ:%.*]] = shl nuw i8 [[X:%.*]], [[Z:%.*]]
@@ -785,6 +786,8 @@ define i8 @sdiv_shl_shl_nsw_nuw2(i8 %x, i8 %y, i8 %z) {
ret i8 %d
}
+; negative test - wrong wrap
+
define i8 @sdiv_shl_shl_nsw_nuw(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @sdiv_shl_shl_nsw_nuw(
; CHECK-NEXT: [[XZ:%.*]] = shl nsw i8 [[X:%.*]], [[Z:%.*]]
@@ -798,6 +801,8 @@ define i8 @sdiv_shl_shl_nsw_nuw(i8 %x, i8 %y, i8 %z) {
ret i8 %d
}
+; negative test - wrong wrap
+
define i8 @sdiv_shl_shl_nuw_nsw2(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @sdiv_shl_shl_nuw_nsw2(
; CHECK-NEXT: [[XZ:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Z:%.*]]
More information about the llvm-commits
mailing list