aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-25 17:35:41 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-04-06 20:13:06 +0000
commitcb14a3fe5122c879eae1fb480ed7ce82a699ddb6 (patch)
treeb983a613c35ece61d561b5a9ef9cd66419f6c7fb /contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp
parent3d68ee6cbdb244de9fab1df8a2525d2fa592571e (diff)
parent99aabd70801bd4bc72c4942747f6d62c675112f5 (diff)
downloadsrc-cb14a3fe5122c879eae1fb480ed7ce82a699ddb6.tar.gz
src-cb14a3fe5122c879eae1fb480ed7ce82a699ddb6.zip
Merge llvm-project main llvmorg-18-init-15692-g007ed0dccd6a
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvm-project main llvmorg-18-init-15692-g007ed0dccd6a. PR: 276104 MFC after: 1 month
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp b/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp
index db63facca870..d00b7853816e 100644
--- a/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1415,6 +1415,9 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::GET_FPENV, MVT::i32, Legal);
setOperationAction(ISD::SET_FPENV, MVT::i32, Legal);
setOperationAction(ISD::RESET_FPENV, MVT::Other, Legal);
+ setOperationAction(ISD::GET_FPMODE, MVT::i32, Legal);
+ setOperationAction(ISD::SET_FPMODE, MVT::i32, Custom);
+ setOperationAction(ISD::RESET_FPMODE, MVT::Other, Custom);
}
// We want to custom lower some of our intrinsics.
@@ -6447,6 +6450,57 @@ SDValue ARMTargetLowering::LowerSET_ROUNDING(SDValue Op,
return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
}
+SDValue ARMTargetLowering::LowerSET_FPMODE(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ SDValue Chain = Op->getOperand(0);
+ SDValue Mode = Op->getOperand(1);
+
+ // Generate nodes to build:
+ // FPSCR = (FPSCR & FPStatusBits) | (Mode & ~FPStatusBits)
+ SDValue Ops[] = {Chain,
+ DAG.getConstant(Intrinsic::arm_get_fpscr, DL, MVT::i32)};
+ SDValue FPSCR =
+ DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i32, MVT::Other}, Ops);
+ Chain = FPSCR.getValue(1);
+ FPSCR = FPSCR.getValue(0);
+
+ SDValue FPSCRMasked =
+ DAG.getNode(ISD::AND, DL, MVT::i32, FPSCR,
+ DAG.getConstant(ARM::FPStatusBits, DL, MVT::i32));
+ SDValue InputMasked =
+ DAG.getNode(ISD::AND, DL, MVT::i32, Mode,
+ DAG.getConstant(~ARM::FPStatusBits, DL, MVT::i32));
+ FPSCR = DAG.getNode(ISD::OR, DL, MVT::i32, FPSCRMasked, InputMasked);
+
+ SDValue Ops2[] = {
+ Chain, DAG.getConstant(Intrinsic::arm_set_fpscr, DL, MVT::i32), FPSCR};
+ return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
+}
+
+SDValue ARMTargetLowering::LowerRESET_FPMODE(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ SDValue Chain = Op->getOperand(0);
+
+ // To get the default FP mode all control bits are cleared:
+ // FPSCR = FPSCR & (FPStatusBits | FPReservedBits)
+ SDValue Ops[] = {Chain,
+ DAG.getConstant(Intrinsic::arm_get_fpscr, DL, MVT::i32)};
+ SDValue FPSCR =
+ DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i32, MVT::Other}, Ops);
+ Chain = FPSCR.getValue(1);
+ FPSCR = FPSCR.getValue(0);
+
+ SDValue FPSCRMasked = DAG.getNode(
+ ISD::AND, DL, MVT::i32, FPSCR,
+ DAG.getConstant(ARM::FPStatusBits | ARM::FPReservedBits, DL, MVT::i32));
+ SDValue Ops2[] = {Chain,
+ DAG.getConstant(Intrinsic::arm_set_fpscr, DL, MVT::i32),
+ FPSCRMasked};
+ return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
+}
+
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG,
const ARMSubtarget *ST) {
SDLoc dl(N);
@@ -10557,6 +10611,10 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::ZERO_EXTEND: return LowerVectorExtend(Op.getNode(), DAG, Subtarget);
case ISD::GET_ROUNDING: return LowerGET_ROUNDING(Op, DAG);
case ISD::SET_ROUNDING: return LowerSET_ROUNDING(Op, DAG);
+ case ISD::SET_FPMODE:
+ return LowerSET_FPMODE(Op, DAG);
+ case ISD::RESET_FPMODE:
+ return LowerRESET_FPMODE(Op, DAG);
case ISD::MUL: return LowerMUL(Op, DAG);
case ISD::SDIV:
if (Subtarget->isTargetWindows() && !Op.getValueType().isVector())