mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Add 'notail' marker for call instructions.
This marker prevents optimization passes from adding 'tail' or 'musttail' markers to a call. Is is used to prevent tail call optimization from being performed on the call. rdar://problem/22667622 Differential Revision: http://reviews.llvm.org/D12923 llvm-svn: 252368
This commit is contained in:
parent
8f0fab0cec
commit
a73e1a6ef3
@ -8386,7 +8386,7 @@ Syntax:
|
||||
|
||||
::
|
||||
|
||||
<result> = [tail | musttail] call [cconv] [ret attrs] <ty> [<fnty>*] <fnptrval>(<function args>) [fn attrs]
|
||||
<result> = [tail | musttail | notail ] call [cconv] [ret attrs] <ty> [<fnty>*] <fnptrval>(<function args>) [fn attrs]
|
||||
[ operand bundles ]
|
||||
|
||||
Overview:
|
||||
@ -8439,6 +8439,10 @@ This instruction requires several arguments:
|
||||
- `Platform-specific constraints are
|
||||
met. <CodeGenerator.html#tailcallopt>`_
|
||||
|
||||
#. The optional ``notail`` marker indicates that the optimizers should not add
|
||||
``tail`` or ``musttail`` markers to the call. It is used to prevent tail
|
||||
call optimization from being performed on the call.
|
||||
|
||||
#. The optional "cconv" marker indicates which :ref:`calling
|
||||
convention <callingconv>` the call should use. If none is
|
||||
specified, the call defaults to using C calling conventions. The
|
||||
|
@ -1489,16 +1489,21 @@ public:
|
||||
}
|
||||
|
||||
// Note that 'musttail' implies 'tail'.
|
||||
enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 };
|
||||
enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2,
|
||||
TCK_NoTail = 3 };
|
||||
TailCallKind getTailCallKind() const {
|
||||
return TailCallKind(getSubclassDataFromInstruction() & 3);
|
||||
}
|
||||
bool isTailCall() const {
|
||||
return (getSubclassDataFromInstruction() & 3) != TCK_None;
|
||||
unsigned Kind = getSubclassDataFromInstruction() & 3;
|
||||
return Kind == TCK_Tail || Kind == TCK_MustTail;
|
||||
}
|
||||
bool isMustTailCall() const {
|
||||
return (getSubclassDataFromInstruction() & 3) == TCK_MustTail;
|
||||
}
|
||||
bool isNoTailCall() const {
|
||||
return (getSubclassDataFromInstruction() & 3) == TCK_NoTail;
|
||||
}
|
||||
void setTailCall(bool isTC = true) {
|
||||
setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) |
|
||||
unsigned(isTC ? TCK_Tail : TCK_None));
|
||||
|
@ -527,6 +527,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(caller);
|
||||
KEYWORD(tail);
|
||||
KEYWORD(musttail);
|
||||
KEYWORD(notail);
|
||||
KEYWORD(target);
|
||||
KEYWORD(triple);
|
||||
KEYWORD(unwind);
|
||||
|
@ -4830,6 +4830,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
||||
case lltok::kw_call: return ParseCall(Inst, PFS, CallInst::TCK_None);
|
||||
case lltok::kw_tail: return ParseCall(Inst, PFS, CallInst::TCK_Tail);
|
||||
case lltok::kw_musttail: return ParseCall(Inst, PFS, CallInst::TCK_MustTail);
|
||||
case lltok::kw_notail: return ParseCall(Inst, PFS, CallInst::TCK_NoTail);
|
||||
// Memory.
|
||||
case lltok::kw_alloca: return ParseAlloc(Inst, PFS);
|
||||
case lltok::kw_load: return ParseLoad(Inst, PFS);
|
||||
|
@ -54,6 +54,7 @@ namespace lltok {
|
||||
kw_caller,
|
||||
kw_tail,
|
||||
kw_musttail,
|
||||
kw_notail,
|
||||
kw_target,
|
||||
kw_triple,
|
||||
kw_unwind,
|
||||
|
@ -5002,6 +5002,8 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
|
||||
TCK = CallInst::TCK_Tail;
|
||||
if (CCInfo & (1 << 14))
|
||||
TCK = CallInst::TCK_MustTail;
|
||||
if (CCInfo & (1 << 16))
|
||||
TCK = CallInst::TCK_NoTail;
|
||||
cast<CallInst>(I)->setTailCallKind(TCK);
|
||||
cast<CallInst>(I)->setAttributes(PAL);
|
||||
break;
|
||||
|
@ -2131,7 +2131,8 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
|
||||
|
||||
Vals.push_back(VE.getAttributeID(CI.getAttributes()));
|
||||
Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall()) |
|
||||
unsigned(CI.isMustTailCall()) << 14 | 1 << 15);
|
||||
unsigned(CI.isMustTailCall()) << 14 | 1 << 15 |
|
||||
unsigned(CI.isNoTailCall()) << 16);
|
||||
Vals.push_back(VE.getTypeID(FTy));
|
||||
PushValueAndType(CI.getCalledValue(), InstID, Vals, VE); // Callee
|
||||
|
||||
|
@ -2768,6 +2768,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
||||
Out << "musttail ";
|
||||
else if (CI->isTailCall())
|
||||
Out << "tail ";
|
||||
else if (CI->isNoTailCall())
|
||||
Out << "notail ";
|
||||
}
|
||||
|
||||
// Print out the opcode...
|
||||
|
@ -304,7 +304,9 @@ bool TailCallElim::markTails(Function &F, bool &AllCallsAreTailCalls) {
|
||||
if (!CI || CI->isTailCall())
|
||||
continue;
|
||||
|
||||
if (CI->doesNotAccessMemory()) {
|
||||
bool IsNoTail = CI->isNoTailCall();
|
||||
|
||||
if (!IsNoTail && CI->doesNotAccessMemory()) {
|
||||
// A call to a readnone function whose arguments are all things computed
|
||||
// outside this function can be marked tail. Even if you stored the
|
||||
// alloca address into a global, a readnone function can't load the
|
||||
@ -332,7 +334,7 @@ bool TailCallElim::markTails(Function &F, bool &AllCallsAreTailCalls) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) {
|
||||
if (!IsNoTail && Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) {
|
||||
DeferredTails.push_back(CI);
|
||||
} else {
|
||||
AllCallsAreTailCalls = false;
|
||||
|
@ -1144,6 +1144,13 @@ define void @instructions.call_musttail(i8* inalloca %val) {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @instructions.call_notail() {
|
||||
notail call void @f1()
|
||||
; CHECK: notail call void @f1()
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @instructions.landingpad() personality i32 -2 {
|
||||
invoke void @llvm.donothing() to label %proceed unwind label %catch1
|
||||
invoke void @llvm.donothing() to label %proceed unwind label %catch2
|
||||
|
24
test/Transforms/TailCallElim/notail.ll
Normal file
24
test/Transforms/TailCallElim/notail.ll
Normal file
@ -0,0 +1,24 @@
|
||||
; RUN: opt < %s -tailcallelim -S | FileCheck %s
|
||||
|
||||
; CHECK: tail call void @callee0()
|
||||
; CHECK: notail call void @callee1()
|
||||
|
||||
define void @foo1(i32 %a) {
|
||||
entry:
|
||||
%tobool = icmp eq i32 %a, 0
|
||||
br i1 %tobool, label %if.else, label %if.then
|
||||
|
||||
if.then:
|
||||
call void @callee0()
|
||||
br label %if.end
|
||||
|
||||
if.else:
|
||||
notail call void @callee1()
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @callee0()
|
||||
declare void @callee1()
|
Loading…
x
Reference in New Issue
Block a user