[LVI] Handle any predicate in comparisons like icmp <pred> (add Val, Offset), ...
authorArtur Pilipenko <apilipenko@azulsystems.com>
Fri, 12 Aug 2016 10:05:11 +0000 (10:05 +0000)
committerArtur Pilipenko <apilipenko@azulsystems.com>
Fri, 12 Aug 2016 10:05:11 +0000 (10:05 +0000)
Currently LVI can only gather value constraints from comparisons like:

* icmp <pred> Val, ...
* icmp ult (add Val, Offset), ...

In fact we can handle any predicate in latter comparisons.

Reviewed By: sanjoy

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

llvm-svn: 278493

llvm/lib/Analysis/LazyValueInfo.cpp
llvm/test/Transforms/CorrelatedValuePropagation/range.ll

index 5faa975..c5c9027 100644 (file)
@@ -1191,7 +1191,7 @@ static LVILatticeVal getValueFromICmpCondition(Value *Val, ICmpInst *ICI,
   // range of Val guaranteed by the condition. Recognize comparisons in the from
   // of:
   //  icmp <pred> Val, ...
-  //  icmp ult (add Val, Offset), ...
+  //  icmp <pred> (add Val, Offset), ...
   // The latter is the range checking idiom that InstCombine produces. Subtract
   // the offset from the allowed range for RHS in this case.
 
@@ -1202,7 +1202,7 @@ static LVILatticeVal getValueFromICmpCondition(Value *Val, ICmpInst *ICI,
   }
 
   ConstantInt *Offset = nullptr;
-  if (Predicate == ICmpInst::ICMP_ULT)
+  if (LHS != Val)
     match(LHS, m_Add(m_Specific(Val), m_ConstantInt(Offset)));
 
   if (LHS == Val || Offset) {
index f8ad6bd..dac6ce4 100644 (file)
@@ -315,3 +315,133 @@ else:
 end:
   ret i32 2
 }
+
+define i1 @test14_slt(i32 %a) {
+; CHECK-LABEL: @test14_slt(
+; CHECK: then:
+; CHECK-NEXT: %result = or i1 false, false
+  %a.off = add i32 %a, -8
+  %cmp = icmp slt i32 %a.off, 8
+  br i1 %cmp, label %then, label %else
+
+then:
+  %dead.1 = icmp eq i32 %a, -2147483641
+  %dead.2 = icmp eq i32 %a, 16
+  %result = or i1 %dead.1, %dead.2
+  ret i1 %result
+
+else:
+  ret i1 false
+}
+
+define i1 @test14_sle(i32 %a) {
+; CHECK-LABEL: @test14_sle(
+; CHECK: then:
+; CHECK-NEXT: %alive = icmp eq i32 %a, 16
+; CHECK-NEXT: %result = or i1 false, %alive
+  %a.off = add i32 %a, -8
+  %cmp = icmp sle i32 %a.off, 8
+  br i1 %cmp, label %then, label %else
+
+then:
+  %dead = icmp eq i32 %a, -2147483641
+  %alive = icmp eq i32 %a, 16
+  %result = or i1 %dead, %alive
+  ret i1 %result
+
+else:
+  ret i1 false
+}
+
+define i1 @test14_sgt(i32 %a) {
+; CHECK-LABEL: @test14_sgt(
+; CHECK: then:
+; CHECK-NEXT: %result = or i1 false, false
+  %a.off = add i32 %a, -8
+  %cmp = icmp sgt i32 %a.off, 8
+  br i1 %cmp, label %then, label %else
+
+then:
+  %dead.1 = icmp eq i32 %a, -2147483640
+  %dead.2 = icmp eq i32 %a, 16
+  %result = or i1 %dead.1, %dead.2
+  ret i1 %result
+
+else:
+  ret i1 false
+}
+
+define i1 @test14_sge(i32 %a) {
+; CHECK-LABEL: @test14_sge(
+; CHECK: then:
+; CHECK-NEXT: %alive = icmp eq i32 %a, 16
+; CHECK-NEXT: %result = or i1 false, %alive
+  %a.off = add i32 %a, -8
+  %cmp = icmp sge i32 %a.off, 8
+  br i1 %cmp, label %then, label %else
+
+then:
+  %dead = icmp eq i32 %a, -2147483640
+  %alive = icmp eq i32 %a, 16
+  %result = or i1 %dead, %alive
+  ret i1 %result
+
+else:
+  ret i1 false
+}
+
+define i1 @test14_ule(i32 %a) {
+; CHECK-LABEL: @test14_ule(
+; CHECK: then:
+; CHECK-NEXT: %alive = icmp eq i32 %a, 16
+; CHECK-NEXT: %result = or i1 false, %alive
+  %a.off = add i32 %a, -8
+  %cmp = icmp ule i32 %a.off, 8
+  br i1 %cmp, label %then, label %else
+
+then:
+  %dead = icmp eq i32 %a, 7
+  %alive = icmp eq i32 %a, 16
+  %result = or i1 %dead, %alive
+  ret i1 %result
+
+else:
+  ret i1 false
+}
+
+define i1 @test14_ugt(i32 %a) {
+; CHECK-LABEL: @test14_ugt(
+; CHECK: then:
+; CHECK-NEXT: %result = or i1 false, false
+  %a.off = add i32 %a, -8
+  %cmp = icmp ugt i32 %a.off, 8
+  br i1 %cmp, label %then, label %else
+
+then:
+  %dead.1 = icmp eq i32 %a, 8
+  %dead.2 = icmp eq i32 %a, 16
+  %result = or i1 %dead.1, %dead.2
+  ret i1 %result
+
+else:
+  ret i1 false
+}
+
+define i1 @test14_uge(i32 %a) {
+; CHECK-LABEL: @test14_uge(
+; CHECK: then:
+; CHECK-NEXT: %alive = icmp eq i32 %a, 16
+; CHECK-NEXT: %result = or i1 false, %alive
+  %a.off = add i32 %a, -8
+  %cmp = icmp uge i32 %a.off, 8
+  br i1 %cmp, label %then, label %else
+
+then:
+  %dead = icmp eq i32 %a, 8
+  %alive = icmp eq i32 %a, 16
+  %result = or i1 %dead, %alive
+  ret i1 %result
+
+else:
+  ret i1 false
+}