[llvm] f75b530 - [ConstantFold] allow folding icmp of null and constexpr

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 8 06:00:29 PST 2021


Author: Sanjay Patel
Date: 2021-03-08T08:53:59-05:00
New Revision: f75b5305f4def4973027a9b96fb3f1e50ce056e3

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

LOG: [ConstantFold] allow folding icmp of null and constexpr

I noticed that we were not folding expressions like this:
icmp ult (constexpr), null
in https://llvm.org/PR49355, so we end up with extremely large
icmp instructions as the constant expressions pile up on each other.

There is no potential to mis-fold an unsigned boundary condition
with a zero/null, so this is just falling through a crack in the
pattern matching.

The more general case of comparisons of non-zero constants and
constexpr are more tricky and may require the datalayout to know
how to cast to different types, etc. Negative tests verify that
we are only changing a subset of potential patterns.

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

Added: 
    

Modified: 
    llvm/lib/IR/ConstantFold.cpp
    llvm/test/CodeGen/PowerPC/pr46923.ll
    llvm/test/Transforms/InstCombine/vector_gep1-inseltpoison.ll
    llvm/test/Transforms/InstCombine/vector_gep1.ll
    llvm/test/Transforms/InstSimplify/ConstProp/icmp-null.ll
    llvm/test/Transforms/JumpThreading/thread-two-bbs.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 6d2770af8322..3903d72ac7c3 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -2011,7 +2011,7 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
       }
   // icmp eq/ne(GV,null) -> false/true
   } else if (C2->isNullValue()) {
-    if (const GlobalValue *GV = dyn_cast<GlobalValue>(C1))
+    if (const GlobalValue *GV = dyn_cast<GlobalValue>(C1)) {
       // Don't try to evaluate aliases.  External weak GV can be null.
       if (!isa<GlobalAlias>(GV) && !GV->hasExternalWeakLinkage() &&
           !NullPointerIsDefined(nullptr /* F */,
@@ -2021,6 +2021,16 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
         else if (pred == ICmpInst::ICMP_NE)
           return ConstantInt::getTrue(C1->getContext());
       }
+    }
+
+    // The caller is expected to commute the operands if the constant expression
+    // is C2.
+    // C1 >= 0 --> true
+    if (pred == ICmpInst::ICMP_UGE)
+      return Constant::getAllOnesValue(ResultTy);
+    // C1 < 0 --> false
+    if (pred == ICmpInst::ICMP_ULT)
+      return Constant::getNullValue(ResultTy);
   }
 
   // If the comparison is a comparison between two i1's, simplify it.

diff  --git a/llvm/test/CodeGen/PowerPC/pr46923.ll b/llvm/test/CodeGen/PowerPC/pr46923.ll
index 3e9faa60422a..0e35d09ed769 100644
--- a/llvm/test/CodeGen/PowerPC/pr46923.ll
+++ b/llvm/test/CodeGen/PowerPC/pr46923.ll
@@ -8,7 +8,6 @@ define i1 @foo() {
 ; CHECK-LABEL: foo:
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    li r3, 0
-; CHECK-NEXT:    isel r3, 0, r3, 4*cr5+lt
 ; CHECK-NEXT:    blr
 entry:
   br label %next

diff  --git a/llvm/test/Transforms/InstCombine/vector_gep1-inseltpoison.ll b/llvm/test/Transforms/InstCombine/vector_gep1-inseltpoison.ll
index 0141112d8834..014e6e96b2ac 100644
--- a/llvm/test/Transforms/InstCombine/vector_gep1-inseltpoison.ll
+++ b/llvm/test/Transforms/InstCombine/vector_gep1-inseltpoison.ll
@@ -64,7 +64,7 @@ define <2 x i32*> @test7(<2 x {i32, i32}*> %a) {
 
 define <vscale x 2 x i1> @test8() {
 ; CHECK-LABEL: @test8(
-; CHECK-NEXT:    ret <vscale x 2 x i1> icmp ult (<vscale x 2 x i64> zext (<vscale x 2 x i32> shufflevector (<vscale x 2 x i32> insertelement (<vscale x 2 x i32> poison, i32 1, i32 0), <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer) to <vscale x 2 x i64>), <vscale x 2 x i64> zeroinitializer)
+; CHECK-NEXT:    ret <vscale x 2 x i1> zeroinitializer
 ;
   %ins = insertelement <vscale x 2 x i32> poison, i32 1, i32 0
   %b = shufflevector <vscale x 2 x i32> %ins, <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer

diff  --git a/llvm/test/Transforms/InstCombine/vector_gep1.ll b/llvm/test/Transforms/InstCombine/vector_gep1.ll
index 4eb449edb348..bd1df0b98ffd 100644
--- a/llvm/test/Transforms/InstCombine/vector_gep1.ll
+++ b/llvm/test/Transforms/InstCombine/vector_gep1.ll
@@ -64,7 +64,7 @@ define <2 x i32*> @test7(<2 x {i32, i32}*> %a) {
 
 define <vscale x 2 x i1> @test8() {
 ; CHECK-LABEL: @test8(
-; CHECK-NEXT:    ret <vscale x 2 x i1> icmp ult (<vscale x 2 x i64> zext (<vscale x 2 x i32> shufflevector (<vscale x 2 x i32> insertelement (<vscale x 2 x i32> undef, i32 1, i32 0), <vscale x 2 x i32> undef, <vscale x 2 x i32> zeroinitializer) to <vscale x 2 x i64>), <vscale x 2 x i64> zeroinitializer)
+; CHECK-NEXT:    ret <vscale x 2 x i1> zeroinitializer
 ;
   %ins = insertelement <vscale x 2 x i32> undef, i32 1, i32 0
   %b = shufflevector <vscale x 2 x i32> %ins, <vscale x 2 x i32> undef, <vscale x 2 x i32> zeroinitializer

diff  --git a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-null.ll b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-null.ll
index 57aea106ace3..c1bef60b347f 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-null.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-null.ll
@@ -3,7 +3,7 @@
 
 define i1 @ule_null_constexpr(i8* %x) {
 ; CHECK-LABEL: @ule_null_constexpr(
-; CHECK-NEXT:    ret i1 icmp uge (i8 (...)* bitcast (i1 (i8*)* @ule_null_constexpr to i8 (...)*), i8 (...)* null)
+; CHECK-NEXT:    ret i1 true
 ;
   %cmp = icmp ule i8 (...)* null, bitcast (i1 (i8*)* @ule_null_constexpr to i8 (...)*)
   ret i1 %cmp
@@ -11,7 +11,7 @@ define i1 @ule_null_constexpr(i8* %x) {
 
 define i1 @ugt_null_constexpr(i8* %x) {
 ; CHECK-LABEL: @ugt_null_constexpr(
-; CHECK-NEXT:    ret i1 icmp ult (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
+; CHECK-NEXT:    ret i1 false
 ;
   %cmp = icmp ugt i8 (...)* null, bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*)
   ret i1 %cmp
@@ -19,7 +19,7 @@ define i1 @ugt_null_constexpr(i8* %x) {
 
 define i1 @uge_constexpr_null(i8* %x) {
 ; CHECK-LABEL: @uge_constexpr_null(
-; CHECK-NEXT:    ret i1 icmp uge (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
+; CHECK-NEXT:    ret i1 true
 ;
   %cmp = icmp uge i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), null
   ret i1 %cmp
@@ -27,12 +27,14 @@ define i1 @uge_constexpr_null(i8* %x) {
 
 define i1 @ult_constexpr_null(i8* %x) {
 ; CHECK-LABEL: @ult_constexpr_null(
-; CHECK-NEXT:    ret i1 icmp ult (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
+; CHECK-NEXT:    ret i1 false
 ;
   %cmp = icmp ult i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), null
   ret i1 %cmp
 }
 
+; Negative test - we don't know if the constexpr is null.
+
 define i1 @ule_constexpr_null(i8* %x) {
 ; CHECK-LABEL: @ule_constexpr_null(
 ; CHECK-NEXT:    ret i1 icmp ule (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
@@ -41,6 +43,8 @@ define i1 @ule_constexpr_null(i8* %x) {
   ret i1 %cmp
 }
 
+; Negative test - we don't know if the constexpr is *signed* less-than null.
+
 define i1 @slt_constexpr_null(i8* %x) {
 ; CHECK-LABEL: @slt_constexpr_null(
 ; CHECK-NEXT:    ret i1 icmp slt (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
@@ -49,6 +53,8 @@ define i1 @slt_constexpr_null(i8* %x) {
   ret i1 %cmp
 }
 
+; Negative test - we don't try to evaluate this comparison of constant expressions.
+
 define i1 @ult_constexpr_constexpr_one(i8* %x) {
 ; CHECK-LABEL: @ult_constexpr_constexpr_one(
 ; CHECK-NEXT:    ret i1 icmp ult (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* inttoptr (i32 1 to i8 (...)*))

diff  --git a/llvm/test/Transforms/JumpThreading/thread-two-bbs.ll b/llvm/test/Transforms/JumpThreading/thread-two-bbs.ll
index fd4ec0012f11..80848b86bd3b 100644
--- a/llvm/test/Transforms/JumpThreading/thread-two-bbs.ll
+++ b/llvm/test/Transforms/JumpThreading/thread-two-bbs.ll
@@ -188,23 +188,24 @@ bb_exit:
   ret void
 }
 
-; TODO: This is a special-case of the above pattern:
+; This is a special-case of the above pattern:
 ; Null is guaranteed to be unsigned <= all values.
 
 define void @icmp_ule_null_constexpr(i8* %arg1, i8* %arg2) {
 ; CHECK-LABEL: @icmp_ule_null_constexpr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8* [[ARG1:%.*]], null
-; CHECK-NEXT:    br i1 [[CMP1]], label [[BB_BAR1:%.*]], label [[BB_END:%.*]]
-; CHECK:       bb_bar1:
-; CHECK-NEXT:    call void @bar(i32 1)
-; CHECK-NEXT:    br label [[BB_END]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[BB_END_THREAD:%.*]], label [[BB_END:%.*]]
 ; CHECK:       bb_end:
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8* [[ARG2:%.*]], null
 ; CHECK-NEXT:    br i1 [[CMP2]], label [[BB_CONT:%.*]], label [[BB_BAR2:%.*]]
+; CHECK:       bb_end.thread:
+; CHECK-NEXT:    call void @bar(i32 1)
+; CHECK-NEXT:    [[CMP21:%.*]] = icmp ne i8* [[ARG2]], null
+; CHECK-NEXT:    br i1 [[CMP21]], label [[BB_EXIT:%.*]], label [[BB_BAR2]]
 ; CHECK:       bb_bar2:
 ; CHECK-NEXT:    call void @bar(i32 2)
-; CHECK-NEXT:    br label [[BB_EXIT:%.*]]
+; CHECK-NEXT:    br label [[BB_EXIT]]
 ; CHECK:       bb_cont:
 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ule i8* [[ARG1]], inttoptr (i64 4 to i8*)
 ; CHECK-NEXT:    br i1 [[CMP3]], label [[BB_EXIT]], label [[BB_BAR3:%.*]]


        


More information about the llvm-commits mailing list