return false;
// Okay, we know we can transform this function if safe. Scan its body
- // looking for calls to llvm.vastart.
+ // looking for calls marked musttail or calls to llvm.vastart.
for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
+ CallInst *CI = dyn_cast<CallInst>(I);
+ if (!CI)
+ continue;
+ if (CI->isMustTailCall())
+ return false;
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
if (II->getIntrinsicID() == Intrinsic::vastart)
return false;
}
-; RUN: opt < %s -deadargelim -S | not grep 47
-; RUN: opt < %s -deadargelim -S | not grep 1.0
+; RUN: opt < %s -deadargelim -S | FileCheck %s
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
+ call void (i32, ...)* @thunk(i32 %A, i64 47, double 1.000000e+00)
+ %a = call i32 (i32, ...)* @has_vastart(i32 %A, i64 47, double 1.000000e+00)
+ %b = call i32 (i32, ...)* @no_vastart( i32 %A, i32 %A, i32 %A, i32 %A, i64 47, double 1.000000e+00 )
+ %c = add i32 %a, %b
+ ret i32 %c
}
+; CHECK-LABEL: define i32 @bar
+; CHECK: call void (i32, ...)* @thunk(i32 %A, i64 47, double 1.000000e+00)
+; CHECK: call i32 (i32, ...)* @has_vastart(i32 %A, i64 47, double 1.000000e+00)
+; CHECK: call i32 @no_vastart(i32 %A)
-define internal i32 @foo(i32 %X, ...) {
- ret i32 %X
+declare void @thunk_target(i32 %X, ...)
+
+define internal void @thunk(i32 %X, ...) {
+ musttail call void(i32, ...)* @thunk_target(i32 %X, ...)
+ ret void
+}
+; CHECK-LABEL: define internal void @thunk(i32 %X, ...)
+; CHECK: musttail call void (i32, ...)* @thunk_target(i32 %X, ...)
+
+define internal i32 @has_vastart(i32 %X, ...) {
+ %valist = alloca i8
+ call void @llvm.va_start(i8* %valist)
+ ret i32 %X
}
+; CHECK-LABEL: define internal i32 @has_vastart(i32 %X, ...)
+declare void @llvm.va_start(i8*)
+
+define internal i32 @no_vastart(i32 %X, ...) {
+ ret i32 %X
+}
+; CHECK-LABEL: define internal i32 @no_vastart(i32 %X)