Files
clang-p2996/llvm/test/CodeGen/X86/catchret-regmask.ll
Roman Lebedev 18ff1ec3c3 Reland [SimplifyCFG] markAliveBlocks(): recognize that normal dest of invoked noreturn function is unreachable
As per LangRef's definition of `noreturn` attribute:
```
noreturn
  This function attribute indicates that the function never returns
  normally, hence through a return instruction.
  This produces undefined behavior at runtime if the function
  ever does dynamically return. nnotated functions may still
  raise an exception, i.a., nounwind is not implied.
```

So if we `invoke` a `noreturn` function, and the normal destination
of an invoke is not an `unreachable`, point it at the new `unreachable`
block.

The change/fix from the original commit is that we now actually create
the new block, and don't just repurpose the original block,
because said normal destination block could have other users.

This reverts commit db1176ce66,
relanding commit 598833c987.
2022-02-05 02:58:19 +03:00

77 lines
1.9 KiB
LLVM

; RUN: llc < %s | FileCheck %s
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
declare i32 @__CxxFrameHandler3(...)
declare void @throw() uwtable
declare i8* @getval()
declare void @llvm.trap()
define i8* @reload_out_of_pad(i8* %arg) #0 personality i32 (...)* @__CxxFrameHandler3 {
assertPassed:
invoke void @throw()
to label %unreachable unwind label %catch.dispatch
catch:
%cp = catchpad within %cs [i8* null, i32 0, i8* null]
catchret from %cp to label %return
; 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:
%cs = catchswitch within none [label %catch] unwind to caller
return:
ret i8* %arg
}
; CHECK-LABEL: reload_out_of_pad: # @reload_out_of_pad
; CHECK: movq %rcx, -[[arg_slot:[0-9]+]](%rbp) # 8-byte Spill
; CHECK: callq throw
; CHECK: ud2
; CHECK: movq -[[arg_slot]](%rbp), %rax # 8-byte Reload
; CHECK: retq
; CHECK: "?catch${{[0-9]+}}@?0?reload_out_of_pad@4HA":
; CHECK-NOT: Reload
; CHECK: retq
define i8* @spill_in_pad() #0 personality i32 (...)* @__CxxFrameHandler3 {
assertPassed:
invoke void @throw()
to label %unreachable unwind label %catch.dispatch
catch:
%cp = catchpad within %cs [i8* null, i32 0, i8* null]
%val = call i8* @getval() [ "funclet"(token %cp) ]
catchret from %cp to label %return
unreachable:
call void @llvm.trap()
unreachable
catch.dispatch:
%cs = catchswitch within none [label %catch] unwind to caller
return:
ret i8* %val
}
; CHECK-LABEL: spill_in_pad: # @spill_in_pad
; CHECK: callq throw
; CHECK: ud2
; CHECK: movq -[[val_slot:[0-9]+]](%rbp), %rax # 8-byte Reload
; CHECK: retq
; CHECK: "?catch${{[0-9]+}}@?0?spill_in_pad@4HA":
; CHECK: callq getval
; CHECK: movq %rax, -[[val_slot]](%rbp) # 8-byte Spill
; CHECK: retq
attributes #0 = { uwtable }