[llvm] 6703290 - [InstCombine] fold `sub + and` pattern with specific const value

via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 4 21:58:54 PDT 2022


Author: chenglin.bi
Date: 2022-11-05T12:58:45+08:00
New Revision: 670329036189040edb6c21e4fd1d98c0c979a9e2

URL: https://github.com/llvm/llvm-project/commit/670329036189040edb6c21e4fd1d98c0c979a9e2
DIFF: https://github.com/llvm/llvm-project/commit/670329036189040edb6c21e4fd1d98c0c979a9e2.diff

LOG: [InstCombine] fold `sub + and` pattern with specific const value

`C1 - ((C3 - X) & C2) --> (X & C2) + (C1 - (C2 & C3))`
when:
    (C3 - ((C2 & C3) - 1)) is pow2 &&
    ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1) &&
    C2 is negative pow2 || (C3 - X) is nuw

https://alive2.llvm.org/ce/z/HXQJV-

Fix: #58523

Reviewed By: spatel

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 76234ccfdcff3..6f1b0b9b070bb 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2032,12 +2032,34 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
   }
 
   const APInt *Op0C;
-  if (match(Op0, m_APInt(Op0C)) && Op0C->isMask()) {
-    // Turn this into a xor if LHS is 2^n-1 and the remaining bits are known
-    // zero.
-    KnownBits RHSKnown = computeKnownBits(Op1, 0, &I);
-    if ((*Op0C | RHSKnown.Zero).isAllOnes())
-      return BinaryOperator::CreateXor(Op1, Op0);
+  if (match(Op0, m_APInt(Op0C))) {
+    if (Op0C->isMask()) {
+      // Turn this into a xor if LHS is 2^n-1 and the remaining bits are known
+      // zero.
+      KnownBits RHSKnown = computeKnownBits(Op1, 0, &I);
+      if ((*Op0C | RHSKnown.Zero).isAllOnes())
+        return BinaryOperator::CreateXor(Op1, Op0);
+    }
+
+    // C - ((C3 -nuw X) & C2) --> (C - (C2 & C3)) + (X & C2) when:
+    // (C3 - ((C2 & C3) - 1)) is pow2
+    // ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1)
+    // C2 is negative pow2 || sub nuw
+    const APInt *C2, *C3;
+    BinaryOperator *InnerSub;
+    if (match(Op1, m_OneUse(m_And(m_BinOp(InnerSub), m_APInt(C2)))) &&
+        match(InnerSub, m_Sub(m_APInt(C3), m_Value(X))) &&
+        (InnerSub->hasNoUnsignedWrap() || C2->isNegatedPowerOf2())) {
+      APInt C2AndC3 = *C2 & *C3;
+      APInt C2AndC3Minus1 = C2AndC3 - 1;
+      APInt C2AddC3 = *C2 + *C3;
+      if ((*C3 - C2AndC3Minus1).isPowerOf2() &&
+          C2AndC3Minus1.isSubsetOf(C2AddC3)) {
+        Value *And = Builder.CreateAnd(X, ConstantInt::get(I.getType(), *C2));
+        return BinaryOperator::CreateAdd(
+            And, ConstantInt::get(I.getType(), *Op0C - C2AndC3));
+      }
+    }
   }
 
   {

diff  --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll
index 4f5349c1b5c09..69fe99fe8521a 100644
--- a/llvm/test/Transforms/InstCombine/sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub.ll
@@ -2229,16 +2229,14 @@ define i8 @demand_sub_from_variable_lowbits3(i8 %x, i8 %y) {
   ret i8 %r
 }
 
-; TODO:
 ; C - ((C3 - X) & C2) --> (C - (C2 & C3)) + (X & C2) when:
-; (C3 - (C2 & C3) + 1) is pow2
+; (C3 - ((C2 & C3) - 1)) is pow2
 ; ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1)
 ; C2 is negative pow2
 define i10 @sub_to_and_nuw(i10 %x) {
 ; CHECK-LABEL: @sub_to_and_nuw(
-; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i10 71, [[X:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = and i10 [[SUB]], 120
-; CHECK-NEXT:    [[R:%.*]] = sub nuw nsw i10 443, [[AND]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i10 [[X:%.*]], 120
+; CHECK-NEXT:    [[R:%.*]] = add nuw nsw i10 [[TMP1]], 379
 ; CHECK-NEXT:    ret i10 [[R]]
 ;
   %sub = sub nuw i10 71, %x
@@ -2247,15 +2245,13 @@ define i10 @sub_to_and_nuw(i10 %x) {
   ret i10 %r
 }
 
-; TODO:
 ; C - ((C3 -nuw X) & C2) --> (C - (C2 & C3)) + (X & C2) when:
-; (C3 - (C2 & C3) + 1) is pow2
+; (C3 - ((C2 & C3) - 1)) is pow2
 ; ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1)
 define i10 @sub_to_and_negpow2(i10 %x) {
 ; CHECK-LABEL: @sub_to_and_negpow2(
-; CHECK-NEXT:    [[SUB:%.*]] = sub i10 71, [[X:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = and i10 [[SUB]], -8
-; CHECK-NEXT:    [[R:%.*]] = sub i10 33, [[AND]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i10 [[X:%.*]], -8
+; CHECK-NEXT:    [[R:%.*]] = add i10 [[TMP1]], -31
 ; CHECK-NEXT:    ret i10 [[R]]
 ;
   %sub = sub i10 71, %x
@@ -2342,9 +2338,8 @@ define i10 @sub_to_and_negative4(i10 %x) {
 
 define <2 x i8> @sub_to_and_vector1(<2 x i8> %x) {
 ; CHECK-LABEL: @sub_to_and_vector1(
-; CHECK-NEXT:    [[SUB:%.*]] = sub nuw <2 x i8> <i8 71, i8 71>, [[X:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[SUB]], <i8 120, i8 120>
-; CHECK-NEXT:    [[R:%.*]] = sub nsw <2 x i8> <i8 55, i8 55>, [[AND]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 120, i8 120>
+; CHECK-NEXT:    [[R:%.*]] = add nsw <2 x i8> [[TMP1]], <i8 -9, i8 -9>
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %sub = sub nuw <2 x i8> <i8 71, i8 71>, %x


        


More information about the llvm-commits mailing list