Skip to content

Commit

Permalink
[InstCombine] Don't strip function type casts from musttail calls
Browse files Browse the repository at this point in the history
Summary:
The cast simplifications that instcombine does here do not make any
attempt to obey the verifier rules for musttail calls. Therefore we have
to disable them.

Reviewers: efriedma, majnemer, pcc

Subscribers: hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D45186

llvm-svn: 329027
rnk committed Apr 2, 2018
1 parent 637fd44 commit 298ffc6
Showing 2 changed files with 42 additions and 1 deletion.
11 changes: 10 additions & 1 deletion llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
@@ -3996,10 +3996,19 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
if (!Callee)
return false;

// The prototype of a thunk is a lie. Don't directly call such a function.
// If this is a call to a thunk function, don't remove the cast. Thunks are
// used to transparently forward all incoming parameters and outgoing return
// values, so it's important to leave the cast in place.
if (Callee->hasFnAttribute("thunk"))
return false;

// If this is a musttail call, the callee's prototype must match the caller's
// prototype with the exception of pointee types. The code below doesn't
// implement that, so we can't do this transform.
// TODO: Do the transform if it only requires adding pointer casts.
if (CS.isMustTailCall())
return false;

Instruction *Caller = CS.getInstruction();
const AttributeList &CallerPAL = CS.getAttributes();

32 changes: 32 additions & 0 deletions llvm/test/Transforms/InstCombine/musttail-thunk.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
; RUN: opt -instcombine -S < %s | FileCheck %s

; These are both direct calls, but make sure instcombine leaves the casts
; alone.

define i32 @call_thunk(i32 %x, i32 %y) {
%r = call i32 bitcast (void (i32, ...)* @inc_first_arg_thunk to i32 (i32, i32)*)(i32 %x, i32 %y)
ret i32 %r
}

; CHECK-LABEL: define i32 @call_thunk(i32 %x, i32 %y)
; CHECK: %r = call i32 bitcast (void (i32, ...)* @inc_first_arg_thunk to i32 (i32, i32)*)(i32 %x, i32 %y)
; CHECK: ret i32 %r

define internal void @inc_first_arg_thunk(i32 %arg1, ...) #0 {
entry:
%inc = add i32 %arg1, 1
musttail call void (i32, ...) bitcast (i32 (i32, i32)* @plus to void (i32, ...)*)(i32 %inc, ...)
ret void
}

; CHECK-LABEL: define internal void @inc_first_arg_thunk(i32 %arg1, ...) #0
; CHECK: %inc = add i32 %arg1, 1
; CHECK: musttail call void (i32, ...) bitcast (i32 (i32, i32)* @plus to void (i32, ...)*)(i32 %inc, ...)
; CHECK: ret void

define internal i32 @plus(i32 %x, i32 %y) {
%r = add i32 %x, %y
ret i32 %r
}

attributes #0 = { "thunk" }

0 comments on commit 298ffc6

Please sign in to comment.