[llvm] [X86] Eliminate dead SSE loads and stores after rewriting stack spills (PR #213498)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 2 07:56:51 PDT 2026
https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/213498
>From 444f8f46066a5b97436f23b8db9928aa1b9fc46c 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 af6ea890804f4fbf19c4a3747cf83fb5ebf5fbf3 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sat, 1 Aug 2026 21:20:34 -0400
Subject: [PATCH 2/2] [X86] Eliminate dead SSE loads and stores after rewriting
stack spills
These spills are redundant and can be removed.
---
llvm/lib/Target/X86/X86FixupInstTuning.cpp | 211 ++++++++++++++++++++
llvm/test/CodeGen/X86/fp-intrinsics.ll | 40 +---
llvm/test/CodeGen/X86/fp80-strict-scalar.ll | 12 +-
llvm/test/CodeGen/X86/scalar-int-to-fp.ll | 84 ++------
llvm/test/CodeGen/X86/x87-inout-bounce.ll | 31 ++-
5 files changed, 269 insertions(+), 109 deletions(-)
diff --git a/llvm/lib/Target/X86/X86FixupInstTuning.cpp b/llvm/lib/Target/X86/X86FixupInstTuning.cpp
index 621fd35a03cd5..ecb8a6eb4f545 100644
--- a/llvm/lib/Target/X86/X86FixupInstTuning.cpp
+++ b/llvm/lib/Target/X86/X86FixupInstTuning.cpp
@@ -29,7 +29,9 @@
#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/IR/Analysis.h"
using namespace llvm;
@@ -47,6 +49,8 @@ class X86FixupInstTuningImpl {
bool processInstruction(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator &I);
+ bool processSpills(MachineBasicBlock &MBB, MachineFunction &MF);
+
const X86InstrInfo *TII = nullptr;
const X86Subtarget *ST = nullptr;
const MCSchedModel *SM = nullptr;
@@ -88,6 +92,212 @@ static std::optional<bool> CmpOptionals(T NewVal, T CurVal) {
return std::nullopt;
}
+bool X86FixupInstTuningImpl::processSpills(MachineBasicBlock &MBB,
+ MachineFunction &MF) {
+ bool Changed = false;
+
+ // Tracks a load->store chain: load from OrigFI into Reg, store Reg to
+ // SpillFI. We want to redirect later loads from SpillFI to OrigFI.
+ struct SpillEntry {
+ SmallVector<MachineOperand, X86::AddrNumOperands> OrigMOs;
+ MachineInstr *LoadMI = nullptr; // The original load from OrigFI.
+ MachineInstr *StoreMI = nullptr; // The store to SpillFI.
+ MCRegister LoadReg; // The register used as intermediary.
+ unsigned UseCount = 0; // Number of loads from SpillFI seen.
+ unsigned RewriteCount = 0; // Number successfully rewritten.
+ };
+
+ // Maps SpillFI -> SpillEntry (the redirect info for that slot).
+ DenseMap<int, SpillEntry> SpillMap;
+
+ // Maps physical register -> (OrigFI, address operands, LoadMI).
+ // Keyed by the canonical (largest) super-register to handle aliasing.
+ struct RegEntry {
+ SmallVector<MachineOperand, X86::AddrNumOperands> MOs;
+ MachineInstr *LoadMI = nullptr;
+ int FI = -1;
+ };
+ DenseMap<MCRegister, RegEntry> RegToFI;
+
+ auto InvalidateReg = [&](MCRegister Reg) {
+ for (MCRegAliasIterator AI(Reg, TRI, /*IncludeSelf=*/true); AI.isValid();
+ ++AI)
+ RegToFI.erase(*AI);
+ };
+
+ auto IsSafeToEraseLoad = [&](MachineInstr *LoadMI, MachineInstr *StoreMI,
+ MCRegister Reg) -> bool {
+ // Walk forward from LoadMI. The register must not be read by anything
+ // other than StoreMI, and must be redefined (or reach end-of-block
+ // without being live-out).
+ for (MachineBasicBlock::iterator I = std::next(LoadMI->getIterator()),
+ E = MBB.end();
+ I != E; ++I) {
+ if (&*I == StoreMI)
+ continue;
+ if (I->readsRegister(Reg, TRI))
+ return false;
+ if (I->definesRegister(Reg, TRI))
+ return true;
+ }
+ // Check if the register is live-out of the block.
+ for (MCRegAliasIterator AI(Reg, TRI, /*IncludeSelf=*/true); AI.isValid();
+ ++AI) {
+ for (MachineBasicBlock *Succ : MBB.successors()) {
+ if (Succ->isLiveIn(*AI))
+ return false;
+ }
+ }
+ return true;
+ };
+
+ for (MachineInstr &MI : MBB) {
+ if (MI.isCall()) {
+ // Calls clobber registers. Memory state (SpillMap) is preserved
+ // because local stack slots don't escape through calls.
+ RegToFI.clear();
+ continue;
+ }
+
+ int LoadedFI = -1;
+ MCRegister LoadedReg(TII->isLoadFromStackSlotPostFE(MI, LoadedFI));
+
+ if (LoadedReg) {
+ auto It = SpillMap.find(LoadedFI);
+ if (It != SpillMap.end()) {
+ // This load reads from a SpillFI we're tracking. Rewrite it to
+ // read directly from OrigFI.
+ SpillEntry &SE = It->second;
+ SE.UseCount++;
+ int MemIdx = X86::getFirstAddrOperandIdx(MI);
+ if (MemIdx >= 0) {
+ for (int i = 0; i < X86::AddrNumOperands; ++i)
+ MI.getOperand(MemIdx + i) = SE.OrigMOs[i];
+ // Drop stale MMOs — they still reference SpillFI.
+ MI.dropMemRefs(MF);
+ SE.RewriteCount++;
+ Changed = true;
+ }
+ }
+ }
+
+ // MMO-based fallback: handles x87 loads (LD_F32m, LD_F64m, etc.) that
+ // aren't recognized by isLoadFromStackSlotPostFE because they aren't
+ // in isFrameLoadOpcode, but do have valid FixedStackPseudoSourceValue
+ // MMOs. We can rewrite address operands but cannot delete the store
+ // (since we can't track all uses via this path reliably).
+ if (!LoadedReg && MI.mayLoad()) {
+ int MemIdx = X86::getFirstAddrOperandIdx(MI);
+ if (MemIdx >= 0) {
+ for (const MachineMemOperand *MMO : MI.memoperands()) {
+ if (!MMO->isLoad())
+ continue;
+ const auto *FSPV =
+ dyn_cast_or_null<FixedStackPseudoSourceValue>(
+ MMO->getPseudoValue());
+ if (!FSPV)
+ continue;
+ int FI = FSPV->getFrameIndex();
+ auto It = SpillMap.find(FI);
+ if (It != SpillMap.end()) {
+ SpillEntry &SE = It->second;
+ SE.UseCount++;
+ for (int i = 0; i < X86::AddrNumOperands; ++i)
+ MI.getOperand(MemIdx + i) = SE.OrigMOs[i];
+ MI.dropMemRefs(MF);
+ SE.RewriteCount++;
+ Changed = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // --- Step 2: Check if this instruction stores to a stack slot ---
+ int StoredFI = -1;
+ MCRegister StoredReg(TII->isStoreToStackSlotPostFE(MI, StoredFI));
+
+ if (StoredReg) {
+ // If the stored register was loaded from a known FI, record the chain.
+ auto It = RegToFI.find(StoredReg);
+ if (It != RegToFI.end()) {
+ SpillEntry SE;
+ SE.OrigMOs = It->second.MOs;
+ SE.LoadMI = It->second.LoadMI;
+ SE.LoadReg = StoredReg;
+ SE.StoreMI = &MI;
+ SpillMap[StoredFI] = SE;
+ } else {
+ // The store overwrites SpillFI with unknown data — invalidate.
+ SpillMap.erase(StoredFI);
+ }
+ }
+
+ // --- Step 3: Memory invalidation for non-stack-slot stores ---
+ // If the instruction writes to memory but we couldn't identify it as a
+ // simple stack slot store, check MMOs for stores to tracked SpillFIs.
+ // Only invalidate what we can't identify.
+ if (MI.mayStore() && !StoredReg) {
+ bool HasUnknownStore = false;
+ for (const MachineMemOperand *MMO : MI.memoperands()) {
+ if (!MMO->isStore())
+ continue;
+ const auto *FSPV =
+ dyn_cast_or_null<FixedStackPseudoSourceValue>(
+ MMO->getPseudoValue());
+ if (FSPV) {
+ // Known FI store — invalidate just that entry.
+ SpillMap.erase(FSPV->getFrameIndex());
+ } else {
+ HasUnknownStore = true;
+ }
+ }
+ if (HasUnknownStore)
+ SpillMap.clear();
+ }
+
+ // --- Step 4: Register invalidation with aliasing ---
+ // Any register def (explicit or implicit) invalidates all aliases.
+ for (const MachineOperand &MO : MI.operands()) {
+ if (MO.isReg() && MO.isDef() && MO.getReg().isPhysical())
+ InvalidateReg(MO.getReg());
+ }
+
+ // --- Step 5: Track loads from stack slots ---
+ if (LoadedReg) {
+ int MemIdx = X86::getFirstAddrOperandIdx(MI);
+ if (MemIdx >= 0) {
+ RegEntry RE;
+ for (int i = 0; i < X86::AddrNumOperands; ++i)
+ RE.MOs.push_back(MI.getOperand(MemIdx + i));
+ RE.LoadMI = &MI;
+ RE.FI = LoadedFI;
+ RegToFI[LoadedReg] = RE;
+ }
+ }
+ }
+
+ SmallPtrSet<MachineInstr *, 4> ToErase;
+ for (auto &[FI, SE] : SpillMap) {
+ // Only delete the store if ALL loads from SpillFI were rewritten.
+ if (SE.RewriteCount > 0 && SE.RewriteCount == SE.UseCount) {
+ if (SE.StoreMI)
+ ToErase.insert(SE.StoreMI);
+ // Only delete the load if its register is provably dead.
+ if (SE.LoadMI && SE.StoreMI &&
+ IsSafeToEraseLoad(SE.LoadMI, SE.StoreMI, SE.LoadReg))
+ ToErase.insert(SE.LoadMI);
+ }
+ }
+
+ for (MachineInstr *MI : ToErase) {
+ MI->eraseFromParent();
+ Changed = true;
+ }
+
+ return Changed;
+}
+
bool X86FixupInstTuningImpl::processInstruction(
MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator &I) {
@@ -712,6 +922,7 @@ bool X86FixupInstTuningImpl::runOnMachineFunction(MachineFunction &MF) {
SM = &ST->getSchedModel();
for (MachineBasicBlock &MBB : MF) {
+ Changed |= processSpills(MBB, MF);
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
if (processInstruction(MF, MBB, I)) {
++NumInstChanges;
diff --git a/llvm/test/CodeGen/X86/fp-intrinsics.ll b/llvm/test/CodeGen/X86/fp-intrinsics.ll
index 5d69a217fb402..abfa265092848 100644
--- a/llvm/test/CodeGen/X86/fp-intrinsics.ll
+++ b/llvm/test/CodeGen/X86/fp-intrinsics.ll
@@ -1080,8 +1080,6 @@ define i64 @f20s64(double %x) #0 {
; X86-SSE: # %bb.0: # %entry
; X86-SSE-NEXT: subl $20, %esp
; X86-SSE-NEXT: .cfi_def_cfa_offset 24
-; X86-SSE-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
-; X86-SSE-NEXT: movsd %xmm0, {{[0-9]+}}(%esp)
; X86-SSE-NEXT: fldl {{[0-9]+}}(%esp)
; X86-SSE-NEXT: wait
; X86-SSE-NEXT: fnstcw {{[0-9]+}}(%esp)
@@ -2076,9 +2074,7 @@ define double @sifdi(i32 %x) #0 {
; X87: # %bb.0: # %entry
; X87-NEXT: pushl %eax
; X87-NEXT: .cfi_def_cfa_offset 8
-; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X87-NEXT: movl %eax, (%esp)
-; X87-NEXT: fildl (%esp)
+; X87-NEXT: fildl {{[0-9]+}}(%esp)
; X87-NEXT: wait
; X87-NEXT: popl %eax
; X87-NEXT: .cfi_def_cfa_offset 4
@@ -2205,9 +2201,7 @@ define float @siffi(i32 %x) #0 {
; X87: # %bb.0: # %entry
; X87-NEXT: pushl %eax
; X87-NEXT: .cfi_def_cfa_offset 8
-; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X87-NEXT: movl %eax, (%esp)
-; X87-NEXT: fildl (%esp)
+; X87-NEXT: fildl {{[0-9]+}}(%esp)
; X87-NEXT: wait
; X87-NEXT: popl %eax
; X87-NEXT: .cfi_def_cfa_offset 4
@@ -2407,10 +2401,8 @@ define double @uifdi(i32 %x) #0 {
; X87: # %bb.0: # %entry
; X87-NEXT: subl $12, %esp
; X87-NEXT: .cfi_def_cfa_offset 16
-; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X87-NEXT: movl %eax, (%esp)
; X87-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X87-NEXT: fildll (%esp)
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
; X87-NEXT: wait
; X87-NEXT: addl $12, %esp
; X87-NEXT: .cfi_def_cfa_offset 4
@@ -2420,10 +2412,8 @@ define double @uifdi(i32 %x) #0 {
; X86-SSE: # %bb.0: # %entry
; X86-SSE-NEXT: subl $20, %esp
; X86-SSE-NEXT: .cfi_def_cfa_offset 24
-; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-SSE-NEXT: movl %eax, (%esp)
; X86-SSE-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-SSE-NEXT: fildll (%esp)
+; X86-SSE-NEXT: fildll {{[0-9]+}}(%esp)
; X86-SSE-NEXT: fstpl {{[0-9]+}}(%esp)
; X86-SSE-NEXT: fldl {{[0-9]+}}(%esp)
; X86-SSE-NEXT: wait
@@ -2459,12 +2449,10 @@ define double @uifdl(i64 %x) #0 {
; X87: # %bb.0: # %entry
; X87-NEXT: subl $20, %esp
; X87-NEXT: .cfi_def_cfa_offset 24
-; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
; X87-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; X87-NEXT: movl %eax, (%esp)
; X87-NEXT: shrl $31, %ecx
-; X87-NEXT: fildll (%esp)
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
; X87-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; X87-NEXT: fstpl {{[0-9]+}}(%esp)
; X87-NEXT: fldl {{[0-9]+}}(%esp)
@@ -2484,10 +2472,7 @@ define double @uifdl(i64 %x) #0 {
; X86-SSE-NEXT: fildll {{[0-9]+}}(%esp)
; X86-SSE-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%eax,4)
; X86-SSE-NEXT: fstpl {{[0-9]+}}(%esp)
-; X86-SSE-NEXT: wait
-; X86-SSE-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
-; X86-SSE-NEXT: movsd %xmm0, (%esp)
-; X86-SSE-NEXT: fldl (%esp)
+; X86-SSE-NEXT: fldl {{[0-9]+}}(%esp)
; X86-SSE-NEXT: wait
; X86-SSE-NEXT: addl $28, %esp
; X86-SSE-NEXT: .cfi_def_cfa_offset 4
@@ -2629,10 +2614,8 @@ define float @uiffi(i32 %x) #0 {
; X87: # %bb.0: # %entry
; X87-NEXT: subl $12, %esp
; X87-NEXT: .cfi_def_cfa_offset 16
-; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X87-NEXT: movl %eax, (%esp)
; X87-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X87-NEXT: fildll (%esp)
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
; X87-NEXT: wait
; X87-NEXT: addl $12, %esp
; X87-NEXT: .cfi_def_cfa_offset 4
@@ -2642,8 +2625,6 @@ define float @uiffi(i32 %x) #0 {
; X86-SSE: # %bb.0: # %entry
; X86-SSE-NEXT: subl $20, %esp
; X86-SSE-NEXT: .cfi_def_cfa_offset 24
-; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-SSE-NEXT: movl %eax, {{[0-9]+}}(%esp)
; X86-SSE-NEXT: movl $0, {{[0-9]+}}(%esp)
; X86-SSE-NEXT: fildll {{[0-9]+}}(%esp)
; X86-SSE-NEXT: fstps {{[0-9]+}}(%esp)
@@ -2681,10 +2662,8 @@ define float @uiffl(i64 %x) #0 {
; X87: # %bb.0: # %entry
; X87-NEXT: subl $20, %esp
; X87-NEXT: .cfi_def_cfa_offset 24
-; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
; X87-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
; X87-NEXT: shrl $31, %ecx
; X87-NEXT: fildll {{[0-9]+}}(%esp)
; X87-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
@@ -2706,10 +2685,7 @@ define float @uiffl(i64 %x) #0 {
; X86-SSE-NEXT: fildll {{[0-9]+}}(%esp)
; X86-SSE-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%eax,4)
; X86-SSE-NEXT: fstps {{[0-9]+}}(%esp)
-; X86-SSE-NEXT: wait
-; X86-SSE-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; X86-SSE-NEXT: movss %xmm0, (%esp)
-; X86-SSE-NEXT: flds (%esp)
+; X86-SSE-NEXT: flds {{[0-9]+}}(%esp)
; X86-SSE-NEXT: wait
; X86-SSE-NEXT: addl $20, %esp
; X86-SSE-NEXT: .cfi_def_cfa_offset 4
diff --git a/llvm/test/CodeGen/X86/fp80-strict-scalar.ll b/llvm/test/CodeGen/X86/fp80-strict-scalar.ll
index b9b1ae60d479e..6276c36677d59 100644
--- a/llvm/test/CodeGen/X86/fp80-strict-scalar.ll
+++ b/llvm/test/CodeGen/X86/fp80-strict-scalar.ll
@@ -737,9 +737,7 @@ define x86_fp80 @sint32_to_fp80(i32 %x) #0 {
; X86: # %bb.0:
; X86-NEXT: pushl %eax
; X86-NEXT: .cfi_def_cfa_offset 8
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movl %eax, (%esp)
-; X86-NEXT: fildl (%esp)
+; X86-NEXT: fildl {{[0-9]+}}(%esp)
; X86-NEXT: wait
; X86-NEXT: popl %eax
; X86-NEXT: .cfi_def_cfa_offset 4
@@ -866,10 +864,8 @@ define x86_fp80 @uint32_to_fp80(i32 %x) #0 {
; X86-NEXT: .cfi_def_cfa_register %ebp
; X86-NEXT: andl $-8, %esp
; X86-NEXT: subl $8, %esp
-; X86-NEXT: movl 8(%ebp), %eax
-; X86-NEXT: movl %eax, (%esp)
; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: fildll (%esp)
+; X86-NEXT: fildll 8(%ebp)
; X86-NEXT: wait
; X86-NEXT: movl %ebp, %esp
; X86-NEXT: popl %ebp
@@ -899,12 +895,10 @@ define x86_fp80 @uint64_to_fp80(i64 %x) #0 {
; X86-NEXT: .cfi_def_cfa_register %ebp
; X86-NEXT: andl $-8, %esp
; X86-NEXT: subl $8, %esp
-; X86-NEXT: movl 8(%ebp), %eax
; X86-NEXT: movl 12(%ebp), %ecx
; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; X86-NEXT: movl %eax, (%esp)
; X86-NEXT: shrl $31, %ecx
-; X86-NEXT: fildll (%esp)
+; X86-NEXT: fildll 8(%ebp)
; X86-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; X86-NEXT: wait
; X86-NEXT: movl %ebp, %esp
diff --git a/llvm/test/CodeGen/X86/scalar-int-to-fp.ll b/llvm/test/CodeGen/X86/scalar-int-to-fp.ll
index 43c1a84f7cd6c..067bdd881e7f5 100644
--- a/llvm/test/CodeGen/X86/scalar-int-to-fp.ll
+++ b/llvm/test/CodeGen/X86/scalar-int-to-fp.ll
@@ -53,10 +53,8 @@ define float @u32_to_f(i32 %a) nounwind {
; SSE1_32-NEXT: movl %esp, %ebp
; SSE1_32-NEXT: andl $-8, %esp
; SSE1_32-NEXT: subl $16, %esp
-; SSE1_32-NEXT: movl 8(%ebp), %eax
-; SSE1_32-NEXT: movl %eax, {{[0-9]+}}(%esp)
; SSE1_32-NEXT: movl $0, {{[0-9]+}}(%esp)
-; SSE1_32-NEXT: fildll {{[0-9]+}}(%esp)
+; SSE1_32-NEXT: fildll 8(%ebp)
; SSE1_32-NEXT: fstps {{[0-9]+}}(%esp)
; SSE1_32-NEXT: flds {{[0-9]+}}(%esp)
; SSE1_32-NEXT: movl %ebp, %esp
@@ -69,10 +67,8 @@ define float @u32_to_f(i32 %a) nounwind {
; X87-NEXT: movl %esp, %ebp
; X87-NEXT: andl $-8, %esp
; X87-NEXT: subl $8, %esp
-; X87-NEXT: movl 8(%ebp), %eax
-; X87-NEXT: movl %eax, (%esp)
; X87-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X87-NEXT: fildll (%esp)
+; X87-NEXT: fildll 8(%ebp)
; X87-NEXT: movl %ebp, %esp
; X87-NEXT: popl %ebp
; X87-NEXT: retl
@@ -112,9 +108,7 @@ define float @s32_to_f(i32 %a) nounwind {
; X87-LABEL: s32_to_f:
; X87: # %bb.0:
; X87-NEXT: pushl %eax
-; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X87-NEXT: movl %eax, (%esp)
-; X87-NEXT: fildl (%esp)
+; X87-NEXT: fildl {{[0-9]+}}(%esp)
; X87-NEXT: popl %eax
; X87-NEXT: retl
%r = sitofp i32 %a to float
@@ -167,10 +161,8 @@ define double @u32_to_d(i32 %a) nounwind {
; SSE1_32-NEXT: movl %esp, %ebp
; SSE1_32-NEXT: andl $-8, %esp
; SSE1_32-NEXT: subl $8, %esp
-; SSE1_32-NEXT: movl 8(%ebp), %eax
-; SSE1_32-NEXT: movl %eax, (%esp)
; SSE1_32-NEXT: movl $0, {{[0-9]+}}(%esp)
-; SSE1_32-NEXT: fildll (%esp)
+; SSE1_32-NEXT: fildll 8(%ebp)
; SSE1_32-NEXT: movl %ebp, %esp
; SSE1_32-NEXT: popl %ebp
; SSE1_32-NEXT: retl
@@ -181,10 +173,8 @@ define double @u32_to_d(i32 %a) nounwind {
; X87-NEXT: movl %esp, %ebp
; X87-NEXT: andl $-8, %esp
; X87-NEXT: subl $8, %esp
-; X87-NEXT: movl 8(%ebp), %eax
-; X87-NEXT: movl %eax, (%esp)
; X87-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X87-NEXT: fildll (%esp)
+; X87-NEXT: fildll 8(%ebp)
; X87-NEXT: movl %ebp, %esp
; X87-NEXT: popl %ebp
; X87-NEXT: retl
@@ -232,18 +222,14 @@ define double @s32_to_d(i32 %a) nounwind {
; SSE1_32-LABEL: s32_to_d:
; SSE1_32: # %bb.0:
; SSE1_32-NEXT: pushl %eax
-; SSE1_32-NEXT: movl {{[0-9]+}}(%esp), %eax
-; SSE1_32-NEXT: movl %eax, (%esp)
-; SSE1_32-NEXT: fildl (%esp)
+; SSE1_32-NEXT: fildl {{[0-9]+}}(%esp)
; SSE1_32-NEXT: popl %eax
; SSE1_32-NEXT: retl
;
; X87-LABEL: s32_to_d:
; X87: # %bb.0:
; X87-NEXT: pushl %eax
-; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X87-NEXT: movl %eax, (%esp)
-; X87-NEXT: fildl (%esp)
+; X87-NEXT: fildl {{[0-9]+}}(%esp)
; X87-NEXT: popl %eax
; X87-NEXT: retl
%r = sitofp i32 %a to double
@@ -257,10 +243,8 @@ define x86_fp80 @u32_to_x(i32 %a) nounwind {
; CHECK32-NEXT: movl %esp, %ebp
; CHECK32-NEXT: andl $-8, %esp
; CHECK32-NEXT: subl $8, %esp
-; CHECK32-NEXT: movl 8(%ebp), %eax
-; CHECK32-NEXT: movl %eax, (%esp)
; CHECK32-NEXT: movl $0, {{[0-9]+}}(%esp)
-; CHECK32-NEXT: fildll (%esp)
+; CHECK32-NEXT: fildll 8(%ebp)
; CHECK32-NEXT: movl %ebp, %esp
; CHECK32-NEXT: popl %ebp
; CHECK32-NEXT: retl
@@ -279,9 +263,7 @@ define x86_fp80 @s32_to_x(i32 %a) nounwind {
; CHECK32-LABEL: s32_to_x:
; CHECK32: # %bb.0:
; CHECK32-NEXT: pushl %eax
-; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax
-; CHECK32-NEXT: movl %eax, (%esp)
-; CHECK32-NEXT: fildl (%esp)
+; CHECK32-NEXT: fildl {{[0-9]+}}(%esp)
; CHECK32-NEXT: popl %eax
; CHECK32-NEXT: retl
;
@@ -314,10 +296,8 @@ define float @u64_to_f(i64 %a) nounwind {
; AVX512DQ_32-LABEL: u64_to_f:
; AVX512DQ_32: # %bb.0:
; AVX512DQ_32-NEXT: pushl %eax
-; AVX512DQ_32-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; AVX512DQ_32-NEXT: vcvtuqq2ps %zmm0, %ymm0
-; AVX512DQ_32-NEXT: vmovss %xmm0, (%esp)
-; AVX512DQ_32-NEXT: flds (%esp)
+; AVX512DQ_32-NEXT: flds {{[0-9]+}}(%esp)
; AVX512DQ_32-NEXT: popl %eax
; AVX512DQ_32-NEXT: vzeroupper
; AVX512DQ_32-NEXT: retl
@@ -335,9 +315,7 @@ define float @u64_to_f(i64 %a) nounwind {
; AVX512F_32-NEXT: fildll {{[0-9]+}}(%esp)
; AVX512F_32-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%eax,4)
; AVX512F_32-NEXT: fstps {{[0-9]+}}(%esp)
-; AVX512F_32-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX512F_32-NEXT: vmovss %xmm0, (%esp)
-; AVX512F_32-NEXT: flds (%esp)
+; AVX512F_32-NEXT: flds {{[0-9]+}}(%esp)
; AVX512F_32-NEXT: movl %ebp, %esp
; AVX512F_32-NEXT: popl %ebp
; AVX512F_32-NEXT: retl
@@ -355,9 +333,7 @@ define float @u64_to_f(i64 %a) nounwind {
; SSE2_32-NEXT: fildll {{[0-9]+}}(%esp)
; SSE2_32-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%eax,4)
; SSE2_32-NEXT: fstps {{[0-9]+}}(%esp)
-; SSE2_32-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; SSE2_32-NEXT: movss %xmm0, (%esp)
-; SSE2_32-NEXT: flds (%esp)
+; SSE2_32-NEXT: flds {{[0-9]+}}(%esp)
; SSE2_32-NEXT: movl %ebp, %esp
; SSE2_32-NEXT: popl %ebp
; SSE2_32-NEXT: retl
@@ -384,19 +360,15 @@ define float @u64_to_f(i64 %a) nounwind {
; SSE1_32-NEXT: movl %esp, %ebp
; SSE1_32-NEXT: andl $-8, %esp
; SSE1_32-NEXT: subl $24, %esp
-; SSE1_32-NEXT: movl 8(%ebp), %eax
; SSE1_32-NEXT: movl 12(%ebp), %ecx
; SSE1_32-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; SSE1_32-NEXT: movl %eax, {{[0-9]+}}(%esp)
-; SSE1_32-NEXT: fldl {{[0-9]+}}(%esp)
+; SSE1_32-NEXT: fldl 8(%ebp)
; SSE1_32-NEXT: fstpl {{[0-9]+}}(%esp)
; SSE1_32-NEXT: shrl $31, %ecx
; SSE1_32-NEXT: fildll {{[0-9]+}}(%esp)
; SSE1_32-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; SSE1_32-NEXT: fstps {{[0-9]+}}(%esp)
-; SSE1_32-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; SSE1_32-NEXT: movss %xmm0, (%esp)
-; SSE1_32-NEXT: flds (%esp)
+; SSE1_32-NEXT: flds {{[0-9]+}}(%esp)
; SSE1_32-NEXT: movl %ebp, %esp
; SSE1_32-NEXT: popl %ebp
; SSE1_32-NEXT: retl
@@ -407,12 +379,10 @@ define float @u64_to_f(i64 %a) nounwind {
; X87-NEXT: movl %esp, %ebp
; X87-NEXT: andl $-8, %esp
; X87-NEXT: subl $16, %esp
-; X87-NEXT: movl 8(%ebp), %eax
; X87-NEXT: movl 12(%ebp), %ecx
; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
; X87-NEXT: shrl $31, %ecx
-; X87-NEXT: fildll {{[0-9]+}}(%esp)
+; X87-NEXT: fildll 8(%ebp)
; X87-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; X87-NEXT: fstps {{[0-9]+}}(%esp)
; X87-NEXT: flds {{[0-9]+}}(%esp)
@@ -443,10 +413,8 @@ define float @s64_to_f(i64 %a) nounwind {
; AVX512DQ_32-LABEL: s64_to_f:
; AVX512DQ_32: # %bb.0:
; AVX512DQ_32-NEXT: pushl %eax
-; AVX512DQ_32-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; AVX512DQ_32-NEXT: vcvtqq2ps %zmm0, %ymm0
-; AVX512DQ_32-NEXT: vmovss %xmm0, (%esp)
-; AVX512DQ_32-NEXT: flds (%esp)
+; AVX512DQ_32-NEXT: flds {{[0-9]+}}(%esp)
; AVX512DQ_32-NEXT: popl %eax
; AVX512DQ_32-NEXT: vzeroupper
; AVX512DQ_32-NEXT: retl
@@ -695,12 +663,10 @@ define double @u64_to_d(i64 %a) nounwind {
; SSE1_32-NEXT: movl %esp, %ebp
; SSE1_32-NEXT: andl $-8, %esp
; SSE1_32-NEXT: subl $16, %esp
-; SSE1_32-NEXT: movl 8(%ebp), %eax
; SSE1_32-NEXT: movl 12(%ebp), %ecx
; SSE1_32-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; SSE1_32-NEXT: movl %eax, (%esp)
; SSE1_32-NEXT: shrl $31, %ecx
-; SSE1_32-NEXT: fildll (%esp)
+; SSE1_32-NEXT: fildll 8(%ebp)
; SSE1_32-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; SSE1_32-NEXT: fstpl {{[0-9]+}}(%esp)
; SSE1_32-NEXT: fldl {{[0-9]+}}(%esp)
@@ -714,12 +680,10 @@ define double @u64_to_d(i64 %a) nounwind {
; X87-NEXT: movl %esp, %ebp
; X87-NEXT: andl $-8, %esp
; X87-NEXT: subl $16, %esp
-; X87-NEXT: movl 8(%ebp), %eax
; X87-NEXT: movl 12(%ebp), %ecx
; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; X87-NEXT: movl %eax, (%esp)
; X87-NEXT: shrl $31, %ecx
-; X87-NEXT: fildll (%esp)
+; X87-NEXT: fildll 8(%ebp)
; X87-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; X87-NEXT: fstpl {{[0-9]+}}(%esp)
; X87-NEXT: fldl {{[0-9]+}}(%esp)
@@ -816,12 +780,10 @@ define double @u64_to_d_optsize(i64 %a) nounwind optsize {
; SSE1_32-NEXT: movl %esp, %ebp
; SSE1_32-NEXT: andl $-8, %esp
; SSE1_32-NEXT: subl $16, %esp
-; SSE1_32-NEXT: movl 8(%ebp), %eax
; SSE1_32-NEXT: movl 12(%ebp), %ecx
; SSE1_32-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; SSE1_32-NEXT: movl %eax, (%esp)
; SSE1_32-NEXT: shrl $31, %ecx
-; SSE1_32-NEXT: fildll (%esp)
+; SSE1_32-NEXT: fildll 8(%ebp)
; SSE1_32-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; SSE1_32-NEXT: fstpl {{[0-9]+}}(%esp)
; SSE1_32-NEXT: fldl {{[0-9]+}}(%esp)
@@ -835,12 +797,10 @@ define double @u64_to_d_optsize(i64 %a) nounwind optsize {
; X87-NEXT: movl %esp, %ebp
; X87-NEXT: andl $-8, %esp
; X87-NEXT: subl $16, %esp
-; X87-NEXT: movl 8(%ebp), %eax
; X87-NEXT: movl 12(%ebp), %ecx
; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; X87-NEXT: movl %eax, (%esp)
; X87-NEXT: shrl $31, %ecx
-; X87-NEXT: fildll (%esp)
+; X87-NEXT: fildll 8(%ebp)
; X87-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; X87-NEXT: fstpl {{[0-9]+}}(%esp)
; X87-NEXT: fldl {{[0-9]+}}(%esp)
@@ -1070,12 +1030,10 @@ define x86_fp80 @u64_to_x(i64 %a) nounwind {
; CHECK32-NEXT: movl %esp, %ebp
; CHECK32-NEXT: andl $-8, %esp
; CHECK32-NEXT: subl $8, %esp
-; CHECK32-NEXT: movl 8(%ebp), %eax
; CHECK32-NEXT: movl 12(%ebp), %ecx
; CHECK32-NEXT: movl %ecx, {{[0-9]+}}(%esp)
-; CHECK32-NEXT: movl %eax, (%esp)
; CHECK32-NEXT: shrl $31, %ecx
-; CHECK32-NEXT: fildll (%esp)
+; CHECK32-NEXT: fildll 8(%ebp)
; CHECK32-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
; CHECK32-NEXT: movl %ebp, %esp
; CHECK32-NEXT: popl %ebp
diff --git a/llvm/test/CodeGen/X86/x87-inout-bounce.ll b/llvm/test/CodeGen/X86/x87-inout-bounce.ll
index 161ca2c1742b1..d07d40dd7cc8f 100644
--- a/llvm/test/CodeGen/X86/x87-inout-bounce.ll
+++ b/llvm/test/CodeGen/X86/x87-inout-bounce.ll
@@ -28,11 +28,9 @@ define float @example_float() {
; 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: movss {{[-0-9]+}}(%e{{[sb]}}p), %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
@@ -80,8 +78,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
@@ -92,3 +88,28 @@ entry:
%conv1 = fpext float %conv to x86_fp80
ret x86_fp80 %conv1
}
+
+declare float @returns_x87_float()
+
+define float @testA() {
+; CHECK-LABEL: testA:
+; CHECK: # %bb.0:
+; CHECK-NEXT: subl $28, %esp
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: calll returns_x87_float at PLT
+; CHECK-NEXT: fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT: calll returns_x87_float at PLT
+; CHECK-NEXT: fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT: movss {{[-0-9]+}}(%e{{[sb]}}p), %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
+ %1 = call float @returns_x87_float()
+ %2 = call float @returns_x87_float()
+ %3 = fadd float %1, %2
+ ret float %3
+}
More information about the llvm-commits
mailing list