summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2016-05-19 20:15:33 +0000
committerHans Wennborg <hans@hanshq.net>2016-05-19 20:15:33 +0000
commit172eee9cfc1a7963aded8b29784b9d9190c1d6b0 (patch)
tree1391607593abb6402e3cfd9c83f9dd7f076fceef
parent3650bbeebc07f3d4cfd026bbb5088432bb1766e6 (diff)
downloadbcm5719-llvm-172eee9cfc1a7963aded8b29784b9d9190c1d6b0.tar.gz
bcm5719-llvm-172eee9cfc1a7963aded8b29784b9d9190c1d6b0.zip
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
-rw-r--r--llvm/include/llvm/Target/TargetLowering.h5
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp6
-rw-r--r--llvm/test/CodeGen/X86/noreturn-call.ll48
3 files changed, 58 insertions, 1 deletions
diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h
index b0002b512c4..ab35c722fe7 100644
--- a/llvm/include/llvm/Target/TargetLowering.h
+++ b/llvm/include/llvm/Target/TargetLowering.h
@@ -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);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 0fd7b173015..0f5f72e40da 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -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,
diff --git a/llvm/test/CodeGen/X86/noreturn-call.ll b/llvm/test/CodeGen/X86/noreturn-call.ll
new file mode 100644
index 00000000000..89781816de8
--- /dev/null
+++ b/llvm/test/CodeGen/X86/noreturn-call.ll
@@ -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*)
OpenPOWER on IntegriCloud