diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 5cc084f3ab138..3d7b121c182fa 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -208,6 +208,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( MVT::v2f64}) setOperationAction(ISD::BUILD_VECTOR, T, Custom); + if (Subtarget->hasFP16()) + setOperationAction(ISD::BUILD_VECTOR, MVT::f16, Custom); + // We have custom shuffle lowering to expose the shuffle mask for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64, MVT::v2f64}) @@ -2055,6 +2058,18 @@ static SDValue LowerConvertLow(SDValue Op, SelectionDAG &DAG) { SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { + MVT VT = Op.getSimpleValueType(); + if (VT == MVT::v8f16) { + // BUILD_VECTOR can't handle FP16 operands since Wasm doesn't have a scaler + // FP16 type, so cast them to I16s. + MVT IVT = VT.changeVectorElementType(MVT::i16); + SmallVector NewOps; + for (unsigned I = 0, E = Op.getNumOperands(); I < E; ++I) + NewOps.push_back(DAG.getBitcast(MVT::i16, Op.getOperand(I))); + SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, SDLoc(), IVT, NewOps); + return DAG.getBitcast(VT, Res); + } + if (auto ConvertLow = LowerConvertLow(Op, DAG)) return ConvertLow; diff --git a/llvm/test/CodeGen/WebAssembly/half-precision.ll b/llvm/test/CodeGen/WebAssembly/half-precision.ll index c0b14d2064d5e..5a0bc56886956 100644 --- a/llvm/test/CodeGen/WebAssembly/half-precision.ll +++ b/llvm/test/CodeGen/WebAssembly/half-precision.ll @@ -28,6 +28,13 @@ define <8 x half> @splat_v8f16(float %x) { ret <8 x half> %v } +; CHECK-LABEL: const_splat_v8f16: +; CHECK: v128.const $push0=, 20800, 0, 0, 0, 0, 0, 0, 20800 +; CHECK-NEXT: return $pop0 +define <8 x half> @const_splat_v8f16() { + ret <8 x half> +} + ; CHECK-LABEL: extract_lane_v8f16: ; CHECK: f16x8.extract_lane $push0=, $0, 1 ; CHECK-NEXT: return $pop0