1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

X86: Don't reset the stack after calls that don't return (PR27117)

Since the calls don't return, the instruction afterwards will never run,
and is just taking up unnecessary space in the binary.

Differential Revision: http://reviews.llvm.org/D20406

llvm-svn: 270109
This commit is contained in:
Hans Wennborg 2016-05-19 20:15:33 +00:00
parent f3a3c62ffb
commit ff73dabfca
3 changed files with 58 additions and 1 deletions

View File

@ -2520,7 +2520,10 @@ public:
RetTy = ResultType;
IsInReg = Call.paramHasAttr(0, Attribute::InReg);
DoesNotReturn = Call.doesNotReturn();
DoesNotReturn =
Call.doesNotReturn() ||
(!Call.isInvoke() &&
isa<UnreachableInst>(Call.getInstruction()->getNextNode()));
IsVarArg = FTy->isVarArg();
IsReturnValueUsed = !Call.getInstruction()->use_empty();
RetSExt = Call.paramHasAttr(0, Attribute::SExt);

View File

@ -3380,6 +3380,12 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
else
NumBytesForCalleeToPop = 0; // Callee pops nothing.
if (CLI.DoesNotReturn && !getTargetMachine().Options.TrapUnreachable) {
// No need to reset the stack after the call if the call doesn't return. To
// make the MI verify, we'll pretend the callee does it for us.
NumBytesForCalleeToPop = NumBytes;
}
// Returns a flag for retval copy to use.
if (!IsSibcall) {
Chain = DAG.getCALLSEQ_END(Chain,

View File

@ -0,0 +1,48 @@
; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck %s
define void @test1(i32 %c) {
; CHECK-LABEL: test1:
entry:
%0 = alloca i8, i32 %c
%tobool = icmp eq i32 %c, 0
br i1 %tobool, label %if.end, label %if.then
if.end:
call void @g(i8* %0)
ret void
if.then:
call void @crash(i8* %0)
unreachable
; CHECK: calll _crash
; There is no need to adjust the stack after the call, since
; the function is noreturn and that code will therefore never run.
; CHECK-NOT: add
; CHECK-NOT: pop
}
define void @test2(i32 %c) {
; CHECK-LABEL: test2:
entry:
%0 = alloca i8, i32 %c
%tobool = icmp eq i32 %c, 0
br i1 %tobool, label %if.end, label %if.then
if.end:
call void @g(i8* %0)
ret void
if.then:
call void @crash2(i8* %0)
unreachable
; CHECK: calll _crash2
; Even though _crash2 is not marked noreturn, it is in practice because
; of the "unreachable" right after it. This happens e.g. when falling off
; a non-void function after a call.
; CHECK-NOT: add
; CHECK-NOT: pop
}
declare void @crash(i8*) noreturn
declare void @crash2(i8*)
declare void @g(i8*)