[llvm] r371466 - [Windows] Replace TrapUnreachable with an int3 insertion pass

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 9 16:04:25 PDT 2019


Author: rnk
Date: Mon Sep  9 16:04:25 2019
New Revision: 371466

URL: http://llvm.org/viewvc/llvm-project?rev=371466&view=rev
Log:
[Windows] Replace TrapUnreachable with an int3 insertion pass

This is an alternative to D66980, which was reverted. Instead of
inserting a pseudo instruction that optionally expands to nothing, add a
pass that inserts int3 when appropriate after basic block layout.

Reviewers: hans

Differential Revision: https://reviews.llvm.org/D67201

Added:
    llvm/trunk/lib/Target/X86/X86AvoidTrailingCall.cpp
    llvm/trunk/test/CodeGen/X86/noreturn-call-win64.ll
    llvm/trunk/test/CodeGen/X86/win64-eh-empty-block.ll
Modified:
    llvm/trunk/lib/Target/X86/CMakeLists.txt
    llvm/trunk/lib/Target/X86/X86.h
    llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
    llvm/trunk/test/CodeGen/WinEH/wineh-noret-cleanup.ll
    llvm/trunk/test/CodeGen/X86/br-fold.ll
    llvm/trunk/test/CodeGen/X86/catchpad-lifetime.ll
    llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll
    llvm/trunk/test/CodeGen/X86/catchret-regmask.ll
    llvm/trunk/test/CodeGen/X86/empty-function.ll
    llvm/trunk/test/CodeGen/X86/funclet-layout.ll
    llvm/trunk/test/CodeGen/X86/pr24374.ll
    llvm/trunk/test/CodeGen/X86/trap.ll
    llvm/trunk/test/CodeGen/X86/unreachable-trap.ll
    llvm/trunk/test/CodeGen/X86/win64_call_epi.ll
    llvm/trunk/test/CodeGen/X86/win64_eh.ll
    llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll
    llvm/trunk/test/DebugInfo/COFF/local-variable-gap.ll

Modified: llvm/trunk/lib/Target/X86/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/CMakeLists.txt?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/X86/CMakeLists.txt Mon Sep  9 16:04:25 2019
@@ -23,6 +23,7 @@ add_public_tablegen_target(X86CommonTabl
 
 set(sources
   X86AsmPrinter.cpp
+  X86AvoidTrailingCall.cpp
   X86CallFrameOptimization.cpp
   X86CallingConv.cpp
   X86CallLowering.cpp

Modified: llvm/trunk/lib/Target/X86/X86.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.h?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86.h (original)
+++ llvm/trunk/lib/Target/X86/X86.h Mon Sep  9 16:04:25 2019
@@ -81,6 +81,12 @@ FunctionPass *createX86FlagsCopyLowering
 /// Return a pass that expands WinAlloca pseudo-instructions.
 FunctionPass *createX86WinAllocaExpander();
 
+/// Return a pass that inserts int3 at the end of the function if it ends with a
+/// CALL instruction. The pass does the same for each funclet as well. This
+/// ensures that the open interval of function start and end PCs contains all
+/// return addresses for the benefit of the Windows x64 unwinder.
+FunctionPass *createX86AvoidTrailingCallPass();
+
 /// Return a pass that optimizes the code-size of x86 call sequences. This is
 /// done by replacing esp-relative movs with pushes.
 FunctionPass *createX86CallFrameOptimization();

Added: llvm/trunk/lib/Target/X86/X86AvoidTrailingCall.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86AvoidTrailingCall.cpp?rev=371466&view=auto
==============================================================================
--- llvm/trunk/lib/Target/X86/X86AvoidTrailingCall.cpp (added)
+++ llvm/trunk/lib/Target/X86/X86AvoidTrailingCall.cpp Mon Sep  9 16:04:25 2019
@@ -0,0 +1,108 @@
+//===----- X86AvoidTrailingCall.cpp - Insert int3 after trailing calls ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The Windows x64 unwinder has trouble unwinding the stack when a return
+// address points to the end of the function. This pass maintains the invariant
+// that every return address is inside the bounds of its parent function or
+// funclet by inserting int3 if the last instruction would otherwise be a call.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "X86InstrInfo.h"
+#include "X86Subtarget.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+
+#define DEBUG_TYPE "x86-avoid-trailing-call"
+
+using namespace llvm;
+
+namespace {
+
+class X86AvoidTrailingCallPass : public MachineFunctionPass {
+public:
+  X86AvoidTrailingCallPass() : MachineFunctionPass(ID) {}
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+private:
+  StringRef getPassName() const override {
+    return "X86 avoid trailing call pass";
+  }
+  static char ID;
+};
+
+char X86AvoidTrailingCallPass::ID = 0;
+
+} // end anonymous namespace
+
+FunctionPass *llvm::createX86AvoidTrailingCallPass() {
+  return new X86AvoidTrailingCallPass();
+}
+
+// A real instruction is a non-meta, non-pseudo instruction.  Some pseudos
+// expand to nothing, and some expand to code. This logic conservatively assumes
+// they might expand to nothing.
+static bool isRealInstruction(MachineInstr &MI) {
+  return !MI.isPseudo() && !MI.isMetaInstruction();
+}
+
+// Return true if this is a call instruction, but not a tail call.
+static bool isCallInstruction(const MachineInstr &MI) {
+  return MI.isCall() && !MI.isReturn();
+}
+
+bool X86AvoidTrailingCallPass::runOnMachineFunction(MachineFunction &MF) {
+  const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
+  const X86InstrInfo &TII = *STI.getInstrInfo();
+  assert(STI.isTargetWin64() && "pass only runs on Win64");
+
+  // FIXME: Perhaps this pass should also replace SEH_Epilogue by inserting nops
+  // before epilogues.
+
+  bool Changed = false;
+  for (MachineBasicBlock &MBB : MF) {
+    // Look for basic blocks that precede funclet entries or are at the end of
+    // the function.
+    MachineBasicBlock *NextMBB = MBB.getNextNode();
+    if (NextMBB && !NextMBB->isEHFuncletEntry())
+      continue;
+
+    // Find the last real instruction in this block, or previous blocks if this
+    // block is empty.
+    MachineBasicBlock::reverse_iterator LastRealInstr;
+    for (MachineBasicBlock &RMBB :
+         make_range(MBB.getReverseIterator(), MF.rend())) {
+      LastRealInstr = llvm::find_if(reverse(RMBB), isRealInstruction);
+      if (LastRealInstr != RMBB.rend())
+        break;
+    }
+
+    // Do nothing if this function or funclet has no instructions.
+    if (LastRealInstr == MF.begin()->rend())
+      continue;
+
+    // If this is a call instruction, insert int3 right after it with the same
+    // DebugLoc. Convert back to a forward iterator and advance the insertion
+    // position once.
+    if (isCallInstruction(*LastRealInstr)) {
+      LLVM_DEBUG({
+        dbgs() << "inserting int3 after trailing call instruction:\n";
+        LastRealInstr->dump();
+        dbgs() << '\n';
+      });
+
+      MachineBasicBlock::iterator MBBI = std::next(LastRealInstr.getReverse());
+      BuildMI(*LastRealInstr->getParent(), MBBI, LastRealInstr->getDebugLoc(),
+              TII.get(X86::INT3));
+      Changed = true;
+    }
+  }
+
+  return Changed;
+}

Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Mon Sep  9 16:04:25 2019
@@ -219,17 +219,9 @@ X86TargetMachine::X86TargetMachine(const
           getEffectiveX86CodeModel(CM, JIT, TT.getArch() == Triple::x86_64),
           OL),
       TLOF(createTLOF(getTargetTriple())) {
-  // Windows stack unwinder gets confused when execution flow "falls through"
-  // 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)
   // 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.
-  // The check here for 64-bit windows is a bit icky, but as we're unlikely
-  // 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()) {
+  if (TT.isPS4() || TT.isOSBinFormatMachO()) {
     this->Options.TrapUnreachable = true;
     this->Options.NoTrapAfterNoreturn = TT.isOSBinFormatMachO();
   }
@@ -518,12 +510,19 @@ void X86PassConfig::addPreEmitPass() {
 }
 
 void X86PassConfig::addPreEmitPass2() {
+  const Triple &TT = TM->getTargetTriple();
+  const MCAsmInfo *MAI = TM->getMCAsmInfo();
+
   addPass(createX86RetpolineThunksPass());
+
+  // Insert extra int3 instructions after trailing call instructions to avoid
+  // issues in the unwinder.
+  if (TT.isOSWindows() && TT.getArch() == Triple::x86_64)
+    addPass(createX86AvoidTrailingCallPass());
+
   // Verify basic block incoming and outgoing cfa offset and register values and
   // correct CFA calculation rule where needed by inserting appropriate CFI
   // instructions.
-  const Triple &TT = TM->getTargetTriple();
-  const MCAsmInfo *MAI = TM->getMCAsmInfo();
   if (!TT.isOSDarwin() &&
       (!TT.isOSWindows() ||
        MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI))

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-noret-cleanup.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-noret-cleanup.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-noret-cleanup.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-noret-cleanup.ll Mon Sep  9 16:04:25 2019
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: sed -e s/.Cxx:// %s | llc -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefix=CXX
 ; RUN: sed -e s/.Seh:// %s | llc -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefix=SEH
 
@@ -69,13 +68,13 @@ catch.body.2:
 ; SEH-NEXT:    .long   .Ltmp0 at IMGREL+1
 ; SEH-NEXT:    .long   .Ltmp1 at IMGREL+1
 ; SEH-NEXT:    .long   dummy_filter at IMGREL
-; SEH-NEXT:    .long   .LBB0_2 at IMGREL
+; SEH-NEXT:    .long   .LBB0_5 at IMGREL
 ; SEH-NEXT:    .long   .Ltmp2 at IMGREL+1
 ; SEH-NEXT:    .long   .Ltmp3 at IMGREL+1
-; SEH-NEXT:    .long   "?dtor$5@?0?test at 4HA"@IMGREL 
+; SEH-NEXT:    .long   "?dtor$2@?0?test at 4HA"@IMGREL
 ; SEH-NEXT:    .long   0
 ; SEH-NEXT:    .long   .Ltmp2 at IMGREL+1
 ; SEH-NEXT:    .long   .Ltmp3 at IMGREL+1
 ; SEH-NEXT:    .long   dummy_filter at IMGREL
-; SEH-NEXT:    .long   .LBB0_2 at IMGREL
+; SEH-NEXT:    .long   .LBB0_5 at IMGREL
 ; SEH-NEXT:  .Llsda_end0:

Modified: llvm/trunk/test/CodeGen/X86/br-fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/br-fold.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/br-fold.ll (original)
+++ llvm/trunk/test/CodeGen/X86/br-fold.ll Mon Sep  9 16:04:25 2019
@@ -5,18 +5,18 @@
 ; RUN: llc -mtriple=x86_64-scei-ps4 < %s | FileCheck -check-prefix=PS4 %s
 
 ; X64_DARWIN: orq
-; X64-DARWIN-NEXT: ud2
+; X64_DARWIN-NEXT: ud2
 
 ; X64_LINUX: orq %rax, %rcx
 ; X64_LINUX-NEXT: jne
 ; X64_LINUX-NEXT: %bb8.i329
 
 ; X64_WINDOWS: orq %rax, %rcx
-; X64_WINDOWS-NEXT: ud2
+; X64_WINDOWS-NEXT: jne
 
 ; X64_WINDOWS_GNU: movq .refptr._ZN11xercesc_2_513SchemaSymbols21fgURI_SCHEMAFORSCHEMAE(%rip), %rax
 ; X64_WINDOWS_GNU: orq .refptr._ZN11xercesc_2_56XMLUni16fgNotationStringE(%rip), %rax
-; X64_WINDOWS_GNU-NEXT: ud2
+; X64_WINDOWS_GNU-NEXT: jne
 
 ; PS4: orq %rax, %rcx
 ; PS4-NEXT: ud2

Modified: llvm/trunk/test/CodeGen/X86/catchpad-lifetime.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/catchpad-lifetime.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/catchpad-lifetime.ll (original)
+++ llvm/trunk/test/CodeGen/X86/catchpad-lifetime.ll Mon Sep  9 16:04:25 2019
@@ -7,6 +7,8 @@ declare void @throw()
 
 declare i32 @__CxxFrameHandler3(...)
 
+declare void @llvm.trap()
+
 define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   %alloca2 = alloca i8*, align 4
@@ -30,6 +32,7 @@ catch.pad:
   %bc2 = bitcast i8** %alloca2 to i8*
   call void @llvm.lifetime.start.p0i8(i64 4, i8* %bc2)
   store volatile i8* null, i8** %alloca1
+  call void @llvm.trap()
   unreachable
 
 ; CHECK-LABEL: "?catch$2@?0?test1 at 4HA"
@@ -67,6 +70,7 @@ catch.pad:
   %bc2 = bitcast i8** %alloca2 to i8*
   call void @llvm.lifetime.start.p0i8(i64 4, i8* %bc2)
   store volatile i8* null, i8** %alloca1
+  call void @llvm.trap()
   unreachable
 
 ; CHECK-LABEL: "?catch$2@?0?test2 at 4HA"

Modified: llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll (original)
+++ llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll Mon Sep  9 16:04:25 2019
@@ -75,7 +75,7 @@ unreachable:
 ; CHECK: popq %rbp
 ; CHECK: retq
 
-; CHECK: "?catch$2@?0?global_array at 4HA":
+; CHECK: "?catch${{[0-9]+}}@?0?global_array at 4HA":
 ; CHECK: pushq   %rbp
 ; CHECK: movslq  {{.*}}, %[[idx:[^ ]*]]
 ; CHECK: leaq    array(%rip), %[[base:[^ ]*]]
@@ -122,7 +122,7 @@ unreachable:
 ; CHECK: popq %rbp
 ; CHECK: retq
 
-; CHECK: "?catch$2@?0?access_imported at 4HA":
+; CHECK: "?catch${{[0-9]+}}@?0?access_imported at 4HA":
 ; CHECK: pushq   %rbp
 ; CHECK: movq    __imp_imported(%rip), %[[base:[^ ]*]]
 ; CHECK: movl    $222, (%[[base]])

Modified: llvm/trunk/test/CodeGen/X86/catchret-regmask.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/catchret-regmask.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/catchret-regmask.ll (original)
+++ llvm/trunk/test/CodeGen/X86/catchret-regmask.ll Mon Sep  9 16:04:25 2019
@@ -6,6 +6,7 @@ target triple = "x86_64-pc-windows-msvc"
 declare i32 @__CxxFrameHandler3(...)
 declare void @throw() noreturn uwtable
 declare i8* @getval()
+declare void @llvm.trap()
 
 define i8* @reload_out_of_pad(i8* %arg) #0 personality i32 (...)* @__CxxFrameHandler3 {
 assertPassed:
@@ -19,6 +20,7 @@ catch:
   ; This block *must* appear after the catchret to test the bug.
   ; FIXME: Make this an MIR test so we can control MBB layout.
 unreachable:
+  call void @llvm.trap()
   unreachable
 
 catch.dispatch:
@@ -35,7 +37,7 @@ return:
 ; CHECK: movq -[[arg_slot]](%rbp), %rax # 8-byte Reload
 ; CHECK: retq
 
-; CHECK: "?catch$3@?0?reload_out_of_pad at 4HA":
+; CHECK: "?catch${{[0-9]+}}@?0?reload_out_of_pad at 4HA":
 ; CHECK-NOT: Reload
 ; CHECK: retq
 
@@ -50,6 +52,7 @@ catch:
   catchret from %cp to label %return
 
 unreachable:
+  call void @llvm.trap()
   unreachable
 
 catch.dispatch:
@@ -65,7 +68,7 @@ return:
 ; CHECK: movq -[[val_slot:[0-9]+]](%rbp), %rax # 8-byte Reload
 ; CHECK: retq
 
-; CHECK: "?catch$3@?0?spill_in_pad at 4HA":
+; CHECK: "?catch${{[0-9]+}}@?0?spill_in_pad at 4HA":
 ; CHECK: callq getval
 ; CHECK: movq %rax, -[[val_slot]](%rbp) # 8-byte Spill
 ; CHECK: retq

Modified: llvm/trunk/test/CodeGen/X86/empty-function.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/empty-function.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/empty-function.ll (original)
+++ llvm/trunk/test/CodeGen/X86/empty-function.ll Mon Sep  9 16:04:25 2019
@@ -15,7 +15,7 @@ entry:
 
 ; CHECK-LABEL: f:
 ; WIN32: nop
-; WIN64: ud2
+; WIN64: nop
 ; LINUX-NOT: nop
 ; LINUX-NOT: ud2
 

Modified: llvm/trunk/test/CodeGen/X86/funclet-layout.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/funclet-layout.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/funclet-layout.ll (original)
+++ llvm/trunk/test/CodeGen/X86/funclet-layout.ll Mon Sep  9 16:04:25 2019
@@ -9,6 +9,8 @@ target triple = "x86_64-pc-windows-msvc"
 @"\01??_7type_info@@6B@" = external constant i8*
 @"\01??_R0H at 8" = internal global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }
 
+declare void @llvm.trap()
+
 define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   invoke void @g()
@@ -31,6 +33,7 @@ try.cont:
   ret void
 
 unreachable:
+  call void @llvm.trap()
   unreachable
 }
 
@@ -76,6 +79,7 @@ try.cont.5:
   ret i32 0
 
 unreachable:                                      ; preds = %catch, %entry
+  call void @llvm.trap()
   unreachable
 }
 
@@ -125,11 +129,13 @@ try.cont:
   br i1 %V, label %exit_one, label %exit_two
 
 exit_one:
-  tail call void @exit(i32 0)
+  tail call void @g()
+  call void @llvm.trap()
   unreachable
 
 exit_two:
-  tail call void @exit(i32 0)
+  tail call void @g()
+  call void @llvm.trap()
   unreachable
 }
 
@@ -138,7 +144,7 @@ exit_two:
 ; The entry funclet contains %entry and %try.cont
 ; CHECK: # %entry
 ; CHECK: # %try.cont
-; CHECK: callq exit
+; CHECK: callq g
 ; CHECK-NOT: # exit_one
 ; CHECK-NOT: # exit_two
 ; CHECK: ud2
@@ -146,12 +152,12 @@ exit_two:
 ; The catch(...) funclet contains %catch.2
 ; CHECK: # %catch.2{{$}}
 ; CHECK: callq exit
-; CHECK: ud2
+; CHECK-NEXT: int3
 
 ; The catch(int) funclet contains %catch
 ; CHECK: # %catch{{$}}
 ; CHECK: callq exit
-; CHECK: ud2
+; CHECK-NEXT: int3
 
 declare void @exit(i32) noreturn nounwind
 declare void @_CxxThrowException(i8*, %eh.ThrowInfo*)

Added: llvm/trunk/test/CodeGen/X86/noreturn-call-win64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/noreturn-call-win64.ll?rev=371466&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/noreturn-call-win64.ll (added)
+++ llvm/trunk/test/CodeGen/X86/noreturn-call-win64.ll Mon Sep  9 16:04:25 2019
@@ -0,0 +1,53 @@
+; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local i32 @foo() {
+entry:
+  %call = call i32 @cond()
+  %tobool = icmp ne i32 %call, 0
+  br i1 %tobool, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @abort1()
+  unreachable
+
+if.end:                                           ; preds = %entry
+  %call1 = call i32 @cond()
+  %tobool2 = icmp ne i32 %call1, 0
+  br i1 %tobool2, label %if.then3, label %if.end4
+
+if.then3:                                         ; preds = %if.end
+  call void @abort2()
+  unreachable
+
+if.end4:                                          ; preds = %if.end
+  %call5 = call i32 @cond()
+  %tobool6 = icmp ne i32 %call5, 0
+  br i1 %tobool6, label %if.then7, label %if.end8
+
+if.then7:                                         ; preds = %if.end4
+  call void @abort3()
+  unreachable
+
+if.end8:                                          ; preds = %if.end4
+  ret i32 0
+}
+
+; CHECK-LABEL: foo:
+; CHECK: callq cond
+; CHECK: callq cond
+; CHECK: callq cond
+;   We don't need int3's between these calls to abort, since they won't confuse
+;   the unwinder.
+; CHECK: callq abort1
+; CHECK-NEXT:   # %if.then3
+; CHECK: callq abort2
+; CHECK-NEXT:   # %if.then7
+; CHECK: callq abort3
+; CHECK-NEXT: int3
+
+declare dso_local i32 @cond()
+
+declare dso_local void @abort1() noreturn
+declare dso_local void @abort2() noreturn
+declare dso_local void @abort3() noreturn

Modified: llvm/trunk/test/CodeGen/X86/pr24374.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pr24374.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/pr24374.ll (original)
+++ llvm/trunk/test/CodeGen/X86/pr24374.ll Mon Sep  9 16:04:25 2019
@@ -31,6 +31,6 @@ define void @g() {
   unreachable
 }
 ; CHECK-LABEL: g:
-; CHECK: ud2
+; CHECK: nop
 
 attributes #0 = { nounwind }

Modified: llvm/trunk/test/CodeGen/X86/trap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/trap.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/trap.ll (original)
+++ llvm/trunk/test/CodeGen/X86/trap.ll Mon Sep  9 16:04:25 2019
@@ -1,13 +1,19 @@
 ; RUN: llc < %s -mtriple=i686-apple-darwin8 -mcpu=yonah | FileCheck %s -check-prefix=DARWIN
 ; RUN: llc < %s -mtriple=i686-unknown-linux -mcpu=yonah | FileCheck %s -check-prefix=LINUX
 ; RUN: llc < %s -mtriple=x86_64-scei-ps4 | FileCheck %s -check-prefix=PS4
+; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s -check-prefix=WIN64
 
 ; DARWIN-LABEL: test0:
 ; DARWIN: ud2
 ; LINUX-LABEL: test0:
 ; LINUX: ud2
+; FIXME: PS4 probably doesn't want two ud2s.
 ; PS4-LABEL: test0:
 ; PS4: ud2
+; PS4: ud2
+; WIN64-LABEL: test0:
+; WIN64: ud2
+; WIN64-NOT: ud2
 define i32 @test0() noreturn nounwind  {
 entry:
 	tail call void @llvm.trap( )
@@ -20,6 +26,9 @@ entry:
 ; LINUX: int3
 ; PS4-LABEL: test1:
 ; PS4: int     $65
+; WIN64-LABEL: test1:
+; WIN64: int3
+; WIN64-NOT: ud2
 define i32 @test1() noreturn nounwind  {
 entry:
 	tail call void @llvm.debugtrap( )

Modified: llvm/trunk/test/CodeGen/X86/unreachable-trap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/unreachable-trap.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/unreachable-trap.ll (original)
+++ llvm/trunk/test/CodeGen/X86/unreachable-trap.ll Mon Sep  9 16:04:25 2019
@@ -1,10 +1,13 @@
-; RUN: llc -o - %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
+; RUN: llc -o - %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,NORMAL
+; RUN: llc -o - %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefixes=CHECK,NORMAL
+; RUN: llc -o - %s -mtriple=x86_64-scei-ps4 | 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
+; NORMAL-NOT: ud2
 define i32 @call_exit() noreturn nounwind {
   tail call void @exit(i32 0)
   unreachable
@@ -14,13 +17,17 @@ define i32 @call_exit() noreturn nounwin
 ; CHECK: ud2
 ; TRAP_AFTER_NORETURN: ud2
 ; NO_TRAP_AFTER_NORETURN-NOT: ud2
+; NORMAL-NOT: ud2
 define i32 @trap() noreturn nounwind {
   tail call void @llvm.trap()
   unreachable
 }
 
 ; CHECK-LABEL: unreachable:
-; CHECK: ud2
+; TRAP_AFTER_NORETURN: ud2
+; NO_TRAP_AFTER_NORETURN: ud2
+; NORMAL-NOT: ud2
+; NORMAL: # -- End function
 define i32 @unreachable() noreturn nounwind {
   unreachable
 }

Added: llvm/trunk/test/CodeGen/X86/win64-eh-empty-block.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win64-eh-empty-block.ll?rev=371466&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win64-eh-empty-block.ll (added)
+++ llvm/trunk/test/CodeGen/X86/win64-eh-empty-block.ll Mon Sep  9 16:04:25 2019
@@ -0,0 +1,107 @@
+; RUN: llc -mtriple=x86_64-windows-gnu %s -o - | FileCheck %s
+
+; Based on this C++ code:
+; struct as {
+;     as() { at = static_cast<int *>(operator new(sizeof(int))); }
+;     ~as() { operator delete(at); }
+;     int *at;
+; };
+; void am(int) {
+;     static as au;
+;     as av;
+;     throw 0;
+; }
+
+; optnone was added to ensure that branch folding and block layout are not
+; disturbed. The key thing about this test is that it ends in an empty
+; unreachable block, which forces us to scan back across blocks.
+
+; CHECK: _Z2ami:
+; CHECK: callq   __cxa_throw
+; CHECK: # %eh.resume
+; CHECK: callq _Unwind_Resume
+; CHECK-NEXT: int3
+; CHECK-NEXT: # %unreachable
+; CHECK-NEXT: .Lfunc_end0:
+
+%struct.as = type { i32* }
+
+ at _ZZ2amiE2au = internal unnamed_addr global %struct.as zeroinitializer, align 8
+ at _ZGVZ2amiE2au = internal global i64 0, align 8
+ at _ZTIi = external constant i8*
+
+define dso_local void @_Z2ami(i32 %0) noinline optnone personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*) {
+entry:
+  %1 = load atomic i8, i8* bitcast (i64* @_ZGVZ2amiE2au to i8*) acquire, align 8
+  %guard.uninitialized = icmp eq i8 %1, 0
+  br i1 %guard.uninitialized, label %init.check, label %init.end
+
+init.check:                                       ; preds = %entry
+  %2 = tail call i32 @__cxa_guard_acquire(i64* nonnull @_ZGVZ2amiE2au)
+  %tobool = icmp eq i32 %2, 0
+  br i1 %tobool, label %init.end, label %init
+
+init:                                             ; preds = %init.check
+  %call.i3 = invoke i8* @_Znwy(i64 4)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %init
+  store i8* %call.i3, i8** bitcast (%struct.as* @_ZZ2amiE2au to i8**), align 8
+  %3 = tail call i32 @atexit(void ()* nonnull @__dtor__ZZ2amiE2au)
+  tail call void @__cxa_guard_release(i64* nonnull @_ZGVZ2amiE2au)
+  br label %init.end
+
+init.end:                                         ; preds = %init.check, %invoke.cont, %entry
+  %call.i = tail call i8* @_Znwy(i64 4)
+  %exception = tail call i8* @__cxa_allocate_exception(i64 4)
+  %4 = bitcast i8* %exception to i32*
+  store i32 0, i32* %4, align 16
+  invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
+          to label %unreachable unwind label %lpad1
+
+lpad:                                             ; preds = %init
+  %5 = landingpad { i8*, i32 }
+          cleanup
+  %6 = extractvalue { i8*, i32 } %5, 0
+  %7 = extractvalue { i8*, i32 } %5, 1
+  tail call void @__cxa_guard_abort(i64* nonnull @_ZGVZ2amiE2au)
+  br label %eh.resume
+
+lpad1:                                            ; preds = %init.end
+  %8 = landingpad { i8*, i32 }
+          cleanup
+  %9 = extractvalue { i8*, i32 } %8, 0
+  %10 = extractvalue { i8*, i32 } %8, 1
+  tail call void @_ZdlPv(i8* %call.i)
+  br label %eh.resume
+
+eh.resume:                                        ; preds = %lpad1, %lpad
+  %exn.slot.0 = phi i8* [ %9, %lpad1 ], [ %6, %lpad ]
+  %ehselector.slot.0 = phi i32 [ %10, %lpad1 ], [ %7, %lpad ]
+  %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn.slot.0, 0
+  %lpad.val2 = insertvalue { i8*, i32 } %lpad.val, i32 %ehselector.slot.0, 1
+  resume { i8*, i32 } %lpad.val2
+
+unreachable:                                      ; preds = %init.end
+  unreachable
+}
+
+declare dso_local i32 @__cxa_guard_acquire(i64*)
+
+declare dso_local i32 @__gxx_personality_seh0(...)
+
+declare dso_local void @__dtor__ZZ2amiE2au()
+
+declare dso_local i32 @atexit(void ()*)
+
+declare dso_local void @__cxa_guard_abort(i64*)
+
+declare dso_local void @__cxa_guard_release(i64*)
+
+declare dso_local i8* @__cxa_allocate_exception(i64)
+
+declare dso_local void @__cxa_throw(i8*, i8*, i8*)
+
+declare dso_local noalias i8* @_Znwy(i64)
+
+declare dso_local void @_ZdlPv(i8*)

Modified: llvm/trunk/test/CodeGen/X86/win64_call_epi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win64_call_epi.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win64_call_epi.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win64_call_epi.ll Mon Sep  9 16:04:25 2019
@@ -24,10 +24,9 @@ catch:
 ; WIN64: nop
 ; WIN64: addq ${{[0-9]+}}, %rsp
 ; WIN64: retq
-; Check for 'ud2' after noreturn call
+; Check for 'int3' after noreturn call.
 ; WIN64: callq _Unwind_Resume
-; WIN64-NEXT: ud2
-; WIN64: .seh_endproc
+; WIN64-NEXT: int3
 
 
 ; Check it still works when blocks are reordered.

Modified: llvm/trunk/test/CodeGen/X86/win64_eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win64_eh.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win64_eh.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win64_eh.ll Mon Sep  9 16:04:25 2019
@@ -125,11 +125,11 @@ endtryfinally:
 ; WIN64-LABEL: foo4:
 ; WIN64: .seh_proc foo4
 ; WIN64: .seh_handler _d_eh_personality, @unwind, @except
-; NORM:  subq $56, %rsp
-; ATOM:  leaq -56(%rsp), %rsp
-; WIN64: .seh_stackalloc 56
+; NORM:  subq $40, %rsp
+; ATOM:  leaq -40(%rsp), %rsp
+; WIN64: .seh_stackalloc 40
 ; WIN64: .seh_endprologue
-; WIN64: addq $56, %rsp
+; WIN64: addq $40, %rsp
 ; WIN64: ret
 ; WIN64: .seh_handlerdata
 ; WIN64: .seh_endproc

Modified: llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll (original)
+++ llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll Mon Sep  9 16:04:25 2019
@@ -320,6 +320,7 @@ unreachable:
 ; CHECK: [[test2_before_f2:.+]]:
 ; CHECK-NEXT: movl $2, %ecx
 ; CHECK-NEXT: callq f
+; CHECK-NEXT: int3
 ; CHECK-NEXT: [[test2_after_f2:.+]]:
 ; CHECK: [[test2_end:.*func_end.*]]:
 
@@ -511,6 +512,7 @@ unreachable:
 ; CHECK: [[test3_before_f4:.+]]:
 ; CHECK-NEXT: movl $4, %ecx
 ; CHECK-NEXT: callq f
+; CHECK-NEXT: int3
 ; CHECK-NEXT: [[test3_after_f4:.+]]:
 ; CHECK: .seh_proc [[test3_fault2:[^ ]+]]
 ; CHECK: # %fault2
@@ -518,6 +520,7 @@ unreachable:
 ; CHECK: [[test3_before_f3:.+]]:
 ; CHECK-NEXT: movl $3, %ecx
 ; CHECK-NEXT: callq f
+; CHECK-NEXT: int3
 ; CHECK-NEXT: [[test3_after_f3:.+]]:
 ; CHECK: .seh_proc [[test3_fault1:[^ ]+]]
 ; CHECK: # %fault1
@@ -525,6 +528,7 @@ unreachable:
 ; CHECK: [[test3_before_f2:.+]]:
 ; CHECK-NEXT: movl $2, %ecx
 ; CHECK-NEXT: callq f
+; CHECK-NEXT: int3
 ; CHECK-NEXT: [[test3_after_f2:.+]]:
 ; CHECK: [[test3_end:.*func_end.*]]:
 }

Modified: llvm/trunk/test/DebugInfo/COFF/local-variable-gap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/local-variable-gap.ll?rev=371466&r1=371465&r2=371466&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/local-variable-gap.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/local-variable-gap.ll Mon Sep  9 16:04:25 2019
@@ -54,7 +54,7 @@
 ; ASM: [[p_b2:\.Ltmp[0-9]+]]:
 ; ASM:         #DEBUG_VALUE: p <- $esi
 ; ASM:         callq   call_noreturn
-; ASM:         ud2
+; ASM:         int3
 ; ASM: .Lfunc_end0:
 
 ; ASM:         .short  {{.*}}         # Record length




More information about the llvm-commits mailing list