[llvm] [X86] Fix RegAlloc issue by implementing TRI::getCustomEHPadPreservedMask (PR #135518)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 12 22:03:47 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Sergei Barannikov (s-barannikov)
<details>
<summary>Changes</summary>
This method needs to be implemented so that the register allocator can
correctly split live ranges of loop invariant virtual registers.
This default return value is correct for DWARF unwinder, which preserves
all registers (except exception pointer/selector), but not for SjLj,
which only preserves sp/fp and possibly bp (they should be reserved).
In the added test `rcx` on the entry to the loop contains the argument
to `foo`. It survives the call due to `preserve_allcc`, but not the
unwind edge entering `LBB0_3`, and so must be recomputed before going to
the next iteration.
Similarly, `rdx` holds the address of a jump table and is recomputed on
every iteration rather than once before the loop.
---
Full diff: https://github.com/llvm/llvm-project/pull/135518.diff
3 Files Affected:
- (modified) llvm/lib/Target/X86/X86RegisterInfo.cpp (+7)
- (modified) llvm/lib/Target/X86/X86RegisterInfo.h (+2)
- (added) llvm/test/CodeGen/X86/sjlj-unwind-clobber.ll (+76)
``````````diff
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..c1d718a9f7031
--- /dev/null
+++ b/llvm/test/CodeGen/X86/sjlj-unwind-clobber.ll
@@ -0,0 +1,76 @@
+; 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 dso_local i32 @__gxx_personality_sj0(...)
+declare dso_local preserve_allcc void @foo(ptr)
+
+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, -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 at 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
+; 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 at 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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/135518
More information about the llvm-commits
mailing list