summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Target/TargetOptions.h5
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp20
-rw-r--r--llvm/lib/Target/AArch64/AArch64TargetMachine.cpp4
-rw-r--r--llvm/lib/Target/ARM/ARMTargetMachine.cpp4
-rw-r--r--llvm/lib/Target/X86/X86TargetMachine.cpp4
-rw-r--r--llvm/test/CodeGen/X86/shadow-stack.ll2
-rw-r--r--llvm/test/CodeGen/X86/unreachable-trap.ll29
7 files changed, 60 insertions, 8 deletions
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index 844031f3090..726dddac517 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -108,6 +108,7 @@ namespace llvm {
DisableIntegratedAS(false), RelaxELFRelocations(false),
FunctionSections(false), DataSections(false),
UniqueSectionNames(true), TrapUnreachable(false),
+ NoTrapAfterNoreturn(false),
EmulatedTLS(false), ExplicitEmulatedTLS(false),
EnableIPRA(false), EmitStackSizeSection(false) {}
@@ -213,6 +214,10 @@ namespace llvm {
/// Emit target-specific trap instruction for 'unreachable' IR instructions.
unsigned TrapUnreachable : 1;
+ /// Do not emit a trap instruction for 'unreachable' IR instructions behind
+ /// noreturn calls, even if TrapUnreachable is true.
+ unsigned NoTrapAfterNoreturn : 1;
+
/// EmulatedTLS - This flag enables emulated TLS model, using emutls
/// function in the runtime library..
unsigned EmulatedTLS : 1;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 4225bd54c89..74c50d2a246 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2625,9 +2625,23 @@ void SelectionDAGBuilder::visitIndirectBr(const IndirectBrInst &I) {
}
void SelectionDAGBuilder::visitUnreachable(const UnreachableInst &I) {
- if (DAG.getTarget().Options.TrapUnreachable)
- DAG.setRoot(
- DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, DAG.getRoot()));
+ if (!DAG.getTarget().Options.TrapUnreachable)
+ return;
+
+ // We may be able to ignore unreachable behind a noreturn call.
+ if (DAG.getTarget().Options.NoTrapAfterNoreturn) {
+ const BasicBlock &BB = *I.getParent();
+ if (&I != &BB.front()) {
+ BasicBlock::const_iterator PredI =
+ std::prev(BasicBlock::const_iterator(&I));
+ if (const CallInst *Call = dyn_cast<CallInst>(&*PredI)) {
+ if (Call->doesNotReturn())
+ return;
+ }
+ }
+ }
+
+ DAG.setRoot(DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, DAG.getRoot()));
}
void SelectionDAGBuilder::visitFSub(const User &I) {
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index d7dea46a351..b25bcdb7edc 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -244,8 +244,10 @@ AArch64TargetMachine::AArch64TargetMachine(const Target &T, const Triple &TT,
TLOF(createTLOF(getTargetTriple())), isLittle(LittleEndian) {
initAsmInfo();
- if (TT.isOSBinFormatMachO())
+ if (TT.isOSBinFormatMachO()) {
this->Options.TrapUnreachable = true;
+ this->Options.NoTrapAfterNoreturn = true;
+ }
// Enable GlobalISel at or below EnableGlobalISelAt0.
if (getOptLevel() <= EnableGlobalISelAtO)
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index 6a7f4814d1c..bc2525b6b42 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -239,8 +239,10 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const Triple &TT,
this->Options.EABIVersion = EABI::EABI5;
}
- if (TT.isOSBinFormatMachO())
+ if (TT.isOSBinFormatMachO()) {
this->Options.TrapUnreachable = true;
+ this->Options.NoTrapAfterNoreturn = true;
+ }
initAsmInfo();
}
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 8402434cd47..9b45e3bddc8 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -229,8 +229,10 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
// to ever want to mix 32 and 64-bit windows code in a single module
// this should be fine.
if ((TT.isOSWindows() && TT.getArch() == Triple::x86_64) || TT.isPS4() ||
- TT.isOSBinFormatMachO())
+ TT.isOSBinFormatMachO()) {
this->Options.TrapUnreachable = true;
+ this->Options.NoTrapAfterNoreturn = TT.isOSBinFormatMachO();
+ }
initAsmInfo();
}
diff --git a/llvm/test/CodeGen/X86/shadow-stack.ll b/llvm/test/CodeGen/X86/shadow-stack.ll
index d0886f49c3e..6fa41378182 100644
--- a/llvm/test/CodeGen/X86/shadow-stack.ll
+++ b/llvm/test/CodeGen/X86/shadow-stack.ll
@@ -64,7 +64,6 @@ define i32 @bar(i32 %i) local_unnamed_addr {
; X86_64-NEXT: movq 8(%rax), %rcx
; X86_64-NEXT: movq 16(%rax), %rsp
; X86_64-NEXT: jmpq *%rcx
-; X86_64-NEXT: ud2
;
; X86-LABEL: bar:
; X86: ## %bb.0: ## %entry
@@ -99,7 +98,6 @@ define i32 @bar(i32 %i) local_unnamed_addr {
; X86-NEXT: movl 4(%eax), %ecx
; X86-NEXT: movl 8(%eax), %esp
; X86-NEXT: jmpl *%ecx
-; X86-NEXT: ud2
entry:
%0 = load i8*, i8** @buf, align 8
tail call void @llvm.eh.sjlj.longjmp(i8* %0)
diff --git a/llvm/test/CodeGen/X86/unreachable-trap.ll b/llvm/test/CodeGen/X86/unreachable-trap.ll
new file mode 100644
index 00000000000..8de0510ed38
--- /dev/null
+++ b/llvm/test/CodeGen/X86/unreachable-trap.ll
@@ -0,0 +1,29 @@
+; RUN: llc -o - %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
+; RUN: llc -o - %s -mtriple=x86_64-apple-darwin | FileCheck %s --check-prefixes=CHECK,NO_TRAP_AFTER_NORETURN
+
+; CHECK-LABEL: call_exit:
+; CHECK: callq {{_?}}exit
+; TRAP_AFTER_NORETURN: ud2
+; NO_TRAP_AFTER_NORETURN-NOT: ud2
+define i32 @call_exit() noreturn nounwind {
+ tail call void @exit(i32 0)
+ unreachable
+}
+
+; CHECK-LABEL: trap:
+; CHECK: ud2
+; TRAP_AFTER_NORETURN: ud2
+; NO_TRAP_AFTER_NORETURN-NOT: ud2
+define i32 @trap() noreturn nounwind {
+ tail call void @llvm.trap()
+ unreachable
+}
+
+; CHECK-LABEL: unreachable:
+; CHECK: ud2
+define i32 @unreachable() noreturn nounwind {
+ unreachable
+}
+
+declare void @llvm.trap() nounwind noreturn
+declare void @exit(i32 %rc) nounwind noreturn
OpenPOWER on IntegriCloud