diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-25 17:35:41 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-06 20:13:06 +0000 |
commit | cb14a3fe5122c879eae1fb480ed7ce82a699ddb6 (patch) | |
tree | b983a613c35ece61d561b5a9ef9cd66419f6c7fb /contrib/llvm-project/llvm/lib/Target/ARM/ARMISelLowering.cpp | |
parent | 3d68ee6cbdb244de9fab1df8a2525d2fa592571e (diff) | |
parent | 99aabd70801bd4bc72c4942747f6d62c675112f5 (diff) | |
download | src-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.cpp | 58 |
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()) |