diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index 1c4114f8cc9c6..68c227cb987de 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -525,6 +525,13 @@ X86RegisterInfo::getNoPreservedMask() const { return CSR_NoRegs_RegMask; } +const uint32_t * +X86RegisterInfo::getCustomEHPadPreservedMask(const MachineFunction &MF) const { + if (MF.getTarget().Options.ExceptionModel == ExceptionHandling::SjLj) + return getNoPreservedMask(); + return TargetRegisterInfo::getCustomEHPadPreservedMask(MF); +} + const uint32_t *X86RegisterInfo::getDarwinTLSCallPreservedMask() const { return CSR_64_TLS_Darwin_RegMask; } diff --git a/llvm/lib/Target/X86/X86RegisterInfo.h b/llvm/lib/Target/X86/X86RegisterInfo.h index 5b6ac3c5da019..d9491cd225827 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.h +++ b/llvm/lib/Target/X86/X86RegisterInfo.h @@ -102,6 +102,8 @@ class X86RegisterInfo final : public X86GenRegisterInfo { const uint32_t *getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override; const uint32_t *getNoPreservedMask() const override; + const uint32_t * + getCustomEHPadPreservedMask(const MachineFunction &MF) const override; // Calls involved in thread-local variable lookup save more registers than // normal calls, so they need a different mask to represent this. diff --git a/llvm/test/CodeGen/X86/sjlj-unwind-clobber.ll b/llvm/test/CodeGen/X86/sjlj-unwind-clobber.ll new file mode 100644 index 0000000000000..596e42fa8c6a2 --- /dev/null +++ b/llvm/test/CodeGen/X86/sjlj-unwind-clobber.ll @@ -0,0 +1,86 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=x86_64 -exception-model=sjlj -o - %s | FileCheck %s + +declare i32 @__gxx_personality_sj0(...) +declare preserve_allcc void @foo(ptr) + +; Check that register allocator splits live ranges of loop invariant virtual +; registers as they don't survive the unwind edge of an invoke. +; The argument of `foo` (passed in %rdi) and the address of the jump table +; (base register of `jmpq`) are loop invariant. They survive the call to `foo`, +; but are clobbered by the unwinder when `foo` throws an exception, and so +; their live ranges must be split around the unwind edge `callq foo` -> LBB0_3. +; This is achieved by recalculating their values before each use rather than +; once before the loop as was the case before register allocation. + +define void @test() personality ptr @__gxx_personality_sj0 { +; CHECK-LABEL: test: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: movq %rsp, %rbp +; CHECK-NEXT: pushq %r15 +; CHECK-NEXT: pushq %r14 +; CHECK-NEXT: pushq %r13 +; CHECK-NEXT: pushq %r12 +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: subq $104, %rsp +; CHECK-NEXT: movq __gxx_personality_sj0@GOTPCREL(%rip), %rax +; CHECK-NEXT: movq %rax, -104(%rbp) +; CHECK-NEXT: movq $GCC_except_table0, -96(%rbp) +; CHECK-NEXT: movq %rbp, -88(%rbp) +; CHECK-NEXT: movq %rsp, -72(%rbp) +; CHECK-NEXT: movq $.LBB0_3, -80(%rbp) +; CHECK-NEXT: leaq -136(%rbp), %rdi +; CHECK-NEXT: callq _Unwind_SjLj_Register@PLT +; CHECK-NEXT: leaq -44(%rbp), %rcx +; CHECK-NEXT: .LBB0_1: # %while.cond +; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: movl $1, -128(%rbp) +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: movq %rcx, %rdi +; CHECK-NEXT: callq foo@PLT +; CHECK-NEXT: .Ltmp1: +; CHECK-NEXT: jmp .LBB0_2 +; CHECK-NEXT: .LBB0_3: # in Loop: Header=BB0_1 Depth=1 +; CHECK-NEXT: leaq -44(%rbp), %rcx +; CHECK-NEXT: movl -128(%rbp), %eax +; CHECK-NEXT: cmpl $1, %eax +; CHECK-NEXT: jae .LBB0_5 +; CHECK-NEXT: # %bb.4: # in Loop: Header=BB0_1 Depth=1 +; CHECK-NEXT: leaq .LJTI0_0(%rip), %rdx +; CHECK-NEXT: jmpq *(%rdx,%rax,8) +; CHECK-NEXT: .LBB0_6: # %lpad +; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1 +; CHECK-NEXT: .Ltmp2: +; CHECK-NEXT: movl -124(%rbp), %eax +; CHECK-NEXT: movl -120(%rbp), %eax +; CHECK-NEXT: jmp .LBB0_1 +; CHECK-NEXT: .LBB0_2: # %while.end +; CHECK-NEXT: leaq -136(%rbp), %rdi +; CHECK-NEXT: callq _Unwind_SjLj_Unregister@PLT +; CHECK-NEXT: addq $104, %rsp +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: popq %r12 +; CHECK-NEXT: popq %r13 +; CHECK-NEXT: popq %r14 +; CHECK-NEXT: popq %r15 +; CHECK-NEXT: popq %rbp +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB0_5: +; CHECK-NEXT: ud2 +entry: + %ptr = alloca i32, align 4 + br label %while.cond + +while.cond: + invoke preserve_allcc void @foo(ptr %ptr) + to label %while.end unwind label %lpad + +lpad: + %lp = landingpad { ptr, i32 } + catch ptr null + br label %while.cond + +while.end: + ret void +}