[llvm] [SelectionDAG] Fix soft-promotion of f16 BUILD_VECTOR for MSA targets (PR #210515)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 18 08:28:09 PDT 2026
https://github.com/fo40225 created https://github.com/llvm/llvm-project/pull/210515
When compiling for MIPS with +msa and f16 vectors (v8f16, v4f16, v2f16), LLVM would crash with "Do not know how to soft promote this operator's operand!" because BUILD_VECTOR was missing from the SoftPromoteHalfOperand switch statement in LegalizeFloatTypes.cpp.
On MIPS, f16 is not natively supported by default, so LLVM soft-promotes it: stores as i16, computes as f32.
Building f16 vectors requires handling BUILD_VECTOR with soft-promoted i16 operands.
This patch adds the missing BUILD_VECTOR case and implements SoftPromoteHalfOp_BUILD_VECTOR, which:
(1) retrieves soft-promoted i16 operands via GetSoftPromotedHalf,
(2) builds a v{N}i16 integer vector,
(3) bitcasts to the original v{N}f16 type.
This matches the soft-promotion pattern used in the BITCAST handler.
Fixes compilation of Rust libcore/compiler_builtins with global +msa.
**Test Plan**:
- Added llvm/test/CodeGen/Mips/msa/f16vec.ll with v8/v4/v2 half tests
- Verified all existing llvm/test/CodeGen/Mips tests pass (1024 passed, 16 pre-existing failures)
- Confirmed MSA instructions (insert.w/d, fill.h, fexupr.w) are correctly generated
>From 8433bec1cd3fe28570a6ba5490224ff9d909aeb6 Mon Sep 17 00:00:00 2001
From: fo4025 <fo40225 at hotmail.com>
Date: Sat, 18 Jul 2026 21:48:31 +0800
Subject: [PATCH] [Mips] Fix soft-promotion of f16 BUILD_VECTOR for MSA targets
When compiling for MIPS with +msa and f16 vectors (v8f16, v4f16, v2f16),
LLVM would crash with "Do not know how to soft promote this operator's
operand!" because BUILD_VECTOR was missing from the SoftPromoteHalfOperand
switch statement in LegalizeFloatTypes.cpp.
On MIPS, f16 is not natively supported by default, so LLVM soft-promotes
it: stores as i16, computes as f32. Building f16 vectors requires handling
BUILD_VECTOR with soft-promoted i16 operands. This patch adds the missing
BUILD_VECTOR case and implements SoftPromoteHalfOp_BUILD_VECTOR, which:
(1) retrieves soft-promoted i16 operands via GetSoftPromotedHalf,
(2) builds a v{N}i16 integer vector,
(3) bitcasts to the original v{N}f16 type.
This matches the soft-promotion pattern used in the BITCAST handler,
where f16 storage is represented as i16 and only operations promote to f32.
Fixes compilation of Rust libcore/compiler_builtins with global +msa.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
---
.../SelectionDAG/LegalizeFloatTypes.cpp | 18 ++++++++
llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 1 +
llvm/test/CodeGen/Mips/msa/f16vec.ll | 41 +++++++++++++++++++
3 files changed, 60 insertions(+)
create mode 100644 llvm/test/CodeGen/Mips/msa/f16vec.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 25cc420c42482..79c1335089096 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -3171,6 +3171,9 @@ bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
"operand!");
case ISD::BITCAST: Res = SoftPromoteHalfOp_BITCAST(N); break;
+ case ISD::BUILD_VECTOR:
+ Res = SoftPromoteHalfOp_BUILD_VECTOR(N);
+ break;
case ISD::FAKE_USE:
Res = SoftPromoteHalfOp_FAKE_USE(N, OpNo);
break;
@@ -3234,6 +3237,21 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BITCAST(SDNode *N) {
return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0), Op0);
}
+SDValue DAGTypeLegalizer::SoftPromoteHalfOp_BUILD_VECTOR(SDNode *N) {
+ SDLoc dl(N);
+ EVT VT = N->getValueType(0);
+ assert(VT.isVector() && VT.getVectorElementType() == MVT::f16);
+
+ SmallVector<SDValue, 8> Ops(N->getNumOperands());
+ for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
+ Ops[i] = GetSoftPromotedHalf(N->getOperand(i));
+
+ EVT IVT = EVT::getVectorVT(*DAG.getContext(), MVT::i16,
+ VT.getVectorElementCount());
+ SDValue Res = DAG.getBuildVector(IVT, dl, Ops);
+ return DAG.getNode(ISD::BITCAST, dl, VT, Res);
+}
+
SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FAKE_USE(SDNode *N, unsigned OpNo) {
assert(OpNo == 1 && "Only Operand 1 must need promotion here");
SDValue Op = GetSoftPromotedHalf(N->getOperand(OpNo));
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index d4d56a9563f71..4a9bfa81e2a33 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -804,6 +804,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
bool SoftPromoteHalfOperand(SDNode *N, unsigned OpNo);
SDValue SoftPromoteHalfOp_BITCAST(SDNode *N);
+ SDValue SoftPromoteHalfOp_BUILD_VECTOR(SDNode *N);
SDValue SoftPromoteHalfOp_FAKE_USE(SDNode *N, unsigned OpNo);
SDValue SoftPromoteHalfOp_FCOPYSIGN(SDNode *N, unsigned OpNo);
SDValue SoftPromoteHalfOp_FP_EXTEND(SDNode *N);
diff --git a/llvm/test/CodeGen/Mips/msa/f16vec.ll b/llvm/test/CodeGen/Mips/msa/f16vec.ll
new file mode 100644
index 0000000000000..97b455dc2c38a
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/msa/f16vec.ll
@@ -0,0 +1,41 @@
+; RUN: llc -mtriple=mipsel-unknown-linux-gnu -mcpu=mips32r5 -mattr=+fp64,+msa < %s | FileCheck %s --check-prefix=MIPS32
+; RUN: llc -mtriple=mips64el-unknown-linux-gnuabi64 -mcpu=mips64r5 -mattr=+fp64,+msa -target-abi n64 < %s | FileCheck %s --check-prefix=MIPS64
+
+; Test that f16 vectors can be passed as arguments and returned without crashing.
+; This is a regression test for a crash in soft-promotion of BUILD_VECTOR operands.
+
+define <8 x half> @f16vec_add(<8 x half> %a, <8 x half> %b) {
+; MIPS32-LABEL: f16vec_add:
+; MIPS32: insert.w
+; MIPS32: insert.w
+;
+; MIPS64-LABEL: f16vec_add:
+; MIPS64: insert.d
+; MIPS64: insert.d
+ %c = fadd <8 x half> %a, %b
+ ret <8 x half> %c
+}
+
+define <4 x half> @f16vec4_add(<4 x half> %a, <4 x half> %b) {
+; MIPS32-LABEL: f16vec4_add:
+; MIPS32: fill.h
+; MIPS32: fexupr.w
+;
+; MIPS64-LABEL: f16vec4_add:
+; MIPS64: fill.h
+; MIPS64: fexupr.w
+ %c = fadd <4 x half> %a, %b
+ ret <4 x half> %c
+}
+
+define <2 x half> @f16vec2_add(<2 x half> %a, <2 x half> %b) {
+; MIPS32-LABEL: f16vec2_add:
+; MIPS32: fill.h
+; MIPS32: fexupr.w
+;
+; MIPS64-LABEL: f16vec2_add:
+; MIPS64: fill.h
+; MIPS64: fexupr.w
+ %c = fadd <2 x half> %a, %b
+ ret <2 x half> %c
+}
More information about the llvm-commits
mailing list