From f81836bd18be6fb8bc6fe9942053f418dbb13d98 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Thu, 24 Mar 2016 00:10:03 +0000 Subject: [PATCH] [PS4] Guarantee an instruction after a 'noreturn' call. We need the "return address" of a noreturn call to be within the bounds of the calling function; TrapUnreachable turns 'unreachable' into a 'ud2' instruction, which has that desired effect. Differential Revision: http://reviews.llvm.org/D18414 llvm-svn: 264224 --- llvm/lib/Target/X86/X86TargetMachine.cpp | 4 +++- llvm/test/CodeGen/X86/br-fold.ll | 4 ++++ llvm/test/CodeGen/X86/ps4-noreturn.ll | 38 ++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/X86/ps4-noreturn.ll diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index 806ba12..382de99 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -119,7 +119,9 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT, // after a call to 'noreturn' function. // To prevent that, we emit a trap for 'unreachable' IR instructions. // (which on X86, happens to be the 'ud2' instruction) - if (Subtarget.isTargetWin64()) + // On PS4, the "return address" of a 'noreturn' call must still be within + // the calling function, and TrapUnreachable is an easy way to get that. + if (Subtarget.isTargetWin64() || Subtarget.isTargetPS4()) this->Options.TrapUnreachable = true; // By default (and when -ffast-math is on), enable estimate codegen for diff --git a/llvm/test/CodeGen/X86/br-fold.ll b/llvm/test/CodeGen/X86/br-fold.ll index fd1e73b..5e5f860 100644 --- a/llvm/test/CodeGen/X86/br-fold.ll +++ b/llvm/test/CodeGen/X86/br-fold.ll @@ -2,6 +2,7 @@ ; RUN: llc -mtriple=x86_64-pc-linux < %s | FileCheck -check-prefix=X64_LINUX %s ; RUN: llc -mtriple=x86_64-pc-windows < %s | FileCheck -check-prefix=X64_WINDOWS %s ; RUN: llc -mtriple=x86_64-pc-windows-gnu < %s | FileCheck -check-prefix=X64_WINDOWS_GNU %s +; RUN: llc -mtriple=x86_64-scei-ps4 < %s | FileCheck -check-prefix=PS4 %s ; X64_DARWIN: orq ; X64_DARWIN-NEXT: %bb8.i329 @@ -15,6 +16,9 @@ ; X64_WINDOWS_GNU: orq %rax, %rcx ; X64_WINDOWS_GNU-NEXT: ud2 +; PS4: orq %rax, %rcx +; PS4-NEXT: ud2 + @_ZN11xercesc_2_513SchemaSymbols21fgURI_SCHEMAFORSCHEMAE = external constant [33 x i16], align 32 ; <[33 x i16]*> [#uses=1] @_ZN11xercesc_2_56XMLUni16fgNotationStringE = external constant [9 x i16], align 16 ; <[9 x i16]*> [#uses=1] diff --git a/llvm/test/CodeGen/X86/ps4-noreturn.ll b/llvm/test/CodeGen/X86/ps4-noreturn.ll new file mode 100644 index 0000000..4c14f21 --- /dev/null +++ b/llvm/test/CodeGen/X86/ps4-noreturn.ll @@ -0,0 +1,38 @@ +; RUN: llc < %s -mtriple=x86_64-scei-ps4 | FileCheck %s + +declare i32 @personality(...) + +; Check that after the (implicitly noreturn) unwind call, there is +; another instruction. It was easy to produce 'ud2' so we check for that. +define void @foo1() personality i32 (...)* @personality { +; CHECK-LABEL: foo1: +; CHECK: .cfi_startproc +; CHECK: callq bar +; CHECK: retq +; Check for 'ud2' between noreturn call and function end. +; CHECK: callq _Unwind_Resume +; CHECK-NEXT: ud2 +; CHECK-NEXT: .Lfunc_end0: + invoke void @bar() + to label %normal + unwind label %catch +normal: + ret void +catch: + %1 = landingpad { i8*, i32 } cleanup + resume { i8*, i32 } %1 +} + +declare void @bar() #0 + +; Similar check after an explicit noreturn call. +define void @foo2() { +; CHECK-LABEL: foo2: +; CHECK: callq bar +; CHECK-NEXT: ud2 +; CHECK-NEXT: .Lfunc_end1: + tail call void @bar() + unreachable +} + +attributes #0 = { noreturn } -- 2.7.4