[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