[llvm] r284241 - [InstCombine] sub X, sext(bool Y) -> add X, zext(bool Y)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 14 08:24:31 PDT 2016


Author: spatel
Date: Fri Oct 14 10:24:31 2016
New Revision: 284241

URL: http://llvm.org/viewvc/llvm-project?rev=284241&view=rev
Log:
[InstCombine] sub X, sext(bool Y) -> add X, zext(bool Y)

Prefer add/zext because they are better supported in terms of value-tracking.

Note that the backend should be prepared for this IR canonicalization 
(including vector types) after:
https://reviews.llvm.org/rL284015

Differential Revision: https://reviews.llvm.org/D25135

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
    llvm/trunk/test/Transforms/InstCombine/sub.ll
    llvm/trunk/test/Transforms/InstCombine/urem.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp?rev=284241&r1=284240&r2=284241&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp Fri Oct 14 10:24:31 2016
@@ -1642,6 +1642,17 @@ Instruction *InstCombiner::visitSub(Bina
       if (Value *XNeg = dyn_castNegVal(X))
         return BinaryOperator::CreateShl(XNeg, Y);
 
+    // Subtracting -1/0 is the same as adding 1/0:
+    // sub [nsw] Op0, sext(bool Y) -> add [nsw] Op0, zext(bool Y)
+    // 'nuw' is dropped in favor of the canonical form.
+    if (match(Op1, m_SExt(m_Value(Y))) &&
+        Y->getType()->getScalarSizeInBits() == 1) {
+      Value *Zext = Builder->CreateZExt(Y, I.getType());
+      BinaryOperator *Add = BinaryOperator::CreateAdd(Op0, Zext);
+      Add->setHasNoSignedWrap(I.hasNoSignedWrap());
+      return Add;
+    }
+
     // X - A*-B -> X + A*B
     // X - -A*B -> X + A*B
     Value *A, *B;

Modified: llvm/trunk/test/Transforms/InstCombine/sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sub.ll?rev=284241&r1=284240&r2=284241&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/sub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/sub.ll Fri Oct 14 10:24:31 2016
@@ -639,3 +639,56 @@ define i32 @test48(i1 %A, i32 %B, i32 %C
   %sub = sub i32 %sel0, %sel1
   ret i32 %sub
 }
+
+; Zext+add is more canonical than sext+sub.
+
+define i8 @bool_sext_sub(i8 %x, i1 %y) {
+; CHECK-LABEL: @bool_sext_sub(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i1 %y to i8
+; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[TMP1]], %x
+; CHECK-NEXT:    ret i8 [[SUB]]
+;
+  %sext = sext i1 %y to i8
+  %sub = sub i8 %x, %sext
+  ret i8 %sub
+}
+
+; Vectors get the same transform.
+
+define <2 x i8> @bool_sext_sub_vec(<2 x i8> %x, <2 x i1> %y) {
+; CHECK-LABEL: @bool_sext_sub_vec(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i1> %y to <2 x i8>
+; CHECK-NEXT:    [[SUB:%.*]] = add <2 x i8> [[TMP1]], %x
+; CHECK-NEXT:    ret <2 x i8> [[SUB]]
+;
+  %sext = sext <2 x i1> %y to <2 x i8>
+  %sub = sub <2 x i8> %x, %sext
+  ret <2 x i8> %sub
+}
+
+; NSW is preserved.
+
+define <2 x i8> @bool_sext_sub_vec_nsw(<2 x i8> %x, <2 x i1> %y) {
+; CHECK-LABEL: @bool_sext_sub_vec_nsw(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i1> %y to <2 x i8>
+; CHECK-NEXT:    [[SUB:%.*]] = add nsw <2 x i8> [[TMP1]], %x
+; CHECK-NEXT:    ret <2 x i8> [[SUB]]
+;
+  %sext = sext <2 x i1> %y to <2 x i8>
+  %sub = sub nsw <2 x i8> %x, %sext
+  ret <2 x i8> %sub
+}
+
+; We favor the canonical zext+add over keeping the NUW.
+
+define i8 @bool_sext_sub_nuw(i8 %x, i1 %y) {
+; CHECK-LABEL: @bool_sext_sub_nuw(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i1 %y to i8
+; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[TMP1]], %x
+; CHECK-NEXT:    ret i8 [[SUB]]
+;
+  %sext = sext i1 %y to i8
+  %sub = sub nuw i8 %x, %sext
+  ret i8 %sub
+}
+

Modified: llvm/trunk/test/Transforms/InstCombine/urem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/urem.ll?rev=284241&r1=284240&r2=284241&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/urem.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/urem.ll Fri Oct 14 10:24:31 2016
@@ -25,12 +25,11 @@ define i8 @big_divisor(i8 %x) {
   ret i8 %rem
 }
 
-; TODO: Should this be zext+add instead of sext+sub?
 define i5 @biggest_divisor(i5 %x) {
 ; CHECK-LABEL: @biggest_divisor(
 ; CHECK-NEXT:    [[NOT_:%.*]] = icmp eq i5 %x, -1
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i1 [[NOT_]] to i5
-; CHECK-NEXT:    [[REM:%.*]] = sub i5 %x, [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i1 [[NOT_]] to i5
+; CHECK-NEXT:    [[REM:%.*]] = add i5 [[TMP1]], %x
 ; CHECK-NEXT:    ret i5 [[REM]]
 ;
   %rem = urem i5 %x, -1




More information about the llvm-commits mailing list