[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