summaryrefslogtreecommitdiffstats
path: root/test/Transforms/DeadArgElim
diff options
context:
space:
mode:
authorShih-wei Liao <sliao@google.com>2010-02-10 11:10:31 -0800
committerShih-wei Liao <sliao@google.com>2010-02-10 11:10:31 -0800
commite264f62ca09a8f65c87a46d562a4d0f9ec5d457e (patch)
tree59e3d57ef656cef79afa708ae0a3daf25cd91fcf /test/Transforms/DeadArgElim
downloadexternal_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.zip
external_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.tar.gz
external_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.tar.bz2
Check in LLVM r95781.
Diffstat (limited to 'test/Transforms/DeadArgElim')
-rw-r--r--test/Transforms/DeadArgElim/2006-06-27-struct-ret.ll11
-rw-r--r--test/Transforms/DeadArgElim/2007-02-07-FuncRename.ll11
-rw-r--r--test/Transforms/DeadArgElim/2007-10-18-VarargsReturn.ll12
-rw-r--r--test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll20
-rw-r--r--test/Transforms/DeadArgElim/2008-01-16-VarargsParamAttrs.ll31
-rw-r--r--test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll23
-rw-r--r--test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll26
-rw-r--r--test/Transforms/DeadArgElim/basictest.ll36
-rw-r--r--test/Transforms/DeadArgElim/canon.ll24
-rw-r--r--test/Transforms/DeadArgElim/dead_vaargs.ll12
-rw-r--r--test/Transforms/DeadArgElim/deadretval.ll18
-rw-r--r--test/Transforms/DeadArgElim/deadretval2.ll59
-rw-r--r--test/Transforms/DeadArgElim/dg.exp3
-rw-r--r--test/Transforms/DeadArgElim/keepalive.ll30
-rw-r--r--test/Transforms/DeadArgElim/multdeadretval.ll68
15 files changed, 384 insertions, 0 deletions
diff --git a/test/Transforms/DeadArgElim/2006-06-27-struct-ret.ll b/test/Transforms/DeadArgElim/2006-06-27-struct-ret.ll
new file mode 100644
index 0000000..fac6dd2
--- /dev/null
+++ b/test/Transforms/DeadArgElim/2006-06-27-struct-ret.ll
@@ -0,0 +1,11 @@
+; RUN: opt < %s -deadargelim -disable-output
+
+define internal void @build_delaunay({ i32 }* sret %agg.result) {
+ ret void
+}
+
+define void @test() {
+ call void @build_delaunay( { i32 }* sret null )
+ ret void
+}
+
diff --git a/test/Transforms/DeadArgElim/2007-02-07-FuncRename.ll b/test/Transforms/DeadArgElim/2007-02-07-FuncRename.ll
new file mode 100644
index 0000000..d5bd6c4
--- /dev/null
+++ b/test/Transforms/DeadArgElim/2007-02-07-FuncRename.ll
@@ -0,0 +1,11 @@
+; RUN: opt < %s -deadargelim -S | grep {@test(}
+; RUN: opt < %s -deadargelim -S | not grep dead
+
+define internal i32 @test(i32 %X, i32 %dead) {
+ ret i32 %X
+}
+
+define i32 @caller() {
+ %A = call i32 @test(i32 123, i32 456)
+ ret i32 %A
+}
diff --git a/test/Transforms/DeadArgElim/2007-10-18-VarargsReturn.ll b/test/Transforms/DeadArgElim/2007-10-18-VarargsReturn.ll
new file mode 100644
index 0000000..d4edce9
--- /dev/null
+++ b/test/Transforms/DeadArgElim/2007-10-18-VarargsReturn.ll
@@ -0,0 +1,12 @@
+; RUN: opt < %s -deadargelim -S | not grep {ret i32 0}
+; PR1735
+
+define internal i32 @test(i32 %A, ...) {
+ ret i32 %A
+}
+
+define i32 @foo() {
+ %A = call i32(i32, ...)* @test(i32 1)
+ ret i32 %A
+}
+
diff --git a/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll b/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll
new file mode 100644
index 0000000..0e9c4f7
--- /dev/null
+++ b/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll
@@ -0,0 +1,20 @@
+; RUN: opt < %s -deadargelim -S > %t
+; RUN: cat %t | grep nounwind | count 2
+; RUN: cat %t | grep signext | count 2
+; RUN: cat %t | not grep inreg
+; RUN: cat %t | not grep zeroext
+; RUN: cat %t | not grep byval
+
+ %struct = type { }
+
+@g = global i8 0
+
+define internal i8 @foo(i8* inreg %p, i8 signext %y, ... ) zeroext nounwind {
+ store i8 %y, i8* @g
+ ret i8 0
+}
+
+define i32 @bar() {
+ %A = call i8(i8*, i8, ...)* @foo(i8* inreg null, i8 signext 1, %struct* byval null ) zeroext nounwind
+ ret i32 0
+}
diff --git a/test/Transforms/DeadArgElim/2008-01-16-VarargsParamAttrs.ll b/test/Transforms/DeadArgElim/2008-01-16-VarargsParamAttrs.ll
new file mode 100644
index 0000000..93282f7
--- /dev/null
+++ b/test/Transforms/DeadArgElim/2008-01-16-VarargsParamAttrs.ll
@@ -0,0 +1,31 @@
+; RUN: opt < %s -deadargelim -S | grep byval
+
+ %struct.point = type { double, double }
+@pts = global [4 x %struct.point] [ %struct.point { double 1.000000e+00, double 2.000000e+00 }, %struct.point { double 3.000000e+00, double 4.000000e+00 }, %struct.point { double 5.000000e+00, double 6.000000e+00 }, %struct.point { double 7.000000e+00, double 8.000000e+00 } ], align 32 ; <[4 x %struct.point]*> [#uses=1]
+
+define internal i32 @va1(i32 %nargs, ...) {
+entry:
+ %pi = alloca %struct.point ; <%struct.point*> [#uses=0]
+ %args = alloca i8* ; <i8**> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ %args1 = bitcast i8** %args to i8* ; <i8*> [#uses=1]
+ call void @llvm.va_start( i8* %args1 )
+ %args41 = bitcast i8** %args to i8* ; <i8*> [#uses=1]
+ call void @llvm.va_end( i8* %args41 )
+ ret i32 undef
+}
+
+declare void @llvm.va_start(i8*) nounwind
+
+declare void @llvm.va_end(i8*) nounwind
+
+define i32 @main() {
+entry:
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ %tmp = getelementptr [4 x %struct.point]* @pts, i32 0, i32 0 ; <%struct.point*> [#uses=1]
+ %tmp1 = call i32 (i32, ...)* @va1( i32 1, %struct.point* byval %tmp ) nounwind ; <i32> [#uses=0]
+ call void @exit( i32 0 ) noreturn nounwind
+ unreachable
+}
+
+declare void @exit(i32) noreturn nounwind
diff --git a/test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll b/test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll
new file mode 100644
index 0000000..adfd019
--- /dev/null
+++ b/test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll
@@ -0,0 +1,23 @@
+; RUN: opt < %s -deadargelim -die -S > %t
+; RUN: cat %t | grep 123
+
+; This test tries to catch wrongful removal of return values for a specific case
+; that was break llvm-gcc builds.
+
+; This function has a live return value, it is used by @alive.
+define internal i32 @test5() {
+ ret i32 123
+}
+
+; This function doesn't use the return value @test5 and tries to lure DAE into
+; marking @test5's return value dead because only this call is unused.
+define i32 @dead() {
+ %DEAD = call i32 @test5()
+ ret i32 0
+}
+
+; This function ensures the retval of @test5 is live.
+define i32 @alive() {
+ %LIVE = call i32 @test5()
+ ret i32 %LIVE
+}
diff --git a/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll b/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll
new file mode 100644
index 0000000..f251d6c
--- /dev/null
+++ b/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll
@@ -0,0 +1,26 @@
+; RUN: opt < %s -deadargelim | llvm-dis
+; PR3807
+
+define internal { i32, i32 } @foo() {
+ ret {i32,i32} {i32 42, i32 4}
+}
+
+define i32 @bar() {
+ %x = invoke {i32,i32} @foo() to label %T unwind label %T2
+T:
+ %y = extractvalue {i32,i32} %x, 1
+ ret i32 %y
+T2:
+ unreachable
+}
+
+define i32 @bar2() {
+entry:
+ %x = invoke {i32,i32} @foo() to label %T unwind label %T2
+T:
+ %PN = phi i32 [0, %entry]
+ %y = extractvalue {i32,i32} %x, 1
+ ret i32 %y
+T2:
+ unreachable
+} \ No newline at end of file
diff --git a/test/Transforms/DeadArgElim/basictest.ll b/test/Transforms/DeadArgElim/basictest.ll
new file mode 100644
index 0000000..9ac2222
--- /dev/null
+++ b/test/Transforms/DeadArgElim/basictest.ll
@@ -0,0 +1,36 @@
+; RUN: opt < %s -deadargelim -S | not grep DEADARG
+
+; test - an obviously dead argument
+define internal i32 @test(i32 %v, i32 %DEADARG1, i32* %p) {
+ store i32 %v, i32* %p
+ ret i32 %v
+}
+
+; hardertest - an argument which is only used by a call of a function with a
+; dead argument.
+define internal i32 @hardertest(i32 %DEADARG2) {
+ %p = alloca i32 ; <i32*> [#uses=1]
+ %V = call i32 @test( i32 5, i32 %DEADARG2, i32* %p ) ; <i32> [#uses=1]
+ ret i32 %V
+}
+
+; evenhardertest - recursive dead argument...
+define internal void @evenhardertest(i32 %DEADARG3) {
+ call void @evenhardertest( i32 %DEADARG3 )
+ ret void
+}
+
+define internal void @needarg(i32 %TEST) {
+ call i32 @needarg2( i32 %TEST ) ; <i32>:1 [#uses=0]
+ ret void
+}
+
+define internal i32 @needarg2(i32 %TEST) {
+ ret i32 %TEST
+}
+
+define internal void @needarg3(i32 %TEST3) {
+ call void @needarg( i32 %TEST3 )
+ ret void
+}
+
diff --git a/test/Transforms/DeadArgElim/canon.ll b/test/Transforms/DeadArgElim/canon.ll
new file mode 100644
index 0000000..11cd482
--- /dev/null
+++ b/test/Transforms/DeadArgElim/canon.ll
@@ -0,0 +1,24 @@
+; This test shows a few canonicalizations made by deadargelim
+; RUN: opt < %s -deadargelim -S > %t
+; This test should remove {} and replace it with void
+; RUN: cat %t | grep {define internal void @test}
+; This test shouls replace the {i32} return value with just i32
+; RUN: cat %t | grep {define internal i32 @test2}
+
+define internal {} @test() {
+ ret {} undef
+}
+
+define internal {i32} @test2() {
+ ret {i32} undef
+}
+
+define void @caller() {
+ call {} @test()
+ %X = call {i32} @test2()
+ %Y = extractvalue {i32} %X, 0
+ call void @user(i32 %Y, {i32} %X)
+ ret void
+}
+
+declare void @user(i32, {i32})
diff --git a/test/Transforms/DeadArgElim/dead_vaargs.ll b/test/Transforms/DeadArgElim/dead_vaargs.ll
new file mode 100644
index 0000000..db3135c
--- /dev/null
+++ b/test/Transforms/DeadArgElim/dead_vaargs.ll
@@ -0,0 +1,12 @@
+; RUN: opt < %s -deadargelim -S | not grep 47
+; RUN: opt < %s -deadargelim -S | not grep 1.0
+
+define i32 @bar(i32 %A) {
+ %tmp4 = tail call i32 (i32, ...)* @foo( i32 %A, i32 %A, i32 %A, i32 %A, i64 47, double 1.000000e+00 ) ; <i32> [#uses=1]
+ ret i32 %tmp4
+}
+
+define internal i32 @foo(i32 %X, ...) {
+ ret i32 %X
+}
+
diff --git a/test/Transforms/DeadArgElim/deadretval.ll b/test/Transforms/DeadArgElim/deadretval.ll
new file mode 100644
index 0000000..5f3817c
--- /dev/null
+++ b/test/Transforms/DeadArgElim/deadretval.ll
@@ -0,0 +1,18 @@
+; RUN: opt < %s -deadargelim -S | not grep DEAD
+
+; Dead arg only used by dead retval
+define internal i32 @test(i32 %DEADARG) {
+ ret i32 %DEADARG
+}
+
+define i32 @test2(i32 %A) {
+ %DEAD = call i32 @test( i32 %A ) ; <i32> [#uses=0]
+ ret i32 123
+}
+
+define i32 @test3() {
+ %X = call i32 @test2( i32 3232 ) ; <i32> [#uses=1]
+ %Y = add i32 %X, -123 ; <i32> [#uses=1]
+ ret i32 %Y
+}
+
diff --git a/test/Transforms/DeadArgElim/deadretval2.ll b/test/Transforms/DeadArgElim/deadretval2.ll
new file mode 100644
index 0000000..dcdc36e
--- /dev/null
+++ b/test/Transforms/DeadArgElim/deadretval2.ll
@@ -0,0 +1,59 @@
+; RUN: opt < %s -deadargelim -die -S > %t
+; RUN: cat %t | not grep DEAD
+; RUN: cat %t | grep LIVE | count 4
+
+@P = external global i32 ; <i32*> [#uses=1]
+
+; Dead arg only used by dead retval
+define internal i32 @test(i32 %DEADARG) {
+ ret i32 %DEADARG
+}
+
+define internal i32 @test2(i32 %DEADARG) {
+ %DEADRETVAL = call i32 @test( i32 %DEADARG ) ; <i32> [#uses=1]
+ ret i32 %DEADRETVAL
+}
+
+define void @test3(i32 %X) {
+ %DEADRETVAL = call i32 @test2( i32 %X ) ; <i32> [#uses=0]
+ ret void
+}
+
+define internal i32 @foo() {
+ %DEAD = load i32* @P ; <i32> [#uses=1]
+ ret i32 %DEAD
+}
+
+define internal i32 @id(i32 %X) {
+ ret i32 %X
+}
+
+define void @test4() {
+ %DEAD = call i32 @foo( ) ; <i32> [#uses=1]
+ %DEAD2 = call i32 @id( i32 %DEAD ) ; <i32> [#uses=0]
+ ret void
+}
+
+; These test if returning another functions return value properly marks that
+; other function's return value as live. We do this twice, with the functions in
+; different orders (ie, first the caller, than the callee and first the callee
+; and then the caller) since DAE processes functions one by one and handles
+; these cases slightly different.
+
+define internal i32 @test5() {
+ ret i32 123
+}
+
+define i32 @test6() {
+ %LIVE = call i32 @test5()
+ ret i32 %LIVE
+}
+
+define i32 @test7() {
+ %LIVE = call i32 @test8()
+ ret i32 %LIVE
+}
+
+define internal i32 @test8() {
+ ret i32 124
+}
diff --git a/test/Transforms/DeadArgElim/dg.exp b/test/Transforms/DeadArgElim/dg.exp
new file mode 100644
index 0000000..f200589
--- /dev/null
+++ b/test/Transforms/DeadArgElim/dg.exp
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
diff --git a/test/Transforms/DeadArgElim/keepalive.ll b/test/Transforms/DeadArgElim/keepalive.ll
new file mode 100644
index 0000000..b0b9bf3
--- /dev/null
+++ b/test/Transforms/DeadArgElim/keepalive.ll
@@ -0,0 +1,30 @@
+; RUN: opt < %s -deadargelim -S > %t
+; RUN: grep {define internal zeroext i32 @test1() nounwind} %t
+; RUN: grep {define internal %Ty @test2} %t
+
+%Ty = type <{ i32, i32 }>
+
+; Check if the pass doesn't modify anything that doesn't need changing. We feed
+; an unused argument to each function to lure it into changing _something_ about
+; the function and then changing too much.
+
+; This checks if the return value attributes are not removed
+define internal zeroext i32 @test1(i32 %DEADARG1) nounwind {
+ ret i32 1
+}
+
+; This checks if the struct doesn't get non-packed
+define internal <{ i32, i32 }> @test2(i32 %DEADARG1) {
+ ret <{ i32, i32 }> <{ i32 1, i32 2 }>
+}
+
+; We use this external function to make sure the return values don't become dead
+declare void @user(i32, <{ i32, i32 }>)
+
+define void @caller() {
+ %B = call i32 @test1(i32 1)
+ %C = call <{ i32, i32 }> @test2(i32 2)
+ call void @user(i32 %B, <{ i32, i32 }> %C)
+ ret void
+}
+
diff --git a/test/Transforms/DeadArgElim/multdeadretval.ll b/test/Transforms/DeadArgElim/multdeadretval.ll
new file mode 100644
index 0000000..68d96ee
--- /dev/null
+++ b/test/Transforms/DeadArgElim/multdeadretval.ll
@@ -0,0 +1,68 @@
+; This test sees if return values (and arguments) are properly removed when they
+; are unused. All unused values are typed i16, so we can easily check. We also
+; run instcombine to fold insert/extractvalue chains and we run dce to clean up
+; any remaining dead stuff.
+; RUN: opt < %s -deadargelim -instcombine -dce -S | not grep i16
+
+define internal {i16, i32} @test(i16 %DEADARG) {
+ %A = insertvalue {i16,i32} undef, i16 1, 0
+ %B = insertvalue {i16,i32} %A, i32 1001, 1
+ ret {i16,i32} %B
+}
+
+define internal {i32, i16} @test2() {
+ %DEAD = call i16 @test4()
+ %A = insertvalue {i32,i16} undef, i32 1, 0
+ %B = insertvalue {i32,i16} %A, i16 %DEAD, 1
+ ret {i32,i16} %B
+}
+
+; Dead argument, used to check if the second result of test2 is dead even when
+; it's used as a dead argument
+define internal i32 @test3(i16 %A) {
+ %ret = call {i16, i32} @test( i16 %A ) ; <i32> [#uses=0]
+ %DEAD = extractvalue {i16, i32} %ret, 0
+ %LIVE = extractvalue {i16, i32} %ret, 1
+ ret i32 %LIVE
+}
+
+define internal i16 @test4() {
+ ret i16 0
+}
+
+; Multiple return values, multiple live return values
+define internal {i32, i32, i16} @test5() {
+ %A = insertvalue {i32,i32,i16} undef, i32 1, 0
+ %B = insertvalue {i32,i32,i16} %A, i32 2, 1
+ %C = insertvalue {i32,i32,i16} %B, i16 3, 2
+ ret {i32, i32, i16} %C
+}
+
+; Nested return values
+define internal {{i32}, {i16, i16}} @test6() {
+ %A = insertvalue {{i32}, {i16, i16}} undef, i32 1, 0, 0
+ %B = insertvalue {{i32}, {i16, i16}} %A, i16 2, 1, 0
+ %C = insertvalue {{i32}, {i16, i16}} %B, i16 3, 1, 1
+ ret {{i32}, {i16, i16}} %C
+}
+
+define i32 @main() {
+ %ret = call {i32, i16} @test2() ; <i32> [#uses=1]
+ %LIVE = extractvalue {i32, i16} %ret, 0
+ %DEAD = extractvalue {i32, i16} %ret, 1
+ %Y = add i32 %LIVE, -123 ; <i32> [#uses=1]
+ %LIVE2 = call i32 @test3(i16 %DEAD) ; <i32> [#uses=1]
+ %Z = add i32 %LIVE2, %Y ; <i32> [#uses=1]
+ %ret1 = call { i32, i32, i16 } @test5 ()
+ %LIVE3 = extractvalue { i32, i32, i16} %ret1, 0
+ %LIVE4 = extractvalue { i32, i32, i16} %ret1, 1
+ %DEAD2 = extractvalue { i32, i32, i16} %ret1, 2
+ %V = add i32 %LIVE3, %LIVE4
+ %W = add i32 %Z, %V
+ %ret2 = call { { i32 }, { i16, i16 } } @test6 ()
+ %LIVE5 = extractvalue { { i32 }, { i16, i16 } } %ret2, 0, 0
+ %DEAD3 = extractvalue { { i32 }, { i16, i16 } } %ret2, 1, 0
+ %DEAD4 = extractvalue { { i32 }, { i16, i16 } } %ret2, 1, 1
+ %Q = add i32 %W, %LIVE5
+ ret i32 %Q
+}