[llvm] 0fdcca0 - [InstCombine] Fold X sdiv (-1 << C) -> -(X u>> Y) iff X is non-negative

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 17 12:50:24 PDT 2020


Author: Roman Lebedev
Date: 2020-07-17T22:50:09+03:00
New Revision: 0fdcca07ad2c0bdc2cdd40ba638109926f4f513b

URL: https://github.com/llvm/llvm-project/commit/0fdcca07ad2c0bdc2cdd40ba638109926f4f513b
DIFF: https://github.com/llvm/llvm-project/commit/0fdcca07ad2c0bdc2cdd40ba638109926f4f513b.diff

LOG: [InstCombine] Fold  X sdiv (-1 << C) -> -(X u>> Y)  iff X is non-negative

This is the one i'm seeing as missed optimization,
although there are likely other possibilities, as usual.

There are 4 variants of a general sdiv->udiv fold:
https://rise4fun.com/Alive/VS6

Name: v0
Pre: C0 >= 0 && C1 >= 0
%r = sdiv i8 C0, C1
  =>
%r = udiv i8 C0, C1

Name: v1
Pre: C0 <= 0 && C1 >= 0
%r = sdiv i8 C0, C1
  =>
%t0 = udiv i8 -C0, C1
%r = sub i8 0, %t0

Name: v2
Pre: C0 >= 0 && C1 <= 0
%r = sdiv i8 C0, C1
  =>
%t0 = udiv i8 C0, -C1
%r = sub i8 0, %t0

Name: v3
Pre: C0 <= 0 && C1 <= 0
%r = sdiv i8 C0, C1
  =>
%r = udiv i8 -C0, -C1


If we really don't like sdiv (more than udiv that is),
and are okay with increasing instruction count (2 new negations),
and we ensure that we don't undo the fold,
then we could just implement these..

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index c6233a68847d..f039989c004c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1182,6 +1182,13 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
       return BO;
     }
 
+    if (match(Op1, m_NegatedPower2())) {
+      // X sdiv (-(1 << C)) -> -(X sdiv (1 << C)) ->
+      //                    -> -(X udiv (1 << C)) -> -(X u>> C)
+      return BinaryOperator::CreateNeg(Builder.Insert(foldUDivPow2Cst(
+          Op0, ConstantExpr::getNeg(cast<Constant>(Op1)), I, *this)));
+    }
+
     if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) {
       // X sdiv (1 << Y) -> X udiv (1 << Y) ( -> X u>> Y)
       // Safe because the only negative value (1 << Y) can take on is

diff  --git a/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll b/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll
index c10a98a41acb..f9dd32bfc612 100644
--- a/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll
+++ b/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll
@@ -13,7 +13,8 @@ define i8 @t0(i8 %x, i8 %y) {
 ; CHECK-LABEL: @t0(
 ; CHECK-NEXT:    [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -1
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]])
-; CHECK-NEXT:    [[DIV:%.*]] = sdiv i8 [[X]], -32
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i8 [[X]], 5
+; CHECK-NEXT:    [[DIV:%.*]] = sub nsw i8 0, [[TMP1]]
 ; CHECK-NEXT:    ret i8 [[DIV]]
 ;
   %x_is_nonnegative = icmp sge i8 %x, 0


        


More information about the llvm-commits mailing list