[clang] [compiler-rt] [llvm] [SystemZ] Add support for half (fp16) (PR #109164)

Ulrich Weigand via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 19 05:49:24 PST 2024


================
@@ -6108,6 +6160,133 @@ static SDValue lowerAddrSpaceCast(SDValue Op, SelectionDAG &DAG) {
   return Op;
 }
 
+SDValue SystemZTargetLowering::LowerFP_EXTEND(SDValue Op,
+                                              SelectionDAG &DAG) const {
+  bool IsStrict = Op->isStrictFPOpcode();
+  SDValue In = Op.getOperand(IsStrict ? 1 : 0);
+  MVT VT = Op.getSimpleValueType();
+  MVT SVT = In.getSimpleValueType();
+  if (SVT != MVT::f16)
+    return Op;
+
+  SDLoc DL(Op);
+  SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue();
+
+  // Need a libcall.  XXX factor out (below)
+  TargetLowering::CallLoweringInfo CLI(DAG);
+  Chain = IsStrict ? Op.getOperand(0) : DAG.getEntryNode();
+  TargetLowering::ArgListTy Args;
+  TargetLowering::ArgListEntry Entry;
+  Entry.Node = In;
+  Entry.Ty = EVT(SVT).getTypeForEVT(*DAG.getContext());
+  Args.push_back(Entry);
+  SDValue Callee = DAG.getExternalSymbol(
+    getLibcallName(RTLIB::FPEXT_F16_F32), getPointerTy(DAG.getDataLayout()));
+  CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
+    CallingConv::C, EVT(MVT::f32).getTypeForEVT(*DAG.getContext()), Callee,
+    std::move(Args));
+  SDValue Res;
+  std::tie(Res,Chain) = LowerCallTo(CLI);
+  if (IsStrict)
+    Res = DAG.getMergeValues({Res, Chain}, DL);
+
+  return DAG.getNode(ISD::FP_EXTEND, DL, VT, Res);
+}
+
+SDValue SystemZTargetLowering::LowerFP_ROUND(SDValue Op,
+                                             SelectionDAG &DAG) const {
+  bool IsStrict = Op->isStrictFPOpcode();
+  SDValue In = Op.getOperand(IsStrict ? 1 : 0);
+  MVT VT = Op.getSimpleValueType();
+  MVT SVT = In.getSimpleValueType();
+  if (VT != MVT::f16)
+    return SDValue(); // XXX?
+
+  SDLoc DL(Op);
+  SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue();
+
+  if (SVT != MVT::f32) {
+    SDValue Rnd = DAG.getIntPtrConstant(0, DL, /*isTarget=*/true);
+    In = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, In, Rnd);
+  }
----------------
uweigand wrote:

The double rounding may yield an incorrect result.  I think GCC just uses different libcalls for all source types.  Another alternative might be to use the "round to prepare for shorter precision" mode for the first operation.  

https://github.com/llvm/llvm-project/pull/109164


More information about the cfe-commits mailing list