[llvm] 4d8e47c - [InstCombine] Sink sub into hands of select if one hand becomes zero (PR44426)

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 4 06:44:44 PST 2020


Author: Roman Lebedev
Date: 2020-01-04T17:30:51+03:00
New Revision: 4d8e47ca180557e9bb872da0b8a6ad0fc515c4d3

URL: https://github.com/llvm/llvm-project/commit/4d8e47ca180557e9bb872da0b8a6ad0fc515c4d3
DIFF: https://github.com/llvm/llvm-project/commit/4d8e47ca180557e9bb872da0b8a6ad0fc515c4d3.diff

LOG: [InstCombine] Sink sub into hands of select if one hand becomes zero (PR44426)

This decreases use count of %Op1, makes one hand of select to be 0,
and possibly exposes further folding potential.

Name: sub (select %Cond, %Op1, %FalseVal), %Op1 -> select %Cond, 0, (sub %FalseVal, %Op1)
  %Op1 = %TrueVal
  %o = select i1 %Cond, i8 %Op1, i8 %FalseVal
  %r = sub i8 %o, %Op1
=>
  %n = sub i8 %FalseVal, %Op1
  %r = select i1 %Cond, i8 0, i8 %n

Name: sub (select %Cond, %TrueVal, %Op1), %Op1 -> select %Cond, (sub %TrueVal, %Op1), 0
  %Op1 = %FalseVal
  %o = select i1 %Cond, i8 %TrueVal, i8 %Op1
  %r = sub i8 %o, %Op1
=>
  %n = sub i8 %TrueVal, %Op1
  %r = select i1 %Cond, i8 %n, i8 0

https://rise4fun.com/Alive/avL

https://bugs.llvm.org/show_bug.cgi?id=44426

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
    llvm/test/Transforms/InstCombine/sub-minmax.ll
    llvm/test/Transforms/InstCombine/subtract-of-one-hand-of-select.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 9676c6abef00..05d13aeabe52 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1898,6 +1898,33 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
     }
   }
 
+  {
+    // If we are subtracting from select with one hand matching the value
+    // we are subtracting, sink subtraction into hands of select:
+    //   sub (select %Cond, %TrueVal, %FalseVal), %Op1
+    //     ->
+    //   select %Cond, (sub %TrueVal, %Op1), (sub %FalseVal, %Op1)
+    // This will result in select between new subtraction and 0.
+    Value *Cond, *TrueVal, *FalseVal;
+    if (match(Op0, m_OneUse(m_Select(m_Value(Cond), m_Value(TrueVal),
+                                     m_Value(FalseVal)))) &&
+        (Op1 == TrueVal || Op1 == FalseVal)) {
+      // While it is really tempting to just create two subtractions and let
+      // InstCombine fold one of those to 0, it isn't possible to do so
+      // because of worklist visitation order. So ugly it is.
+      bool SubtractingTrueVal = Op1 == TrueVal;
+      Value *NewSub =
+          Builder.CreateSub(SubtractingTrueVal ? FalseVal : TrueVal, Op1);
+      Constant *Zero = Constant::getNullValue(I.getType());
+      SelectInst *NewSel =
+          SelectInst::Create(Cond, SubtractingTrueVal ? Zero : NewSub,
+                             SubtractingTrueVal ? NewSub : Zero);
+      // Preserve prof metadata if any.
+      NewSel->copyMetadata(cast<Instruction>(*Op0));
+      return NewSel;
+    }
+  }
+
   if (Op1->hasOneUse()) {
     Value *X = nullptr, *Y = nullptr, *Z = nullptr;
     Constant *C = nullptr;

diff  --git a/llvm/test/Transforms/InstCombine/sub-minmax.ll b/llvm/test/Transforms/InstCombine/sub-minmax.ll
index ccc3483ce95b..7fb5e31d81ed 100644
--- a/llvm/test/Transforms/InstCombine/sub-minmax.ll
+++ b/llvm/test/Transforms/InstCombine/sub-minmax.ll
@@ -4,10 +4,9 @@
 define i32 @max_na_b_minux_na(i32 %A, i32 %B) {
 ; CHECK-LABEL: @max_na_b_minux_na(
 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
-; CHECK-NEXT:    [[L0:%.*]] = icmp ult i32 [[NOT]], [[B:%.*]]
-; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 [[B]]
-; CHECK-NEXT:    [[X:%.*]] = sub i32 [[L1]], [[NOT]]
-; CHECK-NEXT:    ret i32 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 0, [[TMP1]]
+; CHECK-NEXT:    ret i32 [[TMP2]]
 ;
   %not = xor i32 %A, -1
   %l0 = icmp ult i32 %not, %B
@@ -34,10 +33,9 @@ define i32 @na_minus_max_na_b(i32 %A, i32 %B) {
 define i32 @max_b_na_minus_na(i32 %A, i32 %B) {
 ; CHECK-LABEL: @max_b_na_minus_na(
 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
-; CHECK-NEXT:    [[L0:%.*]] = icmp ugt i32 [[NOT]], [[B:%.*]]
-; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[B]], i32 [[NOT]]
-; CHECK-NEXT:    [[X:%.*]] = sub i32 [[L1]], [[NOT]]
-; CHECK-NEXT:    ret i32 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 0, [[TMP1]]
+; CHECK-NEXT:    ret i32 [[TMP2]]
 ;
   %not = xor i32 %A, -1
   %l0 = icmp ugt i32 %not, %B
@@ -79,10 +77,8 @@ define i32 @max_na_bi_minux_na(i32 %A, i32 %Bi) {
 
 define i32 @na_minus_max_na_bi(i32 %A, i32 %Bi) {
 ; CHECK-LABEL: @na_minus_max_na_bi(
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
-; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
-; CHECK-NEXT:    ret i32 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]])
+; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
   %B =  xor i32 %Bi, -1
   %not = xor i32 %A, -1
@@ -109,10 +105,8 @@ define i32 @max_bi_na_minus_na(i32 %A, i32 %Bi) {
 
 define i32 @na_minus_max_bi_na(i32 %A, i32 %Bi) {
 ; CHECK-LABEL: @na_minus_max_bi_na(
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
-; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
-; CHECK-NEXT:    ret i32 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]])
+; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
   %B =  xor i32 %Bi, -1
   %not = xor i32 %A, -1

diff  --git a/llvm/test/Transforms/InstCombine/subtract-of-one-hand-of-select.ll b/llvm/test/Transforms/InstCombine/subtract-of-one-hand-of-select.ll
index d4d5e496952d..931a7e9d2c09 100644
--- a/llvm/test/Transforms/InstCombine/subtract-of-one-hand-of-select.ll
+++ b/llvm/test/Transforms/InstCombine/subtract-of-one-hand-of-select.ll
@@ -12,8 +12,8 @@
 
 define i8 @t0_sub_of_trueval(i1 %c, i8 %Op1, i8 %FalseVal) {
 ; CHECK-LABEL: @t0_sub_of_trueval(
-; CHECK-NEXT:    [[O:%.*]] = select i1 [[C:%.*]], i8 [[OP1:%.*]], i8 [[FALSEVAL:%.*]], !prof !0
-; CHECK-NEXT:    [[R:%.*]] = sub i8 [[O]], [[OP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 [[FALSEVAL:%.*]], [[OP1:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[C:%.*]], i8 0, i8 [[TMP1]], !prof !0
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %o = select i1 %c, i8 %Op1, i8 %FalseVal, !prof !0 ; while there, ensure preservation of prof md
@@ -22,8 +22,8 @@ define i8 @t0_sub_of_trueval(i1 %c, i8 %Op1, i8 %FalseVal) {
 }
 define i8 @t1_sub_of_falseval(i1 %c, i8 %TrueVal, i8 %Op1) {
 ; CHECK-LABEL: @t1_sub_of_falseval(
-; CHECK-NEXT:    [[O:%.*]] = select i1 [[C:%.*]], i8 [[TRUEVAL:%.*]], i8 [[OP1:%.*]], !prof !0
-; CHECK-NEXT:    [[R:%.*]] = sub i8 [[O]], [[OP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 [[TRUEVAL:%.*]], [[OP1:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[C:%.*]], i8 [[TMP1]], i8 0, !prof !0
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %o = select i1 %c, i8 %TrueVal, i8 %Op1, !prof !0 ; while there, ensure preservation of prof md
@@ -35,8 +35,8 @@ define i8 @t1_sub_of_falseval(i1 %c, i8 %TrueVal, i8 %Op1) {
 
 define <2 x i8> @t2_vec(i1 %c, <2 x i8> %Op1, <2 x i8> %FalseVal) {
 ; CHECK-LABEL: @t2_vec(
-; CHECK-NEXT:    [[O:%.*]] = select i1 [[C:%.*]], <2 x i8> [[OP1:%.*]], <2 x i8> [[FALSEVAL:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = sub <2 x i8> [[O]], [[OP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i8> [[FALSEVAL:%.*]], [[OP1:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[C:%.*]], <2 x i8> zeroinitializer, <2 x i8> [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %o = select i1 %c, <2 x i8> %Op1, <2 x i8> %FalseVal


        


More information about the llvm-commits mailing list