[clang-tools-extra] [llvm] [PowerPC] Implement llvm.set.rounding intrinsic (PR #67302)

Qiu Chaofan via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 27 01:41:44 PST 2023


================
@@ -8900,6 +8900,83 @@ SDValue PPCTargetLowering::LowerINT_TO_FP(SDValue Op,
   return FP;
 }
 
+SDValue PPCTargetLowering::LowerSET_ROUNDING(SDValue Op,
+                                             SelectionDAG &DAG) const {
+  SDLoc Dl(Op);
+  MachineFunction &MF = DAG.getMachineFunction();
+  EVT PtrVT = getPointerTy(MF.getDataLayout());
+  SDValue Chain = Op.getOperand(0);
+
+  // If requested mode is constant, just use simpler mtfsb.
+  if (auto *CVal = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
+    uint64_t Mode = CVal->getZExtValue();
+    if (Mode >= 4)
+      llvm_unreachable("Unsupported rounding mode!");
+    unsigned InternalRnd = Mode ^ (~(Mode >> 1) & 1);
+    SDNode *SetHi = DAG.getMachineNode(
+        (InternalRnd & 2) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
+        {DAG.getConstant(30, Dl, MVT::i32, true), Chain});
+    SDNode *SetLo = DAG.getMachineNode(
+        (InternalRnd & 1) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
+        {DAG.getConstant(31, Dl, MVT::i32, true), SDValue(SetHi, 0)});
+    return SDValue(SetLo, 0);
+  }
+
+  // Use x ^ (~(x >> 1) & 1) to transform LLVM rounding mode to Power format.
+  SDValue One = DAG.getConstant(1, Dl, MVT::i32);
+  SDValue SrcFlag = DAG.getNode(ISD::AND, Dl, MVT::i32, Op.getOperand(1),
+                                DAG.getConstant(3, Dl, MVT::i32));
+  SDValue DstFlag = DAG.getNode(
+      ISD::XOR, Dl, MVT::i32, SrcFlag,
+      DAG.getNode(ISD::AND, Dl, MVT::i32,
+                  DAG.getNOT(Dl,
+                             DAG.getNode(ISD::SRL, Dl, MVT::i32, SrcFlag, One),
+                             MVT::i32),
+                  One));
+  SDValue MFFS = DAG.getNode(PPCISD::MFFS, Dl, {MVT::f64, MVT::Other}, Chain);
+  Chain = MFFS.getValue(1);
+  SDValue NewFPSCR;
+  if (isTypeLegal(MVT::i64)) {
+    // Set the last two bits (rounding mode) of bitcasted FPSCR.
+    NewFPSCR = DAG.getNode(
+        ISD::OR, Dl, MVT::i64,
+        DAG.getNode(ISD::AND, Dl, MVT::i64,
+                    DAG.getNode(ISD::BITCAST, Dl, MVT::i64, MFFS),
+                    DAG.getNOT(Dl, DAG.getConstant(3, Dl, MVT::i64), MVT::i64)),
+        DAG.getNode(ISD::ZERO_EXTEND, Dl, MVT::i64, DstFlag));
----------------
ecnelises wrote:

Yes, `DestFlag = SrcFlag ^ (~(SrcFlag >> 1) & 1)`, and `SrcFlag < 4`.

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


More information about the cfe-commits mailing list