[llvm] 82d36da - [SelectionDAG] Fix load/store legalization for softened x86_fp80 (#209991)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 03:46:49 PDT 2026
Author: Muhammed Shiyas N
Date: 2026-08-27T10:46:43Z
New Revision: 82d36dad7e2448f83683a48617286f8a822c0282
URL: https://github.com/llvm/llvm-project/commit/82d36dad7e2448f83683a48617286f8a822c0282
DIFF: https://github.com/llvm/llvm-project/commit/82d36dad7e2448f83683a48617286f8a822c0282.diff
LOG: [SelectionDAG] Fix load/store legalization for softened x86_fp80 (#209991)
Fixes #73201
This fixes a crash during x86_fp80 load/store legalization with x87
disabled. When x86_fp80 is softened to wider integer type, the type
legalizer generates regular loads and stores using widened type, which
can trigger a "Size mismatch" assertion.
This is fixed by using extending loads and truncating stores when the
softened type is wider than the original memory type.
Added:
llvm/test/CodeGen/X86/x86-fp80-load-store-no-x87.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 17d3c34e75194..f099a43089f5e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -913,9 +913,12 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) {
~(MachineMemOperand::MOInvariant | MachineMemOperand::MODereferenceable);
SDValue NewL;
if (L->getExtensionType() == ISD::NON_EXTLOAD) {
- NewL = DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), NVT, dl,
+ // If softening widens the integer representation (e.g. x86_fp80 -> i96),
+ // load the original memory width and extend to the softened type.
+ EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
+ NewL = DAG.getLoad(L->getAddressingMode(), ISD::EXTLOAD, NVT, dl,
L->getChain(), L->getBasePtr(), L->getOffset(),
- L->getPointerInfo(), NVT, L->getBaseAlign(), MMOFlags,
+ L->getPointerInfo(), MemVT, L->getBaseAlign(), MMOFlags,
L->getAAInfo());
// Legalized the chain result - switch anything that used the old chain to
// use the new one.
@@ -1348,8 +1351,12 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) {
else
Val = GetSoftenedFloat(Val);
- return DAG.getStore(ST->getChain(), dl, Val, ST->getBasePtr(),
- ST->getMemOperand());
+ // If softening widens the integer representation (e.g. x86_fp80 -> i96),
+ // truncate the value before storing to preserve the original memory width.
+ EVT MemVT =
+ EVT::getIntegerVT(*DAG.getContext(), ST->getMemoryVT().getSizeInBits());
+ return DAG.getTruncStore(ST->getChain(), dl, Val, ST->getBasePtr(), MemVT,
+ ST->getMemOperand());
}
SDValue DAGTypeLegalizer::SoftenFloatOp_ATOMIC_STORE(SDNode *N, unsigned OpNo) {
diff --git a/llvm/test/CodeGen/X86/x86-fp80-load-store-no-x87.ll b/llvm/test/CodeGen/X86/x86-fp80-load-store-no-x87.ll
new file mode 100644
index 0000000000000..e6dc0369928b2
--- /dev/null
+++ b/llvm/test/CodeGen/X86/x86-fp80-load-store-no-x87.ll
@@ -0,0 +1,64 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=X64
+; RUN: llc < %s -mtriple=i686-unknown-linux-gnu | FileCheck %s --check-prefix=X86
+
+; Verify that x86_fp80 load/store legalization handles widened softened types
+; correctly when x87 is disabled.
+define void @test_load_store_f80(ptr %p, ptr %q) #0 {
+; X64-LABEL: test_load_store_f80:
+; X64: # %bb.0:
+; X64-NEXT: movl 8(%rdi), %eax
+; X64-NEXT: movq (%rdi), %rcx
+; X64-NEXT: movq %rcx, (%rsi)
+; X64-NEXT: movw %ax, 8(%rsi)
+; X64-NEXT: retq
+;
+; X86-LABEL: test_load_store_f80:
+; X86: # %bb.0:
+; X86-NEXT: pushl %esi
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: movl 8(%ecx), %edx
+; X86-NEXT: movl (%ecx), %esi
+; X86-NEXT: movl 4(%ecx), %ecx
+; X86-NEXT: movl %esi, (%eax)
+; X86-NEXT: movl %ecx, 4(%eax)
+; X86-NEXT: movw %dx, 8(%eax)
+; X86-NEXT: popl %esi
+; X86-NEXT: retl
+ %v = load x86_fp80, ptr %p, align 16
+ store x86_fp80 %v, ptr %q, align 16
+ ret void
+}
+
+; Verify that returning a struct containing x86_fp80 values works with
+; x87 disabled.
+define { x86_fp80, x86_fp80 } @test_struct_ret_f80() #0 {
+; X64-LABEL: test_struct_ret_f80:
+; X64: # %bb.0:
+; X64-NEXT: movq %rdi, %rax
+; X64-NEXT: movl 8, %ecx
+; X64-NEXT: movq 0, %rdx
+; X64-NEXT: movq %rdx, (%rdi)
+; X64-NEXT: movw %cx, 8(%rdi)
+; X64-NEXT: retq
+;
+; X86-LABEL: test_struct_ret_f80:
+; X86: # %bb.0:
+; X86-NEXT: pushl %esi
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: movl 8, %ecx
+; X86-NEXT: movl 0, %edx
+; X86-NEXT: movl 4, %esi
+; X86-NEXT: movl %esi, 4(%eax)
+; X86-NEXT: movl %edx, (%eax)
+; X86-NEXT: movw %cx, 8(%eax)
+; X86-NEXT: popl %esi
+; X86-NEXT: retl $4
+ %r.real = load x86_fp80, ptr null, align 16
+ %.fca.0.insert = insertvalue { x86_fp80, x86_fp80 } zeroinitializer, x86_fp80 %r.real, 0
+ %.fca.1.insert = insertvalue { x86_fp80, x86_fp80 } %.fca.0.insert, x86_fp80 poison, 1
+ ret { x86_fp80, x86_fp80 } %.fca.1.insert
+}
+
+attributes #0 = { nounwind "target-features"="-x87" }
More information about the llvm-commits
mailing list