[PATCH] D140666: [InstCombine] combine intersection for inequality icmps

Yingchi Long via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 25 02:29:52 PST 2023


inclyc updated this revision to Diff 492043.
inclyc added a comment.

add test `masked_and_expected_false`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140666/new/

https://reviews.llvm.org/D140666

Files:
  llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
  llvm/test/Transforms/InstCombine/icmp-logical.ll


Index: llvm/test/Transforms/InstCombine/icmp-logical.ll
===================================================================
--- llvm/test/Transforms/InstCombine/icmp-logical.ll
+++ llvm/test/Transforms/InstCombine/icmp-logical.ll
@@ -280,11 +280,8 @@
 
 define i1 @masked_or_eq(i32 %A) {
 ; CHECK-LABEL: @masked_or_eq(
-; CHECK-NEXT:    [[MASK1:%.*]] = and i32 [[A:%.*]], 15
-; CHECK-NEXT:    [[TST1:%.*]] = icmp eq i32 [[MASK1]], 3
-; CHECK-NEXT:    [[MASK2:%.*]] = and i32 [[A]], 255
-; CHECK-NEXT:    [[TST2:%.*]] = icmp eq i32 [[MASK2]], 243
-; CHECK-NEXT:    [[RES:%.*]] = or i1 [[TST1]], [[TST2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], 15
+; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[TMP1]], 3
 ; CHECK-NEXT:    ret i1 [[RES]]
 ;
   %mask1 = and i32 %A, 15 ; 0x0f
@@ -314,11 +311,8 @@
 
 define i1 @masked_and_ne(i32 %A) {
 ; CHECK-LABEL: @masked_and_ne(
-; CHECK-NEXT:    [[MASK1:%.*]] = and i32 [[A:%.*]], 15
-; CHECK-NEXT:    [[TST1:%.*]] = icmp ne i32 [[MASK1]], 3
-; CHECK-NEXT:    [[MASK2:%.*]] = and i32 [[A]], 255
-; CHECK-NEXT:    [[TST2:%.*]] = icmp ne i32 [[MASK2]], 243
-; CHECK-NEXT:    [[RES:%.*]] = and i1 [[TST1]], [[TST2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], 15
+; CHECK-NEXT:    [[RES:%.*]] = icmp ne i32 [[TMP1]], 3
 ; CHECK-NEXT:    ret i1 [[RES]]
 ;
   %mask1 = and i32 %A, 15 ; 0x0f
Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -654,6 +654,41 @@
     return Builder.CreateICmp(NewCC, NewAnd, NewOr2);
   }
 
+  if (Mask & BMask_NotMixed) {
+    // Check the intersection (B & D) for inequality.
+    // Assume that (B & D) == B || (B & D) == D, i.e B/D is a subset of D/B
+    // and (B & D) & (C ^ E) == 0, bits of C and E, which are shared by both the
+    // B and the D, don't contradict.
+    // Note that we can assume (~B & C) == 0 && (~D & E) == 0, previous
+    // operation should delete these icmps if it hadn't been met.
+
+    // (icmp ne (A & B), C) & (icmp ne (A & D), E)
+    // -> (icmp ne (A & (B & D)), (C & E))
+
+    NewCC = CmpInst::getInversePredicate(NewCC);
+
+    const APInt *OldConstC, *OldConstE;
+    if (!match(C, m_APInt(OldConstC)) || !match(E, m_APInt(OldConstE)))
+      return nullptr;
+
+    const APInt ConstC = PredL != NewCC ? *ConstB ^ *OldConstC : *OldConstC;
+    const APInt ConstE = PredR != NewCC ? *ConstD ^ *OldConstE : *OldConstE;
+
+    const APInt ConstT = *ConstB & *ConstD;
+    if (ConstT != *ConstB && ConstT != *ConstD)
+      return nullptr;
+
+    assert((~*ConstB & ConstC) == 0);
+    assert((~*ConstD & ConstE) == 0);
+
+    // If there is a conflict, we still have to check both sides.
+    if (((*ConstB & *ConstD) & (ConstC ^ ConstE)).getBoolValue())
+      return nullptr;
+
+    Value *NewAnd1 = Builder.CreateAnd(A, /* B&D */ ConstT);
+    Value *NewAnd2 = ConstantInt::get(A->getType(), ConstC & ConstE);
+    return Builder.CreateICmp(NewCC, NewAnd1, NewAnd2);
+  }
   return nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D140666.492043.patch
Type: text/x-patch
Size: 3126 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230125/7358c1ca/attachment.bin>


More information about the llvm-commits mailing list