[libc-commits] [libc] [llvm] [LoongArch] Support ISD::SET_ROUNDING (llvm.set.rounding) (PR #205051)

Paper Moon via libc-commits libc-commits at lists.llvm.org
Mon Jun 22 01:05:21 PDT 2026


https://github.com/tangyuan0821 created https://github.com/llvm/llvm-project/pull/205051

`@llvm.set.rounding()` crashed with "Cannot select: set_rounding" on
loongarch64. Lower ISD::SET_ROUNDING via WRFCSR (movgr2fcsr) since
the rounding mode encoding matches LoongArch FCSR hardware directly.

>From 152f23515b7d900fe0a698a2b479ab4bfbdc982a Mon Sep 17 00:00:00 2001
From: tangyuan0821 <tangyuan0821 at email.cn>
Date: Mon, 22 Jun 2026 16:00:05 +0800
Subject: [PATCH] [LoongArch] Support ISD::SET_ROUNDING (llvm.set.rounding)

Fixes "Cannot select: set_rounding" for loongarch64. The rounding mode
encoding matches LoongArch FCSR hardware, so no translation is needed.
---
 libc/shared/fp_bits.h                         |  2 +-
 .../LoongArch/LoongArchISelLowering.cpp       | 28 +++++++++++++++++++
 .../Target/LoongArch/LoongArchISelLowering.h  |  1 +
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/libc/shared/fp_bits.h b/libc/shared/fp_bits.h
index e6bb1e17b80c9..1a7544be7519d 100644
--- a/libc/shared/fp_bits.h
+++ b/libc/shared/fp_bits.h
@@ -1,4 +1,4 @@
-//===-- Floating point number utils -----------------------------*- C++ -*-===//
+comm//===-- Floating point number utils -----------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 8748f4723339b..9438608fac82a 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -125,6 +125,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::VASTART, MVT::Other, Custom);
   setOperationAction({ISD::VAARG, ISD::VACOPY, ISD::VAEND}, MVT::Other, Expand);
 
+  setOperationAction(ISD::SET_ROUNDING, MVT::Other, Custom);
   setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal);
   setOperationAction(ISD::TRAP, MVT::Other, Legal);
 
@@ -613,6 +614,8 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
     return lowerFRAMEADDR(Op, DAG);
   case ISD::RETURNADDR:
     return lowerRETURNADDR(Op, DAG);
+  case ISD::SET_ROUNDING:
+    return lowerSET_ROUNDING(Op, DAG);
   case ISD::WRITE_REGISTER:
     return lowerWRITE_REGISTER(Op, DAG);
   case ISD::INSERT_VECTOR_ELT:
@@ -4015,6 +4018,31 @@ 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);
+
+  // Zero-extend i32 rounding mode to GRLenVT.
+  RMValue = DAG.getNode(ISD::ZERO_EXTEND, DL, GRLenVT, RMValue);
+
+  // The rounding mode in FCSR0 occupies bits 1:0.
+  // LLVM rounding mode encoding (0=RNE,1=RTZ,2=RDN,3=RUP) matches
+  // the LoongArch FCSR hardware encoding, so no translation needed.
+  // We 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).
+  SDValue FCSRNo = DAG.getTargetConstant(0, DL, GRLenVT); // FCSR0
+  MachineSDNode *RN = DAG.getMachineNode(LoongArch::WRFCSR, DL, MVT::Other,
+                                          FCSRNo, RMValue, Chain);
+  return SDValue(RN, 0);
+}
+
 SDValue LoongArchTargetLowering::lowerWRITE_REGISTER(SDValue Op,
                                                      SelectionDAG &DAG) const {
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 2f2eda1e2c7d9..8d9ec6020478b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -236,6 +236,7 @@ class LoongArchTargetLowering : public TargetLowering {
   SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;



More information about the libc-commits mailing list