[llvm] r342163 - [InstCombine] Fold (xor (min/max X, Y), -1) -> (max/min ~X, ~Y) when X and Y are freely invertible.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 13 11:52:59 PDT 2018


Author: ctopper
Date: Thu Sep 13 11:52:58 2018
New Revision: 342163

URL: http://llvm.org/viewvc/llvm-project?rev=342163&view=rev
Log:
[InstCombine] Fold (xor (min/max X, Y), -1) -> (max/min ~X, ~Y) when X and Y are freely invertible.

This allows the xor to be removed completely.

This might help with recomitting r341674, but seems good regardless.

Coincidentally fixes PR38915.

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

Added:
    llvm/trunk/test/Transforms/InstCombine/pr38915.ll
Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/trunk/test/Transforms/InstCombine/xor.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=342163&r1=342162&r2=342163&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Thu Sep 13 11:52:58 2018
@@ -2898,6 +2898,17 @@ Instruction *InstCombiner::visitXor(Bina
         return SelectInst::Create(
             Builder.CreateICmp(getInverseMinMaxPred(SPF), NotX, Y), NotX, Y);
       }
+
+      // If both sides are freely invertible, then we can get rid of the xor
+      // completely.
+      if (IsFreeToInvert(LHS, !LHS->hasNUsesOrMore(3)) &&
+          IsFreeToInvert(RHS, !RHS->hasNUsesOrMore(3))) {
+        Value *NotLHS = Builder.CreateNot(LHS);
+        Value *NotRHS = Builder.CreateNot(RHS);
+        return SelectInst::Create(
+            Builder.CreateICmp(getInverseMinMaxPred(SPF), NotLHS, NotRHS),
+            NotLHS, NotRHS);
+      }
     }
   }
 

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=342163&r1=342162&r2=342163&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp Thu Sep 13 11:52:58 2018
@@ -1847,6 +1847,8 @@ Instruction *InstCombiner::visitSelectIn
       // MIN(~a, ~b) -> ~MAX(a, b)
       Value *A, *B;
       if (match(LHS, m_Not(m_Value(A))) && match(RHS, m_Not(m_Value(B))) &&
+          !IsFreeToInvert(A, A->hasOneUse()) &&
+          !IsFreeToInvert(B, B->hasOneUse()) &&
           (!LHS->hasNUsesOrMore(3) || !RHS->hasNUsesOrMore(3))) {
         CmpInst::Predicate InvertedPred = getInverseMinMaxPred(SPF);
         Value *InvertedCmp = Builder.CreateICmp(InvertedPred, A, B);

Added: llvm/trunk/test/Transforms/InstCombine/pr38915.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/pr38915.ll?rev=342163&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/pr38915.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/pr38915.ll Thu Sep 13 11:52:58 2018
@@ -0,0 +1,24 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt %s -instcombine -S | FileCheck %s
+
+define i32 @PR38915(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @PR38915(
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -1
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[Y:%.*]], -1
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], [[TMP1]]
+; CHECK-NEXT:    [[M1N:%.*]] = select i1 [[TMP3]], i32 [[TMP1]], i32 [[TMP2]]
+; CHECK-NEXT:    [[C2:%.*]] = icmp sgt i32 [[M1N]], [[Z:%.*]]
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[C2]], i32 [[M1N]], i32 [[Z]]
+; CHECK-NEXT:    [[M2N:%.*]] = xor i32 [[M2]], -1
+; CHECK-NEXT:    ret i32 [[M2N]]
+;
+  %xn = sub i32 0, %x
+  %yn = sub i32 0, %y
+  %c1 = icmp sgt i32 %xn, %yn
+  %m1 = select i1 %c1, i32 %xn, i32 %yn
+  %m1n = xor i32 %m1, -1
+  %c2 = icmp sgt i32 %m1n, %z
+  %m2 = select i1 %c2, i32 %m1n, i32 %z
+  %m2n = xor i32 %m2, -1
+  ret i32 %m2n
+}

Modified: llvm/trunk/test/Transforms/InstCombine/xor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/xor.ll?rev=342163&r1=342162&r2=342163&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/xor.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/xor.ll Thu Sep 13 11:52:58 2018
@@ -805,10 +805,9 @@ define i32 @test47(i32 %x, i32 %y, i32 %
 
 define i32 @test48(i32 %x) {
 ; CHECK-LABEL: @test48(
-; CHECK-NEXT:    [[A:%.*]] = sub i32 -2, [[X:%.*]]
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt i32 [[A]], 0
-; CHECK-NEXT:    [[C:%.*]] = select i1 [[B]], i32 [[A]], i32 0
-; CHECK-NEXT:    [[D:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP1]], -1
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 -1
 ; CHECK-NEXT:    ret i32 [[D]]
 ;
   %a = sub i32 -2, %x
@@ -820,10 +819,9 @@ define i32 @test48(i32 %x) {
 
 define <2 x i32> @test48vec(<2 x i32> %x) {
 ; CHECK-LABEL: @test48vec(
-; CHECK-NEXT:    [[A:%.*]] = sub <2 x i32> <i32 -2, i32 -2>, [[X:%.*]]
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt <2 x i32> [[A]], zeroinitializer
-; CHECK-NEXT:    [[C:%.*]] = select <2 x i1> [[B]], <2 x i32> [[A]], <2 x i32> zeroinitializer
-; CHECK-NEXT:    [[D:%.*]] = xor <2 x i32> [[C]], <i32 -1, i32 -1>
+; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 1, i32 1>
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt <2 x i32> [[TMP1]], <i32 -1, i32 -1>
+; CHECK-NEXT:    [[D:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[TMP1]], <2 x i32> <i32 -1, i32 -1>
 ; CHECK-NEXT:    ret <2 x i32> [[D]]
 ;
   %a = sub <2 x i32> <i32 -2, i32 -2>, %x
@@ -835,10 +833,9 @@ define <2 x i32> @test48vec(<2 x i32> %x
 
 define i32 @test49(i32 %x) {
 ; CHECK-LABEL: @test49(
-; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -2
-; CHECK-NEXT:    [[B:%.*]] = icmp slt i32 [[A]], -1
-; CHECK-NEXT:    [[C:%.*]] = select i1 [[B]], i32 [[A]], i32 -1
-; CHECK-NEXT:    [[D:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 1, [[X:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], 0
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 0
 ; CHECK-NEXT:    ret i32 [[D]]
 ;
   %a = add i32 %x, -2
@@ -850,10 +847,9 @@ define i32 @test49(i32 %x) {
 
 define <2 x i32> @test49vec(<2 x i32> %x) {
 ; CHECK-LABEL: @test49vec(
-; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X:%.*]], <i32 -2, i32 -2>
-; CHECK-NEXT:    [[B:%.*]] = icmp slt <2 x i32> [[A]], <i32 -1, i32 -1>
-; CHECK-NEXT:    [[C:%.*]] = select <2 x i1> [[B]], <2 x i32> [[A]], <2 x i32> <i32 -1, i32 -1>
-; CHECK-NEXT:    [[D:%.*]] = xor <2 x i32> [[C]], <i32 -1, i32 -1>
+; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i32> <i32 1, i32 1>, [[X:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <2 x i32> [[TMP1]], zeroinitializer
+; CHECK-NEXT:    [[D:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[TMP1]], <2 x i32> zeroinitializer
 ; CHECK-NEXT:    ret <2 x i32> [[D]]
 ;
   %a = add <2 x i32> %x, <i32 -2, i32 -2>
@@ -865,11 +861,10 @@ define <2 x i32> @test49vec(<2 x i32> %x
 
 define i32 @test50(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test50(
-; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], -2
-; CHECK-NEXT:    [[B:%.*]] = sub i32 -2, [[Y:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[A]], [[B]]
-; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]]
-; CHECK-NEXT:    [[E:%.*]] = xor i32 [[D]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 1, [[X:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[Y:%.*]], 1
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[TMP2]], [[TMP1]]
+; CHECK-NEXT:    [[E:%.*]] = select i1 [[TMP3]], i32 [[TMP1]], i32 [[TMP2]]
 ; CHECK-NEXT:    ret i32 [[E]]
 ;
   %a = add i32 %x, -2
@@ -882,11 +877,10 @@ define i32 @test50(i32 %x, i32 %y) {
 
 define <2 x i32> @test50vec(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: @test50vec(
-; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X:%.*]], <i32 -2, i32 -2>
-; CHECK-NEXT:    [[B:%.*]] = sub <2 x i32> <i32 -2, i32 -2>, [[Y:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp slt <2 x i32> [[A]], [[B]]
-; CHECK-NEXT:    [[D:%.*]] = select <2 x i1> [[C]], <2 x i32> [[A]], <2 x i32> [[B]]
-; CHECK-NEXT:    [[E:%.*]] = xor <2 x i32> [[D]], <i32 -1, i32 -1>
+; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i32> <i32 1, i32 1>, [[X:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add <2 x i32> [[Y:%.*]], <i32 1, i32 1>
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt <2 x i32> [[TMP2]], [[TMP1]]
+; CHECK-NEXT:    [[E:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP1]], <2 x i32> [[TMP2]]
 ; CHECK-NEXT:    ret <2 x i32> [[E]]
 ;
   %a = add <2 x i32> %x, <i32 -2, i32 -2>
@@ -899,11 +893,10 @@ define <2 x i32> @test50vec(<2 x i32> %x
 
 define i32 @test51(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test51(
-; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], 2
-; CHECK-NEXT:    [[B:%.*]] = sub i32 2, [[Y:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[A]], [[B]]
-; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]]
-; CHECK-NEXT:    [[E:%.*]] = xor i32 [[D]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 -3, [[X:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[Y:%.*]], -3
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], [[TMP1]]
+; CHECK-NEXT:    [[E:%.*]] = select i1 [[TMP3]], i32 [[TMP1]], i32 [[TMP2]]
 ; CHECK-NEXT:    ret i32 [[E]]
 ;
   %a = add i32 %x, 2
@@ -916,11 +909,10 @@ define i32 @test51(i32 %x, i32 %y) {
 
 define <2 x i32> @test51vec(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: @test51vec(
-; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X:%.*]], <i32 2, i32 2>
-; CHECK-NEXT:    [[B:%.*]] = sub <2 x i32> <i32 2, i32 2>, [[Y:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp sgt <2 x i32> [[A]], [[B]]
-; CHECK-NEXT:    [[D:%.*]] = select <2 x i1> [[C]], <2 x i32> [[A]], <2 x i32> [[B]]
-; CHECK-NEXT:    [[E:%.*]] = xor <2 x i32> [[D]], <i32 -1, i32 -1>
+; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i32> <i32 -3, i32 -3>, [[X:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add <2 x i32> [[Y:%.*]], <i32 -3, i32 -3>
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt <2 x i32> [[TMP2]], [[TMP1]]
+; CHECK-NEXT:    [[E:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP1]], <2 x i32> [[TMP2]]
 ; CHECK-NEXT:    ret <2 x i32> [[E]]
 ;
   %a = add <2 x i32> %x, <i32 2, i32 2>




More information about the llvm-commits mailing list