[PATCH] D21512: [InstSimplify] look through zexts of icmps to eliminate obviously false logic (PR27869)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 19 15:06:32 PDT 2016


spatel created this revision.
spatel added reviewers: eli.friedman, majnemer, sanjoy.
spatel added a subscriber: llvm-commits.
Herald added a subscriber: mcrosier.

This is a specialized form of a transform that already exists in InstCombine. By doing this transform in InstSimplify, we sidestep the problem/question raised by PR27869:
https://llvm.org/bugs/show_bug.cgi?id=27869
...where InstCombine turns an icmp+zext into a shift causing us to miss the fold.

Ideally, we can generalize this a bit to catch other cases (and remove the corresponding code from InstCombine?), but I thought it was better to start with the specific case in the bug report.

http://reviews.llvm.org/D21512

Files:
  lib/Analysis/InstructionSimplify.cpp
  test/Transforms/InstSimplify/AndOrXor.ll

Index: test/Transforms/InstSimplify/AndOrXor.ll
===================================================================
--- test/Transforms/InstSimplify/AndOrXor.ll
+++ test/Transforms/InstSimplify/AndOrXor.ll
@@ -233,12 +233,7 @@
 
 define i32 @and_of_zexted_icmps(i32 %i) {
 ; CHECK-LABEL: @and_of_zexted_icmps(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 %i, 0
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 %i, 4
-; CHECK-NEXT:    [[CONV2:%.*]] = zext i1 [[CMP1]] to i32
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[CONV]], [[CONV2]]
-; CHECK-NEXT:    ret i32 [[AND]]
+; CHECK-NEXT:    ret i32 0
 ;
   %cmp = icmp eq i32 %i, 0
   %conv = zext i1 %cmp to i32
@@ -250,12 +245,7 @@
 
 define <4 x i32> @and_of_zexted_icmps_vec(<4 x i32> %i) {
 ; CHECK-LABEL: @and_of_zexted_icmps_vec(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <4 x i32> %i, zeroinitializer
-; CHECK-NEXT:    [[CONV:%.*]] = zext <4 x i1> [[CMP]] to <4 x i32>
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <4 x i32> %i, zeroinitializer
-; CHECK-NEXT:    [[CONV2:%.*]] = zext <4 x i1> [[CMP1]] to <4 x i32>
-; CHECK-NEXT:    [[AND:%.*]] = and <4 x i32> [[CONV]], [[CONV2]]
-; CHECK-NEXT:    ret <4 x i32> [[AND]]
+; CHECK-NEXT:    ret <4 x i32> zeroinitializer
 ;
   %cmp = icmp eq <4 x i32> %i, zeroinitializer
   %conv = zext <4 x i1> %cmp to <4 x i32>
Index: lib/Analysis/InstructionSimplify.cpp
===================================================================
--- lib/Analysis/InstructionSimplify.cpp
+++ lib/Analysis/InstructionSimplify.cpp
@@ -1608,6 +1608,21 @@
     }
   }
 
+  // The compares may be hidden behind zexts.
+  // Look for this pattern: zext(icmp X, C0) & zext(icmp X, C1)).
+  ICmpInst::Predicate Pred0, Pred1;
+  const APInt *C0, *C1;
+  Value *X;
+  if (match(Op0, m_ZExt(m_ICmp(Pred0, m_Value(X), m_APInt(C0)))) &&
+      match(Op1, m_ZExt(m_ICmp(Pred1, m_Specific(X), m_APInt(C1))))) {
+    // Make a constant range that's the intersection of the two icmp ranges.
+    // If the intersection is empty, we know that the result is false.
+    auto Range0 = ConstantRange::makeAllowedICmpRegion(Pred0, *C0);
+    auto Range1 = ConstantRange::makeAllowedICmpRegion(Pred1, *C1);
+    if (Range0.intersectWith(Range1).isEmptySet())
+      return Constant::getNullValue(Op0->getType());
+  }
+
   // Try some generic simplifications for associative operations.
   if (Value *V = SimplifyAssociativeBinOp(Instruction::And, Op0, Op1, Q,
                                           MaxRecurse))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21512.61230.patch
Type: text/x-patch
Size: 2521 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160619/5f0c6b1b/attachment.bin>


More information about the llvm-commits mailing list