summaryrefslogtreecommitdiff
path: root/test/Transforms/TailCallElim/basic.ll
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/TailCallElim/basic.ll')
-rw-r--r--test/Transforms/TailCallElim/basic.ll145
1 files changed, 145 insertions, 0 deletions
diff --git a/test/Transforms/TailCallElim/basic.ll b/test/Transforms/TailCallElim/basic.ll
new file mode 100644
index 0000000000000..35420ab08c33a
--- /dev/null
+++ b/test/Transforms/TailCallElim/basic.ll
@@ -0,0 +1,145 @@
+; RUN: opt < %s -tailcallelim -S | FileCheck %s
+
+declare void @noarg()
+declare void @use(i32*)
+declare void @use_nocapture(i32* nocapture)
+declare void @use2_nocapture(i32* nocapture, i32* nocapture)
+
+; Trivial case. Mark @noarg with tail call.
+define void @test0() {
+; CHECK: tail call void @noarg()
+ call void @noarg()
+ ret void
+}
+
+; PR615. Make sure that we do not move the alloca so that it interferes with the tail call.
+define i32 @test1() {
+; CHECK: i32 @test1()
+; CHECK-NEXT: alloca
+ %A = alloca i32 ; <i32*> [#uses=2]
+ store i32 5, i32* %A
+ call void @use(i32* %A)
+; CHECK: tail call i32 @test1
+ %X = tail call i32 @test1() ; <i32> [#uses=1]
+ ret i32 %X
+}
+
+; This function contains intervening instructions which should be moved out of the way
+define i32 @test2(i32 %X) {
+; CHECK: i32 @test2
+; CHECK-NOT: call
+; CHECK: ret i32
+entry:
+ %tmp.1 = icmp eq i32 %X, 0 ; <i1> [#uses=1]
+ br i1 %tmp.1, label %then.0, label %endif.0
+then.0: ; preds = %entry
+ %tmp.4 = add i32 %X, 1 ; <i32> [#uses=1]
+ ret i32 %tmp.4
+endif.0: ; preds = %entry
+ %tmp.10 = add i32 %X, -1 ; <i32> [#uses=1]
+ %tmp.8 = call i32 @test2(i32 %tmp.10) ; <i32> [#uses=1]
+ %DUMMY = add i32 %X, 1 ; <i32> [#uses=0]
+ ret i32 %tmp.8
+}
+
+; Though this case seems to be fairly unlikely to occur in the wild, someone
+; plunked it into the demo script, so maybe they care about it.
+define i32 @test3(i32 %c) {
+; CHECK: i32 @test3
+; CHECK-NOT: call
+; CHECK: ret i32 0
+entry:
+ %tmp.1 = icmp eq i32 %c, 0 ; <i1> [#uses=1]
+ br i1 %tmp.1, label %return, label %else
+else: ; preds = %entry
+ %tmp.5 = add i32 %c, -1 ; <i32> [#uses=1]
+ %tmp.3 = call i32 @test3(i32 %tmp.5) ; <i32> [#uses=0]
+ ret i32 0
+return: ; preds = %entry
+ ret i32 0
+}
+
+; Make sure that a nocapture pointer does not stop adding a tail call marker to
+; an unrelated call and additionally that we do not mark the nocapture call with
+; a tail call.
+;
+; rdar://14324281
+define void @test4() {
+; CHECK: void @test4
+; CHECK-NOT: tail call void @use_nocapture
+; CHECK: tail call void @noarg()
+; CHECK: ret void
+ %a = alloca i32
+ call void @use_nocapture(i32* %a)
+ call void @noarg()
+ ret void
+}
+
+; Make sure that we do not perform TRE even with a nocapture use. This is due to
+; bad codegen caused by PR962.
+;
+; rdar://14324281.
+define i32* @test5(i32* nocapture %A, i1 %cond) {
+; CHECK: i32* @test5
+; CHECK-NOT: tailrecurse:
+; CHECK: ret i32* null
+ %B = alloca i32
+ br i1 %cond, label %cond_true, label %cond_false
+cond_true:
+ call i32* @test5(i32* %B, i1 false)
+ ret i32* null
+cond_false:
+ call void @use2_nocapture(i32* %A, i32* %B)
+ call void @noarg()
+ ret i32* null
+}
+
+; PR14143: Make sure that we do not mark functions with nocapture allocas with tail.
+;
+; rdar://14324281.
+define void @test6(i32* %a, i32* %b) {
+; CHECK-LABEL: @test6(
+; CHECK-NOT: tail call
+; CHECK: ret void
+ %c = alloca [100 x i8], align 16
+ %tmp = bitcast [100 x i8]* %c to i32*
+ call void @use2_nocapture(i32* %b, i32* %tmp)
+ ret void
+}
+
+; PR14143: Make sure that we do not mark functions with nocapture allocas with tail.
+;
+; rdar://14324281
+define void @test7(i32* %a, i32* %b) nounwind uwtable {
+entry:
+; CHECK-LABEL: @test7(
+; CHECK-NOT: tail call
+; CHECK: ret void
+ %c = alloca [100 x i8], align 16
+ %0 = bitcast [100 x i8]* %c to i32*
+ call void @use2_nocapture(i32* %0, i32* %a)
+ call void @use2_nocapture(i32* %b, i32* %0)
+ ret void
+}
+
+; If we have a mix of escaping captured/non-captured allocas, ensure that we do
+; not do anything including marking callsites with the tail call marker.
+;
+; rdar://14324281.
+define i32* @test8(i32* nocapture %A, i1 %cond) {
+; CHECK: i32* @test8
+; CHECK-NOT: tailrecurse:
+; CHECK-NOT: tail call
+; CHECK: ret i32* null
+ %B = alloca i32
+ %B2 = alloca i32
+ br i1 %cond, label %cond_true, label %cond_false
+cond_true:
+ call void @use(i32* %B2)
+ call i32* @test8(i32* %B, i1 false)
+ ret i32* null
+cond_false:
+ call void @use2_nocapture(i32* %A, i32* %B)
+ call void @noarg()
+ ret i32* null
+}