[llvm] [X86] Report an error for FP environment accesses that are not 256 bits (PR #228841)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 4 00:01:09 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Doha Nam (waroad)
<details>
<summary>Changes</summary>
LowerGET_FPENV_MEM and LowerSET_FPENV_MEM assume the 256-bit X86 FP
environment layout (x87 environment plus MXCSR) and only checked the width
with an assertion. The IR verifier accepts llvm.get.fpenv/llvm.set.fpenv on
any integer type. With a narrower type, release builds therefore wrote 32
bytes into a smaller stack slot (for i64, fnstenv/stmxcsr overwrote the
return address).
Emit an error for other widths instead, following the approach used for
missing floating-point state libcalls.
Fixes #<!-- -->228830.
Co-Authored-By: Claude Opus 5.5 <noreply@<!-- -->anthropic.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/228841.diff
2 Files Affected:
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+18-3)
- (added) llvm/test/CodeGen/X86/fpenv-invalid-type.ll (+25)
``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index ccd53f8aaaffe..1968ec3a37f29 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -29466,7 +29466,20 @@ SDValue X86TargetLowering::LowerSET_ROUNDING(SDValue Op,
const unsigned X87StateSize = 28;
const unsigned FPStateSize = 32;
-[[maybe_unused]] const unsigned FPStateSizeInBits = FPStateSize * 8;
+const unsigned FPStateSizeInBits = FPStateSize * 8;
+
+// The X86 FP environment is 256 bits (x87 environment plus MXCSR). Report an
+// error for other widths rather than reading or writing past the memory
+// operand.
+static bool checkFPStateWidth(SDValue Op, EVT MemVT, SelectionDAG &DAG) {
+ if (MemVT.getSizeInBits() == FPStateSizeInBits)
+ return true;
+ DAG.getContext()->emitError(Twine("unsupported type for ") +
+ Op->getOperationName(&DAG) +
+ ": the X86 floating-point environment is " +
+ Twine(FPStateSizeInBits) + " bits");
+ return false;
+}
SDValue X86TargetLowering::LowerGET_FPENV_MEM(SDValue Op,
SelectionDAG &DAG) const {
@@ -29476,7 +29489,8 @@ SDValue X86TargetLowering::LowerGET_FPENV_MEM(SDValue Op,
SDValue Ptr = Op->getOperand(1);
auto *Node = cast<FPStateAccessSDNode>(Op);
EVT MemVT = Node->getMemoryVT();
- assert(MemVT.getSizeInBits() == FPStateSizeInBits);
+ if (!checkFPStateWidth(Op, MemVT, DAG))
+ return Chain;
MachineMemOperand *MMO = cast<FPStateAccessSDNode>(Op)->getMemOperand();
// Get x87 state, if it presents.
@@ -29542,7 +29556,8 @@ SDValue X86TargetLowering::LowerSET_FPENV_MEM(SDValue Op,
SDValue Ptr = Op->getOperand(1);
auto *Node = cast<FPStateAccessSDNode>(Op);
EVT MemVT = Node->getMemoryVT();
- assert(MemVT.getSizeInBits() == FPStateSizeInBits);
+ if (!checkFPStateWidth(Op, MemVT, DAG))
+ return Chain;
MachineMemOperand *MMO = cast<FPStateAccessSDNode>(Op)->getMemOperand();
return createSetFPEnvNodes(Ptr, Chain, DL, MemVT, MMO, DAG, Subtarget);
}
diff --git a/llvm/test/CodeGen/X86/fpenv-invalid-type.ll b/llvm/test/CodeGen/X86/fpenv-invalid-type.ll
new file mode 100644
index 0000000000000..2734e6f17dd1e
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fpenv-invalid-type.ll
@@ -0,0 +1,25 @@
+; RUN: not llc -mtriple=x86_64-unknown-linux-gnu -filetype=null %s 2>&1 | FileCheck %s
+; RUN: not llc -mtriple=i686-unknown-linux-gnu -filetype=null %s 2>&1 | FileCheck %s
+
+; The X86 floating-point environment is 256 bits. Other widths are rejected
+; with an error instead of reading or writing past the memory operand.
+; https://github.com/llvm/llvm-project/issues/228830
+
+; CHECK: error: unsupported type for get_fpenv_mem: the X86 floating-point environment is 256 bits
+define i64 @get_fpenv_i64() nounwind {
+ %env = call i64 @llvm.get.fpenv.i64()
+ ret i64 %env
+}
+
+; CHECK: error: unsupported type for set_fpenv_mem: the X86 floating-point environment is 256 bits
+define void @set_fpenv_i128(i128 %env) nounwind {
+ call void @llvm.set.fpenv.i128(i128 %env)
+ ret void
+}
+
+; CHECK: error: unsupported type for get_fpenv_mem: the X86 floating-point environment is 256 bits
+define void @get_fpenv_i512(ptr %p) nounwind {
+ %env = call i512 @llvm.get.fpenv.i512()
+ store i512 %env, ptr %p
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/228841
More information about the llvm-commits
mailing list