1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-23 13:02:52 +02:00
llvm-mirror/test/Transforms/CorrelatedValuePropagation/basic.ll
Philip Reames 0926f356af [LVI] Reduce compile time by lazily scanning blocks if needed
When encountering a non-local pointer, LVI would eagerly scan the block for dereferences of the given object to prove the pointer to be non null.  That's all well and good, but *then* we'd go recurse through our input blocks.  As a result, we could end up scanning each and every block we traverse, even if the final definition was obviously non null or we found a constant value somewhere up the chain.  The previous code papered over this by using the isKnownNonNull routine from value tracking.  This made the duplication less painful in the common case.

Instead, we know do the block scan only *after* we've gotten the recursive results back.  This lets us stop scanning individual blocks as soon as we've determined it to be non-null in any predecessor block and use our usual merge rules to propagate that information cheaply through successor blocks.  For a pointer which can be found non-null, this does strictly less work and sometimes substaintially so.

Note that the case where we *can't* prove something non-null is still the really expensive case.  We end up scanning each and every block looking for a dereference and never end up finding one.

llvm-svn: 267642
2016-04-27 00:30:55 +00:00

488 lines
9.4 KiB
LLVM

; RUN: opt < %s -correlated-propagation -S | FileCheck %s
; PR2581
; CHECK-LABEL: @test1(
define i32 @test1(i1 %C) nounwind {
br i1 %C, label %exit, label %body
body: ; preds = %0
; CHECK-NOT: select
%A = select i1 %C, i32 10, i32 11 ; <i32> [#uses=1]
; CHECK: ret i32 11
ret i32 %A
exit: ; preds = %0
; CHECK: ret i32 10
ret i32 10
}
; PR4420
declare i1 @ext()
; CHECK-LABEL: @test2(
define i1 @test2() {
entry:
%cond = tail call i1 @ext() ; <i1> [#uses=2]
br i1 %cond, label %bb1, label %bb2
bb1: ; preds = %entry
%cond2 = tail call i1 @ext() ; <i1> [#uses=1]
br i1 %cond2, label %bb3, label %bb2
bb2: ; preds = %bb1, %entry
; CHECK-NOT: phi i1
%cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ] ; <i1> [#uses=1]
; CHECK: ret i1 false
ret i1 %cond_merge
bb3: ; preds = %bb1
%res = tail call i1 @ext() ; <i1> [#uses=1]
; CHECK: ret i1 %res
ret i1 %res
}
; PR4855
@gv = internal constant i8 7
; CHECK-LABEL: @test3(
define i8 @test3(i8* %a) nounwind {
entry:
%cond = icmp eq i8* %a, @gv
br i1 %cond, label %bb2, label %bb
bb: ; preds = %entry
ret i8 0
bb2: ; preds = %entry
; CHECK: %should_be_const = load i8, i8* @gv
%should_be_const = load i8, i8* %a
ret i8 %should_be_const
}
; PR1757
; CHECK-LABEL: @test4(
define i32 @test4(i32) {
EntryBlock:
; CHECK: icmp sgt i32 %0, 2
%.demorgan = icmp sgt i32 %0, 2
br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo
GreaterThanTwo:
; CHECK-NOT: icmp eq i32 %0, 2
icmp eq i32 %0, 2
; CHECK: br i1 false
br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo
NotTwoAndGreaterThanTwo:
ret i32 2
Impossible:
ret i32 1
LessThanOrEqualToTwo:
ret i32 0
}
declare i32* @f(i32*)
define void @test5(i32* %x, i32* %y) {
; CHECK-LABEL: @test5(
entry:
%pre = icmp eq i32* %x, null
br i1 %pre, label %return, label %loop
loop:
%phi = phi i32* [ %sel, %loop ], [ %x, %entry ]
; CHECK: %phi = phi i32* [ %f, %loop ], [ %x, %entry ]
%f = tail call i32* @f(i32* %phi)
%cmp1 = icmp ne i32* %f, %y
%sel = select i1 %cmp1, i32* %f, i32* null
%cmp2 = icmp eq i32* %sel, null
br i1 %cmp2, label %return, label %loop
return:
ret void
}
define i32 @switch1(i32 %s) {
; CHECK-LABEL: @switch1(
entry:
%cmp = icmp slt i32 %s, 0
br i1 %cmp, label %negative, label %out
negative:
switch i32 %s, label %out [
; CHECK: switch i32 %s, label %out
i32 0, label %out
; CHECK-NOT: i32 0
i32 1, label %out
; CHECK-NOT: i32 1
i32 -1, label %next
; CHECK: i32 -1, label %next
i32 -2, label %next
; CHECK: i32 -2, label %next
i32 2, label %out
; CHECK-NOT: i32 2
i32 3, label %out
; CHECK-NOT: i32 3
]
out:
%p = phi i32 [ 1, %entry ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ]
ret i32 %p
next:
%q = phi i32 [ 0, %negative ], [ 0, %negative ]
ret i32 %q
}
define i32 @switch2(i32 %s) {
; CHECK-LABEL: @switch2(
entry:
%cmp = icmp sgt i32 %s, 0
br i1 %cmp, label %positive, label %out
positive:
switch i32 %s, label %out [
i32 0, label %out
i32 -1, label %next
i32 -2, label %next
]
; CHECK: br label %out
out:
%p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ]
ret i32 %p
next:
%q = phi i32 [ 0, %positive ], [ 0, %positive ]
ret i32 %q
}
define i32 @switch3(i32 %s) {
; CHECK-LABEL: @switch3(
entry:
%cmp = icmp sgt i32 %s, 0
br i1 %cmp, label %positive, label %out
positive:
switch i32 %s, label %out [
i32 -1, label %out
i32 -2, label %next
i32 -3, label %next
]
; CHECK: br label %out
out:
%p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ]
ret i32 %p
next:
%q = phi i32 [ 0, %positive ], [ 0, %positive ]
ret i32 %q
}
define void @switch4(i32 %s) {
; CHECK-LABEL: @switch4(
entry:
%cmp = icmp eq i32 %s, 0
br i1 %cmp, label %zero, label %out
zero:
switch i32 %s, label %out [
i32 0, label %next
i32 1, label %out
i32 -1, label %out
]
; CHECK: br label %next
out:
ret void
next:
ret void
}
define i1 @arg_attribute(i8* nonnull %a) {
; CHECK-LABEL: @arg_attribute(
; CHECK: ret i1 false
%cmp = icmp eq i8* %a, null
br label %exit
exit:
ret i1 %cmp
}
declare nonnull i8* @return_nonnull()
define i1 @call_attribute() {
; CHECK-LABEL: @call_attribute(
; CHECK: ret i1 false
%a = call i8* @return_nonnull()
%cmp = icmp eq i8* %a, null
br label %exit
exit:
ret i1 %cmp
}
define i1 @umin(i32 %a, i32 %b) {
; CHECK-LABEL: @umin(
entry:
%cmp = icmp ult i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%cmp2 = icmp ult i32 %b, 20
br i1 %cmp2, label %b_guard, label %out
b_guard:
%sel_cmp = icmp ult i32 %a, %b
%min = select i1 %sel_cmp, i32 %a, i32 %b
%res = icmp eq i32 %min, 7
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
define i1 @smin(i32 %a, i32 %b) {
; CHECK-LABEL: @smin(
entry:
%cmp = icmp ult i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%cmp2 = icmp ult i32 %b, 20
br i1 %cmp2, label %b_guard, label %out
b_guard:
%sel_cmp = icmp sle i32 %a, %b
%min = select i1 %sel_cmp, i32 %a, i32 %b
%res = icmp eq i32 %min, 7
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
define i1 @smax(i32 %a, i32 %b) {
; CHECK-LABEL: @smax(
entry:
%cmp = icmp sgt i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%cmp2 = icmp sgt i32 %b, 20
br i1 %cmp2, label %b_guard, label %out
b_guard:
%sel_cmp = icmp sge i32 %a, %b
%max = select i1 %sel_cmp, i32 %a, i32 %b
%res = icmp eq i32 %max, 7
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
define i1 @umax(i32 %a, i32 %b) {
; CHECK-LABEL: @umax(
entry:
%cmp = icmp sgt i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%cmp2 = icmp sgt i32 %b, 20
br i1 %cmp2, label %b_guard, label %out
b_guard:
%sel_cmp = icmp uge i32 %a, %b
%max = select i1 %sel_cmp, i32 %a, i32 %b
%res = icmp eq i32 %max, 7
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
define i1 @clamp_low1(i32 %a) {
; CHECK-LABEL: @clamp_low1(
entry:
%cmp = icmp sge i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%sel_cmp = icmp eq i32 %a, 5
%add = add i32 %a, -1
%sel = select i1 %sel_cmp, i32 5, i32 %a
%res = icmp eq i32 %sel, 4
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
define i1 @clamp_low2(i32 %a) {
; CHECK-LABEL: @clamp_low2(
entry:
%cmp = icmp sge i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%sel_cmp = icmp ne i32 %a, 5
%add = add i32 %a, -1
%sel = select i1 %sel_cmp, i32 %a, i32 5
%res = icmp eq i32 %sel, 4
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
define i1 @clamp_high1(i32 %a) {
; CHECK-LABEL: @clamp_high1(
entry:
%cmp = icmp sle i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%sel_cmp = icmp eq i32 %a, 5
%add = add i32 %a, 1
%sel = select i1 %sel_cmp, i32 5, i32 %a
%res = icmp eq i32 %sel, 6
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
define i1 @clamp_high2(i32 %a) {
; CHECK-LABEL: @clamp_high2(
entry:
%cmp = icmp sle i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%sel_cmp = icmp ne i32 %a, 5
%add = add i32 %a, 1
%sel = select i1 %sel_cmp, i32 %a, i32 5
%res = icmp eq i32 %sel, 6
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
; Just showing arbitrary constants work, not really a clamp
define i1 @clamp_high3(i32 %a) {
; CHECK-LABEL: @clamp_high3(
entry:
%cmp = icmp sle i32 %a, 5
br i1 %cmp, label %a_guard, label %out
a_guard:
%sel_cmp = icmp ne i32 %a, 5
%add = add i32 %a, 100
%sel = select i1 %sel_cmp, i32 %a, i32 5
%res = icmp eq i32 %sel, 105
br label %next
next:
; CHECK: next:
; CHECK: ret i1 false
ret i1 %res
out:
ret i1 false
}
define i1 @zext_unknown(i8 %a) {
; CHECK-LABEL: @zext_unknown
; CHECK: ret i1 true
entry:
%a32 = zext i8 %a to i32
%cmp = icmp sle i32 %a32, 256
br label %exit
exit:
ret i1 %cmp
}
define i1 @trunc_unknown(i32 %a) {
; CHECK-LABEL: @trunc_unknown
; CHECK: ret i1 true
entry:
%a8 = trunc i32 %a to i8
%a32 = sext i8 %a8 to i32
%cmp = icmp sle i32 %a32, 128
br label %exit
exit:
ret i1 %cmp
}
; TODO: missed optimization
; Make sure we exercise non-integer inputs to unary operators (i.e. crash
; check).
define i1 @bitcast_unknown(float %a) {
; CHECK-LABEL: @bitcast_unknown
; CHECK: ret i1 %cmp
entry:
%a32 = bitcast float %a to i32
%cmp = icmp sle i32 %a32, 128
br label %exit
exit:
ret i1 %cmp
}
define i1 @bitcast_unknown2(i8* %p) {
; CHECK-LABEL: @bitcast_unknown2
; CHECK: ret i1 %cmp
entry:
%p64 = ptrtoint i8* %p to i64
%cmp = icmp sle i64 %p64, 128
br label %exit
exit:
ret i1 %cmp
}
define i1 @and_unknown(i32 %a) {
; CHECK-LABEL: @and_unknown
; CHECK: ret i1 true
entry:
%and = and i32 %a, 128
%cmp = icmp sle i32 %and, 128
br label %exit
exit:
ret i1 %cmp
}
define i1 @lshr_unknown(i32 %a) {
; CHECK-LABEL: @lshr_unknown
; CHECK: ret i1 true
entry:
%and = lshr i32 %a, 30
%cmp = icmp sle i32 %and, 128
br label %exit
exit:
ret i1 %cmp
}