[libc-commits] [libc] [llvm] [LoongArch] Support ISD::SET_ROUNDING (llvm.set.rounding) (PR #205051)
via libc-commits
libc-commits at lists.llvm.org
Mon Jun 22 23:48:55 PDT 2026
================
@@ -4015,6 +4019,53 @@ SDValue LoongArchTargetLowering::lowerATOMIC_FENCE(SDValue Op,
return Op;
}
+SDValue LoongArchTargetLowering::lowerSET_ROUNDING(SDValue Op,
+ SelectionDAG &DAG) const {
+ MVT GRLenVT = Subtarget.getGRLenVT();
+ SDLoc DL(Op);
+ SDValue Chain = Op.getOperand(0);
+ SDValue RMValue = Op.getOperand(1);
+
+ // LLVM rounding mode encoding: 0=RTZ, 1=RNE, 2=RUP, 3=RDN.
+ if (auto *CVal = dyn_cast<ConstantSDNode>(RMValue)) {
+ uint64_t RM = CVal->getZExtValue();
+ if (RM > 3) {
+ DAG.getContext()->emitError("invalid rounding mode");
+ return Chain;
+ }
+ }
+
+ // Zero-extend i32 rounding mode to GRLenVT.
+ RMValue = DAG.getNode(ISD::ZERO_EXTEND, DL, GRLenVT, RMValue);
+
+ // LLVM rounding mode encoding differs from LoongArch FCSR encoding:
+ // LLVM: 0=RTZ, 1=RNE, 2=RUP, 3=RDN
+ // FCSR: 0=RNE, 1=RZ, 2=RP, 3=RN
+ // Translate by swapping 0↔1 (XOR with 1 when RM < 2), keep 2 and 3.
+ // 0 (RTZ) → 1 (RZ), 1 (RNE) → 0 (RNE), 2 (RUP) → 2 (RP), 3 (RDN) → 3 (RN)
+ // Transformation: RM ^ (~(RM >> 1) & 1)
+ SDValue ShiftRight1 = DAG.getNode(ISD::SRL, DL, GRLenVT, RMValue,
+ DAG.getConstant(1, DL, GRLenVT));
+ SDValue SwapMask = DAG.getNode(ISD::AND, DL, GRLenVT,
+ DAG.getNode(ISD::XOR, DL, GRLenVT, ShiftRight1,
+ DAG.getConstant(1, DL, GRLenVT)),
+ DAG.getConstant(1, DL, GRLenVT));
+ RMValue = DAG.getNode(ISD::XOR, DL, GRLenVT, RMValue, SwapMask);
+
+ // Mask to 2 bits to guard against invalid values.
+ RMValue = DAG.getNode(ISD::AND, DL, GRLenVT, RMValue,
+ DAG.getConstant(0x3, DL, GRLenVT));
+
+ // Build MachineInstr node for WRFCSR (pseudo for MOVGR2FCSR).
+ // WRFCSR takes (uimm2:$fcsr, GPR:$src).
+ // FCSR3 is an alias of the RM field; writing it avoids clobbering
+ // unrelated fields in FCSR0.
+ SDValue FCSRNo = DAG.getTargetConstant(3, DL, GRLenVT);
+ MachineSDNode *RN = DAG.getMachineNode(LoongArch::WRFCSR, DL, MVT::Other,
+ FCSRNo, RMValue, Chain);
----------------
wangleiat wrote:
`RMValue` should be left-shifted by 8 bits before being written.
https://github.com/llvm/llvm-project/pull/205051
More information about the libc-commits
mailing list