[llvm] [X86] Avoid redundant SSE bounce in x87 FP_EXTEND(FP_ROUND) conversions (PR #213494)

via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 1 17:13:39 PDT 2026


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/213494

>From c3bb27afc982313752b20e544bf825e7344053c4 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sat, 1 Aug 2026 20:08:12 -0400
Subject: [PATCH 1/2] [X86] Add pre-commit test case for x87 float return and
 SSE roundtrip

---
 llvm/test/CodeGen/X86/x87-inout-bounce.ll | 94 +++++++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/x87-inout-bounce.ll

diff --git a/llvm/test/CodeGen/X86/x87-inout-bounce.ll b/llvm/test/CodeGen/X86/x87-inout-bounce.ll
new file mode 100644
index 0000000000000..161ca2c1742b1
--- /dev/null
+++ b/llvm/test/CodeGen/X86/x87-inout-bounce.ll
@@ -0,0 +1,94 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -mattr=+sse2,+x87 | FileCheck %s
+
+define float @returns_float() {
+; CHECK-LABEL: returns_float:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subl $12, %esp
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    calll rand at PLT
+; CHECK-NEXT:    cvtsi2ss %eax, %xmm0
+; CHECK-NEXT:    movss %xmm0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    flds {{[0-9]+}}(%esp)
+; CHECK-NEXT:    addl $12, %esp
+; CHECK-NEXT:    .cfi_def_cfa_offset 4
+; CHECK-NEXT:    retl
+entry:
+  %call = call i32 @rand()
+  %conv = sitofp i32 %call to float
+  ret float %conv
+}
+
+declare i32 @rand()
+
+define float @example_float() {
+; CHECK-LABEL: example_float:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subl $28, %esp
+; CHECK-NEXT:    .cfi_def_cfa_offset 32
+; CHECK-NEXT:    calll returns_float at PLT
+; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    movss %xmm0, (%esp) # 4-byte Spill
+; CHECK-NEXT:    calll returns_float at PLT
+; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT:    movss (%esp), %xmm0 # 4-byte Reload
+; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    addss {{[0-9]+}}(%esp), %xmm0
+; CHECK-NEXT:    movss %xmm0, (%esp) # 4-byte Spill
+; CHECK-NEXT:    calll returns_float at PLT
+; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT:    movss (%esp), %xmm0 # 4-byte Reload
+; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    addss {{[0-9]+}}(%esp), %xmm0
+; CHECK-NEXT:    movss %xmm0, (%esp) # 4-byte Spill
+; CHECK-NEXT:    calll returns_float at PLT
+; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT:    movss (%esp), %xmm0 # 4-byte Reload
+; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    addss {{[0-9]+}}(%esp), %xmm0
+; CHECK-NEXT:    movss %xmm0, (%esp) # 4-byte Spill
+; CHECK-NEXT:    calll returns_float at PLT
+; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT:    movss (%esp), %xmm0 # 4-byte Reload
+; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    addss {{[0-9]+}}(%esp), %xmm0
+; CHECK-NEXT:    movss %xmm0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    flds {{[0-9]+}}(%esp)
+; CHECK-NEXT:    addl $28, %esp
+; CHECK-NEXT:    .cfi_def_cfa_offset 4
+; CHECK-NEXT:    retl
+entry:
+  %call = call float @returns_float()
+  %call1 = call float @returns_float()
+  %add = fadd float %call, %call1
+  %call2 = call float @returns_float()
+  %add3 = fadd float %add, %call2
+  %call4 = call float @returns_float()
+  %add5 = fadd float %add3, %call4
+  %call6 = call float @returns_float()
+  %add7 = fadd float %add5, %call6
+  ret float %add7
+}
+
+declare x86_fp80 @returns_long_double()
+
+define x86_fp80 @testC() {
+; CHECK-LABEL: testC:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subl $12, %esp
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    calll returns_long_double at PLT
+; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    movss %xmm0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    flds {{[0-9]+}}(%esp)
+; CHECK-NEXT:    addl $12, %esp
+; CHECK-NEXT:    .cfi_def_cfa_offset 4
+; CHECK-NEXT:    retl
+entry:
+  %call = call x86_fp80 @returns_long_double()
+  %conv = fptrunc x86_fp80 %call to float
+  %conv1 = fpext float %conv to x86_fp80
+  ret x86_fp80 %conv1
+}

>From 402cde2e60137f93ef70266ba419e6228aa40dcc Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sat, 1 Aug 2026 20:10:08 -0400
Subject: [PATCH 2/2] [X86] Avoid redundant SSE bounce in x87
 FP_EXTEND(FP_ROUND) conversions

In 32-bit x86 code generation with both x87 and SSE enabled (e.g., `-mtriple=i386-unknown-linux-gnu -mattr=+sse2,+x87`), floating-point values returned in `st(0)` that undergo a sequence of truncation and extension (such as `fptrunc` to `float` followed by `fpext` to `x86_fp80`) were previously bouncing through SSE XMM registers (`movss`).
---
 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp   | 36 ++++++++++++++++++-----
 llvm/test/CodeGen/X86/x87-inout-bounce.ll |  2 --
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index d078117061677..80bf5bab2aca7 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -1449,18 +1449,40 @@ void X86DAGToDAGISel::PreprocessISelDAG() {
       // FPStack has extload and truncstore.  SSE can fold direct loads into other
       // operations.  Based on this, decide what we want to do.
       MVT MemVT = (N->getOpcode() == ISD::FP_ROUND) ? DstVT : SrcVT;
-      SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
-      int SPFI = cast<FrameIndexSDNode>(MemTmp)->getIndex();
-      MachinePointerInfo MPI =
-          MachinePointerInfo::getFixedStack(CurDAG->getMachineFunction(), SPFI);
       SDLoc dl(N);
 
       // FIXME: optimize the case where the src/dest is a load or store?
+      SDValue SrcVal = N->getOperand(0);
+      SDValue Store, MemTmp;
+      MachinePointerInfo MemMPI;
+
+      if (auto *LD = dyn_cast<LoadSDNode>(SrcVal)) {
+        if (LD->getMemoryVT() == MemVT) {
+          Store = LD->getChain();
+          MemTmp = LD->getBasePtr();
+          MemMPI = LD->getPointerInfo();
+        }
+      } else if (SrcVal.getOpcode() == ISD::FP_ROUND) {
+        MemTmp = CurDAG->CreateStackTemporary(MemVT);
+        int SPFI = cast<FrameIndexSDNode>(MemTmp)->getIndex();
+        MemMPI = MachinePointerInfo::getFixedStack(CurDAG->getMachineFunction(),
+                                                   SPFI);
+        Store =
+            CurDAG->getTruncStore(CurDAG->getEntryNode(), dl,
+                                  SrcVal.getOperand(0), MemTmp, MemMPI, MemVT);
+      }
+
+      if (!MemTmp) {
+        MemTmp = CurDAG->CreateStackTemporary(MemVT);
+        int SPFI = cast<FrameIndexSDNode>(MemTmp)->getIndex();
+        MemMPI = MachinePointerInfo::getFixedStack(CurDAG->getMachineFunction(),
+                                                   SPFI);
+        Store = CurDAG->getTruncStore(CurDAG->getEntryNode(), dl, SrcVal,
+                                      MemTmp, MemMPI, MemVT);
+      }
 
-      SDValue Store = CurDAG->getTruncStore(
-          CurDAG->getEntryNode(), dl, N->getOperand(0), MemTmp, MPI, MemVT);
       SDValue Result = CurDAG->getExtLoad(ISD::EXTLOAD, dl, DstVT, Store,
-                                          MemTmp, MPI, MemVT);
+                                          MemTmp, MemMPI, MemVT);
 
       // We're about to replace all uses of the FP_ROUND/FP_EXTEND with the
       // extload we created.  This will cause general havok on the dag because
diff --git a/llvm/test/CodeGen/X86/x87-inout-bounce.ll b/llvm/test/CodeGen/X86/x87-inout-bounce.ll
index 161ca2c1742b1..bc531aef9219c 100644
--- a/llvm/test/CodeGen/X86/x87-inout-bounce.ll
+++ b/llvm/test/CodeGen/X86/x87-inout-bounce.ll
@@ -80,8 +80,6 @@ define x86_fp80 @testC() {
 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
 ; CHECK-NEXT:    calll returns_long_double at PLT
 ; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
-; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; CHECK-NEXT:    movss %xmm0, {{[0-9]+}}(%esp)
 ; CHECK-NEXT:    flds {{[0-9]+}}(%esp)
 ; CHECK-NEXT:    addl $12, %esp
 ; CHECK-NEXT:    .cfi_def_cfa_offset 4



More information about the llvm-commits mailing list