[llvm] [X86] Don't save/restore fp around longjmp instructions (PR #102556)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 8 17:53:26 PDT 2024


https://github.com/weiguozhi created https://github.com/llvm/llvm-project/pull/102556

Longjmp instructions can also modify fp register, it is expected behavior. We should not save/restore fp around these instructions.

>From 9cae8fbc5792b59026a48cffdc182eae32982206 Mon Sep 17 00:00:00 2001
From: Guozhi Wei <carrot at google.com>
Date: Thu, 8 Aug 2024 17:47:33 -0700
Subject: [PATCH] [X86] Don't save/restore fp around longjmp instructions

Longjmp instructions can also modify fp register, it is expected
behavior. We should not save/restore fp around these instructions.
---
 llvm/lib/Target/X86/X86FrameLowering.cpp     |  6 +++
 llvm/lib/Target/X86/X86ISelLowering.cpp      |  2 +
 llvm/lib/Target/X86/X86MachineFunctionInfo.h | 11 +++++
 llvm/test/CodeGen/X86/clobber_frame_ptr.ll   | 43 ++++++++++++++++++++
 4 files changed, 62 insertions(+)

diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 8404f2231680d..8760e97e684e3 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -4389,6 +4389,12 @@ bool X86FrameLowering::skipSpillFPBP(
       ++MI;
     return true;
   }
+
+  // FP clobbered by longjmp is expected.
+  X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
+  if (X86FI->containLongJmpMIClobberFP(&*MI))
+    return true;
+
   return false;
 }
 
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index f69606783f25c..6974d18814eb7 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -36205,6 +36205,8 @@ X86TargetLowering::emitEHSjLjLongJmp(MachineInstr &MI,
       MIB.add(MO);
   }
   MIB.setMemRefs(MMOs);
+  auto *MFI = MF->getInfo<X86MachineFunctionInfo>();
+  MFI->insertLongJmpMIClobberFP(MIB.getInstr());
 
   // Reload IP
   MIB = BuildMI(*thisMBB, MI, MIMD, TII->get(PtrLoadOpc), Tmp);
diff --git a/llvm/lib/Target/X86/X86MachineFunctionInfo.h b/llvm/lib/Target/X86/X86MachineFunctionInfo.h
index 13d57c2fa9dfb..bf3ffdc8677bf 100644
--- a/llvm/lib/Target/X86/X86MachineFunctionInfo.h
+++ b/llvm/lib/Target/X86/X86MachineFunctionInfo.h
@@ -14,6 +14,7 @@
 #define LLVM_LIB_TARGET_X86_X86MACHINEFUNCTIONINFO_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MIRYamlMapping.h"
@@ -174,6 +175,9 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   bool FPClobberedByCall = false;
   bool BPClobberedByCall = false;
 
+  // A set of instructions clobber FP generated from longjmp.
+  SmallSet<MachineInstr *, 2> LongJmpMIClobberFP;
+
 private:
   /// ForwardedMustTailRegParms - A list of virtual and physical registers
   /// that must be forwarded to every musttail call.
@@ -338,6 +342,13 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
 
   bool getBPClobberedByCall() const { return BPClobberedByCall; }
   void setBPClobberedByCall(bool C) { BPClobberedByCall = C; }
+
+  bool containLongJmpMIClobberFP(MachineInstr *MI) const {
+    return LongJmpMIClobberFP.contains(MI);
+  }
+  void insertLongJmpMIClobberFP(MachineInstr *MI) {
+    LongJmpMIClobberFP.insert(MI);
+  }
 };
 
 } // End llvm namespace
diff --git a/llvm/test/CodeGen/X86/clobber_frame_ptr.ll b/llvm/test/CodeGen/X86/clobber_frame_ptr.ll
index 6209e1a85e9e1..fd8ba7feb9f48 100644
--- a/llvm/test/CodeGen/X86/clobber_frame_ptr.ll
+++ b/llvm/test/CodeGen/X86/clobber_frame_ptr.ll
@@ -157,3 +157,46 @@ define i64 @test3(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6,
   %x = call cc 11 i64 @hipe2(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7)
   ret i64 %x
 }
+
+ at buf = dso_local global [20 x ptr] zeroinitializer, align 16
+
+; longjmp modifies fp, it is expected behavior, wo should not save/restore fp
+; around it.
+define void @test4() {
+; CHECK-LABEL: test4:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    .cfi_offset %rbp, -16
+; CHECK-NEXT:    movq %rsp, %rbp
+; CHECK-NEXT:    .cfi_def_cfa_register %rbp
+; CHECK-NEXT:    pushq %r15
+; CHECK-NEXT:    pushq %r14
+; CHECK-NEXT:    pushq %r13
+; CHECK-NEXT:    pushq %r12
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    andq $-16, %rsp
+; CHECK-NEXT:    subq $16, %rsp
+; CHECK-NEXT:    .cfi_offset %rbx, -56
+; CHECK-NEXT:    .cfi_offset %r12, -48
+; CHECK-NEXT:    .cfi_offset %r13, -40
+; CHECK-NEXT:    .cfi_offset %r14, -32
+; CHECK-NEXT:    .cfi_offset %r15, -24
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    .cfi_remember_state
+; CHECK-NEXT:    .cfi_escape 0x0f, 0x06, 0x77, 0x08, 0x06, 0x11, 0x10, 0x22 #
+; CHECK-NEXT:    xorl %r13d, %r13d
+; CHECK-NEXT:    callq external at PLT
+; CHECK-NEXT:    addq $8, %rsp
+; CHECK-NEXT:    popq %rbp
+; CHECK-NEXT:    .cfi_restore_state
+; CHECK-NEXT:    movq buf(%rip), %rbp
+; CHECK-NEXT:    movq buf+8(%rip), %rax
+; CHECK-NEXT:    movq buf+16(%rip), %rsp
+; CHECK-NEXT:    jmpq *%rax
+entry:
+  %x = call ghccc i32 @external(i32 0)
+  call void @llvm.eh.sjlj.longjmp(ptr @buf)
+  unreachable
+}



More information about the llvm-commits mailing list