llvm-mirror/test/Transforms/SROA/phi-and-select.ll
Matt Arsenault 731346ec27 SROA: Allow eliminating addrspacecasted allocas
There is a circular dependency between SROA and InferAddressSpaces
today that requires running both multiple times in order to be able to
eliminate all simple allocas and addrspacecasts. InferAddressSpaces
can't remove addrspacecasts when written to memory, and SROA helps
move pointers out of memory.

This should avoid inserting new commuting addrspacecasts with GEPs,
since there are unresolved questions about pointer wrapping between
different address spaces.

For now, don't replace volatile operations that don't match the alloca
addrspace, as it would change the address space of the access. It may
be still OK to insert an addrspacecast from the new alloca, but be
more conservative for now.

llvm-svn: 363462
2019-06-14 21:38:31 +00:00

697 lines
19 KiB
LLVM

; RUN: opt < %s -sroa -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64"
define i32 @test1() {
; CHECK-LABEL: @test1(
entry:
%a = alloca [2 x i32]
; CHECK-NOT: alloca
%a0 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 0
%a1 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
store i32 0, i32* %a0
store i32 1, i32* %a1
%v0 = load i32, i32* %a0
%v1 = load i32, i32* %a1
; CHECK-NOT: store
; CHECK-NOT: load
%cond = icmp sle i32 %v0, %v1
br i1 %cond, label %then, label %exit
then:
br label %exit
exit:
%phi = phi i32* [ %a1, %then ], [ %a0, %entry ]
; CHECK: phi i32 [ 1, %{{.*}} ], [ 0, %{{.*}} ]
%result = load i32, i32* %phi
ret i32 %result
}
define i32 @test2() {
; CHECK-LABEL: @test2(
entry:
%a = alloca [2 x i32]
; CHECK-NOT: alloca
%a0 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 0
%a1 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
store i32 0, i32* %a0
store i32 1, i32* %a1
%v0 = load i32, i32* %a0
%v1 = load i32, i32* %a1
; CHECK-NOT: store
; CHECK-NOT: load
%cond = icmp sle i32 %v0, %v1
%select = select i1 %cond, i32* %a1, i32* %a0
; CHECK: select i1 %{{.*}}, i32 1, i32 0
%result = load i32, i32* %select
ret i32 %result
}
; If bitcast isn't considered a safe phi/select use, the alloca
; remains as an array.
; FIXME: Why isn't this identical to test2?
; CHECK-LABEL: @test2_bitcast(
; CHECK: alloca i32
; CHECK-NEXT: alloca i32
; CHECK: %select = select i1 %cond, i32* %a.sroa.3, i32* %a.sroa.0
; CHECK-NEXT: %select.bc = bitcast i32* %select to float*
; CHECK-NEXT: %result = load float, float* %select.bc, align 4
define float @test2_bitcast() {
entry:
%a = alloca [2 x i32]
%a0 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 0
%a1 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
store i32 0, i32* %a0
store i32 1, i32* %a1
%v0 = load i32, i32* %a0
%v1 = load i32, i32* %a1
%cond = icmp sle i32 %v0, %v1
%select = select i1 %cond, i32* %a1, i32* %a0
%select.bc = bitcast i32* %select to float*
%result = load float, float* %select.bc
ret float %result
}
; CHECK-LABEL: @test2_addrspacecast(
; CHECK: alloca i32
; CHECK-NEXT: alloca i32
; CHECK: %select = select i1 %cond, i32* %a.sroa.3, i32* %a.sroa.0
; CHECK-NEXT: %select.asc = addrspacecast i32* %select to i32 addrspace(1)*
; CHECK-NEXT: load i32, i32 addrspace(1)* %select.asc, align 4
define i32 @test2_addrspacecast() {
entry:
%a = alloca [2 x i32]
%a0 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 0
%a1 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
store i32 0, i32* %a0
store i32 1, i32* %a1
%v0 = load i32, i32* %a0
%v1 = load i32, i32* %a1
%cond = icmp sle i32 %v0, %v1
%select = select i1 %cond, i32* %a1, i32* %a0
%select.asc = addrspacecast i32* %select to i32 addrspace(1)*
%result = load i32, i32 addrspace(1)* %select.asc
ret i32 %result
}
define i32 @test3(i32 %x) {
; CHECK-LABEL: @test3(
entry:
%a = alloca [2 x i32]
; CHECK-NOT: alloca
; Note that we build redundant GEPs here to ensure that having different GEPs
; into the same alloca partation continues to work with PHI speculation. This
; was the underlying cause of PR13926.
%a0 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 0
%a0b = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 0
%a1 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
%a1b = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
store i32 0, i32* %a0
store i32 1, i32* %a1
; CHECK-NOT: store
switch i32 %x, label %bb0 [ i32 1, label %bb1
i32 2, label %bb2
i32 3, label %bb3
i32 4, label %bb4
i32 5, label %bb5
i32 6, label %bb6
i32 7, label %bb7 ]
bb0:
br label %exit
bb1:
br label %exit
bb2:
br label %exit
bb3:
br label %exit
bb4:
br label %exit
bb5:
br label %exit
bb6:
br label %exit
bb7:
br label %exit
exit:
%phi = phi i32* [ %a1, %bb0 ], [ %a0, %bb1 ], [ %a0, %bb2 ], [ %a1, %bb3 ],
[ %a1b, %bb4 ], [ %a0b, %bb5 ], [ %a0b, %bb6 ], [ %a1b, %bb7 ]
; CHECK: phi i32 [ 1, %{{.*}} ], [ 0, %{{.*}} ], [ 0, %{{.*}} ], [ 1, %{{.*}} ], [ 1, %{{.*}} ], [ 0, %{{.*}} ], [ 0, %{{.*}} ], [ 1, %{{.*}} ]
%result = load i32, i32* %phi
ret i32 %result
}
define i32 @test4() {
; CHECK-LABEL: @test4(
entry:
%a = alloca [2 x i32]
; CHECK-NOT: alloca
%a0 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 0
%a1 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
store i32 0, i32* %a0
store i32 1, i32* %a1
%v0 = load i32, i32* %a0
%v1 = load i32, i32* %a1
; CHECK-NOT: store
; CHECK-NOT: load
%cond = icmp sle i32 %v0, %v1
%select = select i1 %cond, i32* %a0, i32* %a0
; CHECK-NOT: select
%result = load i32, i32* %select
ret i32 %result
; CHECK: ret i32 0
}
define i32 @test5(i32* %b) {
; CHECK-LABEL: @test5(
entry:
%a = alloca [2 x i32]
; CHECK-NOT: alloca
%a1 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
store i32 1, i32* %a1
; CHECK-NOT: store
%select = select i1 true, i32* %a1, i32* %b
; CHECK-NOT: select
%result = load i32, i32* %select
; CHECK-NOT: load
ret i32 %result
; CHECK: ret i32 1
}
declare void @f(i32*, i32*)
define i32 @test6(i32* %b) {
; CHECK-LABEL: @test6(
entry:
%a = alloca [2 x i32]
%c = alloca i32
; CHECK-NOT: alloca
%a1 = getelementptr [2 x i32], [2 x i32]* %a, i64 0, i32 1
store i32 1, i32* %a1
%select = select i1 true, i32* %a1, i32* %b
%select2 = select i1 false, i32* %a1, i32* %b
%select3 = select i1 false, i32* %c, i32* %b
; CHECK: %[[select2:.*]] = select i1 false, i32* undef, i32* %b
; CHECK: %[[select3:.*]] = select i1 false, i32* undef, i32* %b
; Note, this would potentially escape the alloca pointer except for the
; constant folding of the select.
call void @f(i32* %select2, i32* %select3)
; CHECK: call void @f(i32* %[[select2]], i32* %[[select3]])
%result = load i32, i32* %select
; CHECK-NOT: load
%dead = load i32, i32* %c
ret i32 %result
; CHECK: ret i32 1
}
define i32 @test7() {
; CHECK-LABEL: @test7(
; CHECK-NOT: alloca
entry:
%X = alloca i32
br i1 undef, label %good, label %bad
good:
%Y1 = getelementptr i32, i32* %X, i64 0
store i32 0, i32* %Y1
br label %exit
bad:
%Y2 = getelementptr i32, i32* %X, i64 1
store i32 0, i32* %Y2
br label %exit
exit:
%P = phi i32* [ %Y1, %good ], [ %Y2, %bad ]
; CHECK: %[[phi:.*]] = phi i32 [ 0, %good ],
%Z2 = load i32, i32* %P
ret i32 %Z2
; CHECK: ret i32 %[[phi]]
}
define i32 @test8(i32 %b, i32* %ptr) {
; Ensure that we rewrite allocas to the used type when that use is hidden by
; a PHI that can be speculated.
; CHECK-LABEL: @test8(
; CHECK-NOT: alloca
; CHECK-NOT: load
; CHECK: %[[value:.*]] = load i32, i32* %ptr
; CHECK-NOT: load
; CHECK: %[[result:.*]] = phi i32 [ undef, %else ], [ %[[value]], %then ]
; CHECK-NEXT: ret i32 %[[result]]
entry:
%f = alloca float
%test = icmp ne i32 %b, 0
br i1 %test, label %then, label %else
then:
br label %exit
else:
%bitcast = bitcast float* %f to i32*
br label %exit
exit:
%phi = phi i32* [ %bitcast, %else ], [ %ptr, %then ]
%loaded = load i32, i32* %phi, align 4
ret i32 %loaded
}
define i32 @test9(i32 %b, i32* %ptr) {
; Same as @test8 but for a select rather than a PHI node.
; CHECK-LABEL: @test9(
; CHECK-NOT: alloca
; CHECK-NOT: load
; CHECK: %[[value:.*]] = load i32, i32* %ptr
; CHECK-NOT: load
; CHECK: %[[result:.*]] = select i1 %{{.*}}, i32 undef, i32 %[[value]]
; CHECK-NEXT: ret i32 %[[result]]
entry:
%f = alloca float
store i32 0, i32* %ptr
%test = icmp ne i32 %b, 0
%bitcast = bitcast float* %f to i32*
%select = select i1 %test, i32* %bitcast, i32* %ptr
%loaded = load i32, i32* %select, align 4
ret i32 %loaded
}
define float @test10(i32 %b, float* %ptr) {
; Don't try to promote allocas which are not elligible for it even after
; rewriting due to the necessity of inserting bitcasts when speculating a PHI
; node.
; CHECK-LABEL: @test10(
; CHECK: %[[alloca:.*]] = alloca
; CHECK: %[[argvalue:.*]] = load float, float* %ptr
; CHECK: %[[cast:.*]] = bitcast double* %[[alloca]] to float*
; CHECK: %[[allocavalue:.*]] = load float, float* %[[cast]]
; CHECK: %[[result:.*]] = phi float [ %[[allocavalue]], %else ], [ %[[argvalue]], %then ]
; CHECK-NEXT: ret float %[[result]]
entry:
%f = alloca double
store double 0.0, double* %f
%test = icmp ne i32 %b, 0
br i1 %test, label %then, label %else
then:
br label %exit
else:
%bitcast = bitcast double* %f to float*
br label %exit
exit:
%phi = phi float* [ %bitcast, %else ], [ %ptr, %then ]
%loaded = load float, float* %phi, align 4
ret float %loaded
}
define float @test11(i32 %b, float* %ptr) {
; Same as @test10 but for a select rather than a PHI node.
; CHECK-LABEL: @test11(
; CHECK: %[[alloca:.*]] = alloca
; CHECK: %[[cast:.*]] = bitcast double* %[[alloca]] to float*
; CHECK: %[[allocavalue:.*]] = load float, float* %[[cast]]
; CHECK: %[[argvalue:.*]] = load float, float* %ptr
; CHECK: %[[result:.*]] = select i1 %{{.*}}, float %[[allocavalue]], float %[[argvalue]]
; CHECK-NEXT: ret float %[[result]]
entry:
%f = alloca double
store double 0.0, double* %f
store float 0.0, float* %ptr
%test = icmp ne i32 %b, 0
%bitcast = bitcast double* %f to float*
%select = select i1 %test, float* %bitcast, float* %ptr
%loaded = load float, float* %select, align 4
ret float %loaded
}
define i32 @test12(i32 %x, i32* %p) {
; Ensure we don't crash or fail to nuke dead selects of allocas if no load is
; never found.
; CHECK-LABEL: @test12(
; CHECK-NOT: alloca
; CHECK-NOT: select
; CHECK: ret i32 %x
entry:
%a = alloca i32
store i32 %x, i32* %a
%dead = select i1 undef, i32* %a, i32* %p
%load = load i32, i32* %a
ret i32 %load
}
define i32 @test13(i32 %x, i32* %p) {
; Ensure we don't crash or fail to nuke dead phis of allocas if no load is ever
; found.
; CHECK-LABEL: @test13(
; CHECK-NOT: alloca
; CHECK-NOT: phi
; CHECK: ret i32 %x
entry:
%a = alloca i32
store i32 %x, i32* %a
br label %loop
loop:
%phi = phi i32* [ %p, %entry ], [ %a, %loop ]
br i1 undef, label %loop, label %exit
exit:
%load = load i32, i32* %a
ret i32 %load
}
define i32 @test14(i1 %b1, i1 %b2, i32* %ptr) {
; Check for problems when there are both selects and phis and one is
; speculatable toward promotion but the other is not. That should block all of
; the speculation.
; CHECK-LABEL: @test14(
; CHECK: alloca
; CHECK: alloca
; CHECK: select
; CHECK: phi
; CHECK: phi
; CHECK: select
; CHECK: ret i32
entry:
%f = alloca i32
%g = alloca i32
store i32 0, i32* %f
store i32 0, i32* %g
%f.select = select i1 %b1, i32* %f, i32* %ptr
br i1 %b2, label %then, label %else
then:
br label %exit
else:
br label %exit
exit:
%f.phi = phi i32* [ %f, %then ], [ %f.select, %else ]
%g.phi = phi i32* [ %g, %then ], [ %ptr, %else ]
%f.loaded = load i32, i32* %f.phi
%g.select = select i1 %b1, i32* %g, i32* %g.phi
%g.loaded = load i32, i32* %g.select
%result = add i32 %f.loaded, %g.loaded
ret i32 %result
}
define i32 @PR13905() {
; Check a pattern where we have a chain of dead phi nodes to ensure they are
; deleted and promotion can proceed.
; CHECK-LABEL: @PR13905(
; CHECK-NOT: alloca i32
; CHECK: ret i32 undef
entry:
%h = alloca i32
store i32 0, i32* %h
br i1 undef, label %loop1, label %exit
loop1:
%phi1 = phi i32* [ null, %entry ], [ %h, %loop1 ], [ %h, %loop2 ]
br i1 undef, label %loop1, label %loop2
loop2:
br i1 undef, label %loop1, label %exit
exit:
%phi2 = phi i32* [ %phi1, %loop2 ], [ null, %entry ]
ret i32 undef
}
define i32 @PR13906() {
; Another pattern which can lead to crashes due to failing to clear out dead
; PHI nodes or select nodes. This triggers subtly differently from the above
; cases because the PHI node is (recursively) alive, but the select is dead.
; CHECK-LABEL: @PR13906(
; CHECK-NOT: alloca
entry:
%c = alloca i32
store i32 0, i32* %c
br label %for.cond
for.cond:
%d.0 = phi i32* [ undef, %entry ], [ %c, %if.then ], [ %d.0, %for.cond ]
br i1 undef, label %if.then, label %for.cond
if.then:
%tmpcast.d.0 = select i1 undef, i32* %c, i32* %d.0
br label %for.cond
}
define i64 @PR14132(i1 %flag) {
; CHECK-LABEL: @PR14132(
; Here we form a PHI-node by promoting the pointer alloca first, and then in
; order to promote the other two allocas, we speculate the load of the
; now-phi-node-pointer. In doing so we end up loading a 64-bit value from an i8
; alloca. While this is a bit dubious, we were asserting on trying to
; rewrite it. The trick is that the code using the value may carefully take
; steps to only use the not-undef bits, and so we need to at least loosely
; support this..
entry:
%a = alloca i64, align 8
%b = alloca i8, align 8
%ptr = alloca i64*, align 8
; CHECK-NOT: alloca
%ptr.cast = bitcast i64** %ptr to i8**
store i64 0, i64* %a, align 8
store i8 1, i8* %b, align 8
store i64* %a, i64** %ptr, align 8
br i1 %flag, label %if.then, label %if.end
if.then:
store i8* %b, i8** %ptr.cast, align 8
br label %if.end
; CHECK-NOT: store
; CHECK: %[[ext:.*]] = zext i8 1 to i64
if.end:
%tmp = load i64*, i64** %ptr, align 8
%result = load i64, i64* %tmp, align 8
; CHECK-NOT: load
; CHECK: %[[result:.*]] = phi i64 [ %[[ext]], %if.then ], [ 0, %entry ]
ret i64 %result
; CHECK-NEXT: ret i64 %[[result]]
}
define float @PR16687(i64 %x, i1 %flag) {
; CHECK-LABEL: @PR16687(
; Check that even when we try to speculate the same phi twice (in two slices)
; on an otherwise promotable construct, we don't get ahead of ourselves and try
; to promote one of the slices prior to speculating it.
entry:
%a = alloca i64, align 8
store i64 %x, i64* %a
br i1 %flag, label %then, label %else
; CHECK-NOT: alloca
; CHECK-NOT: store
; CHECK: %[[lo:.*]] = trunc i64 %x to i32
; CHECK: %[[shift:.*]] = lshr i64 %x, 32
; CHECK: %[[hi:.*]] = trunc i64 %[[shift]] to i32
then:
%a.f = bitcast i64* %a to float*
br label %end
; CHECK: %[[lo_cast:.*]] = bitcast i32 %[[lo]] to float
else:
%a.raw = bitcast i64* %a to i8*
%a.raw.4 = getelementptr i8, i8* %a.raw, i64 4
%a.raw.4.f = bitcast i8* %a.raw.4 to float*
br label %end
; CHECK: %[[hi_cast:.*]] = bitcast i32 %[[hi]] to float
end:
%a.phi.f = phi float* [ %a.f, %then ], [ %a.raw.4.f, %else ]
%f = load float, float* %a.phi.f
ret float %f
; CHECK: %[[phi:.*]] = phi float [ %[[lo_cast]], %then ], [ %[[hi_cast]], %else ]
; CHECK-NOT: load
; CHECK: ret float %[[phi]]
}
; Verifies we fixed PR20425. We should be able to promote all alloca's to
; registers in this test.
;
; %0 = slice
; %1 = slice
; %2 = phi(%0, %1) // == slice
define float @simplify_phi_nodes_that_equal_slice(i1 %cond, float* %temp) {
; CHECK-LABEL: @simplify_phi_nodes_that_equal_slice(
entry:
%arr = alloca [4 x float], align 4
; CHECK-NOT: alloca
br i1 %cond, label %then, label %else
then:
%0 = getelementptr inbounds [4 x float], [4 x float]* %arr, i64 0, i64 3
store float 1.000000e+00, float* %0, align 4
br label %merge
else:
%1 = getelementptr inbounds [4 x float], [4 x float]* %arr, i64 0, i64 3
store float 2.000000e+00, float* %1, align 4
br label %merge
merge:
%2 = phi float* [ %0, %then ], [ %1, %else ]
store float 0.000000e+00, float* %temp, align 4
%3 = load float, float* %2, align 4
ret float %3
}
; A slightly complicated example for PR20425.
;
; %0 = slice
; %1 = phi(%0) // == slice
; %2 = slice
; %3 = phi(%1, %2) // == slice
define float @simplify_phi_nodes_that_equal_slice_2(i1 %cond, float* %temp) {
; CHECK-LABEL: @simplify_phi_nodes_that_equal_slice_2(
entry:
%arr = alloca [4 x float], align 4
; CHECK-NOT: alloca
br i1 %cond, label %then, label %else
then:
%0 = getelementptr inbounds [4 x float], [4 x float]* %arr, i64 0, i64 3
store float 1.000000e+00, float* %0, align 4
br label %then2
then2:
%1 = phi float* [ %0, %then ]
store float 2.000000e+00, float* %1, align 4
br label %merge
else:
%2 = getelementptr inbounds [4 x float], [4 x float]* %arr, i64 0, i64 3
store float 3.000000e+00, float* %2, align 4
br label %merge
merge:
%3 = phi float* [ %1, %then2 ], [ %2, %else ]
store float 0.000000e+00, float* %temp, align 4
%4 = load float, float* %3, align 4
ret float %4
}
%struct.S = type { i32 }
; Verifies we fixed PR20822. We have a foldable PHI feeding a speculatable PHI
; which requires the rewriting of the speculated PHI to handle insertion
; when the incoming pointer is itself from a PHI node. We would previously
; insert a bitcast instruction *before* a PHI, producing an invalid module;
; make sure we insert *after* the first non-PHI instruction.
define void @PR20822() {
; CHECK-LABEL: @PR20822(
entry:
%f = alloca %struct.S, align 4
; CHECK: %[[alloca:.*]] = alloca
br i1 undef, label %if.end, label %for.cond
for.cond: ; preds = %for.cond, %entry
br label %if.end
if.end: ; preds = %for.cond, %entry
%f2 = phi %struct.S* [ %f, %entry ], [ %f, %for.cond ]
; CHECK: phi i32
; CHECK: %[[cast:.*]] = bitcast i32* %[[alloca]] to %struct.S*
phi i32 [ undef, %entry ], [ undef, %for.cond ]
br i1 undef, label %if.then5, label %if.then2
if.then2: ; preds = %if.end
br label %if.then5
if.then5: ; preds = %if.then2, %if.end
%f1 = phi %struct.S* [ undef, %if.then2 ], [ %f2, %if.end ]
; CHECK: phi {{.*}} %[[cast]]
store %struct.S undef, %struct.S* %f1, align 4
ret void
}
define i32 @phi_align(i32* %z) {
; CHECK-LABEL: @phi_align(
entry:
%a = alloca [8 x i8], align 8
; CHECK: alloca [7 x i8]
%a0x = getelementptr [8 x i8], [8 x i8]* %a, i64 0, i32 1
%a0 = bitcast i8* %a0x to i32*
%a1x = getelementptr [8 x i8], [8 x i8]* %a, i64 0, i32 4
%a1 = bitcast i8* %a1x to i32*
; CHECK: store i32 0, {{.*}}, align 1
store i32 0, i32* %a0, align 1
; CHECK: store i32 1, {{.*}}, align 1
store i32 1, i32* %a1, align 4
; CHECK: load {{.*}}, align 1
%v0 = load i32, i32* %a0, align 1
; CHECK: load {{.*}}, align 1
%v1 = load i32, i32* %a1, align 4
%cond = icmp sle i32 %v0, %v1
br i1 %cond, label %then, label %exit
then:
br label %exit
exit:
; CHECK: %phi = phi i32* [ {{.*}}, %then ], [ %z, %entry ]
; CHECK-NEXT: %result = load i32, i32* %phi, align 1
%phi = phi i32* [ %a1, %then ], [ %z, %entry ]
%result = load i32, i32* %phi, align 4
ret i32 %result
}
; Don't speculate a load based on an earlier volatile operation.
define i8 @volatile_select(i8* %p, i1 %b) {
; CHECK-LABEL: @volatile_select(
; CHECK: select i1 %b, i8* %p, i8* %p2
%p2 = alloca i8
store i8 0, i8* %p2
store volatile i8 0, i8* %p
%px = select i1 %b, i8* %p, i8* %p2
%v2 = load i8, i8* %px
ret i8 %v2
}