diff options
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 37 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.h | 1 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrVFP.td | 4 |
3 files changed, 30 insertions, 12 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 762da041244..414ade7fa6f 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -1283,6 +1283,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { case ARMISD::VMOVDRR: return "ARMISD::VMOVDRR"; case ARMISD::VMOVhr: return "ARMISD::VMOVhr"; case ARMISD::VMOVrh: return "ARMISD::VMOVrh"; + case ARMISD::VMOVSR: return "ARMISD::VMOVSR"; case ARMISD::EH_SJLJ_SETJMP: return "ARMISD::EH_SJLJ_SETJMP"; case ARMISD::EH_SJLJ_LONGJMP: return "ARMISD::EH_SJLJ_LONGJMP"; @@ -4518,9 +4519,10 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { bool InvalidOnQNaN; FPCCToARMCC(CC, CondCode, CondCode2, InvalidOnQNaN); - // Try to generate VMAXNM/VMINNM on ARMv8. - if (Subtarget->hasFPARMv8() && (TrueVal.getValueType() == MVT::f32 || - TrueVal.getValueType() == MVT::f64)) { + // Try to generate VMAXNM/VMINNM on ARMv8. Except if we compare to a zero. + // This ensures we use CMPFPw0 instead of CMPFP in such case. + if (Subtarget->hasFPARMv8() && !isFloatingPointZero(RHS) && + (TrueVal.getValueType() == MVT::f32 || TrueVal.getValueType() == MVT::f64)) { bool swpCmpOps = false; bool swpVselOps = false; checkVSELConstraints(CC, CondCode, swpCmpOps, swpVselOps); @@ -5942,23 +5944,34 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, SDValue ARMTargetLowering::LowerConstantFP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST) const { - bool IsDouble = Op.getValueType() == MVT::f64; + EVT VT = Op.getValueType(); + bool IsDouble = (VT == MVT::f64); ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op); const APFloat &FPVal = CFP->getValueAPF(); // Prevent floating-point constants from using literal loads // when execute-only is enabled. if (ST->genExecuteOnly()) { + // If we can represent the constant as an immediate, don't lower it + if (isFPImmLegal(FPVal, VT)) + return Op; + // Otherwise, construct as integer, and move to float register APInt INTVal = FPVal.bitcastToAPInt(); SDLoc DL(CFP); - if (IsDouble) { - SDValue Lo = DAG.getConstant(INTVal.trunc(32), DL, MVT::i32); - SDValue Hi = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32); - if (!ST->isLittle()) - std::swap(Lo, Hi); - return DAG.getNode(ARMISD::VMOVDRR, DL, MVT::f64, Lo, Hi); - } else { - return DAG.getConstant(INTVal, DL, MVT::i32); + switch (VT.getSimpleVT().SimpleTy) { + default: + llvm_unreachable("Unknown floating point type!"); + break; + case MVT::f64: { + SDValue Lo = DAG.getConstant(INTVal.trunc(32), DL, MVT::i32); + SDValue Hi = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32); + if (!ST->isLittle()) + std::swap(Lo, Hi); + return DAG.getNode(ARMISD::VMOVDRR, DL, MVT::f64, Lo, Hi); + } + case MVT::f32: + return DAG.getNode(ARMISD::VMOVSR, DL, VT, + DAG.getConstant(INTVal, DL, MVT::i32)); } } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h index b196e2344ea..d3d3ac29c67 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.h +++ b/llvm/lib/Target/ARM/ARMISelLowering.h @@ -102,6 +102,7 @@ class VectorType; VMOVRRD, // double to two gprs. VMOVDRR, // Two gprs to double. + VMOVSR, // move gpr to single, used for f32 literal constructed in a gpr EH_SJLJ_SETJMP, // SjLj exception handling setjmp. EH_SJLJ_LONGJMP, // SjLj exception handling longjmp. diff --git a/llvm/lib/Target/ARM/ARMInstrVFP.td b/llvm/lib/Target/ARM/ARMInstrVFP.td index 8731a7fdce9..e6a7730d467 100644 --- a/llvm/lib/Target/ARM/ARMInstrVFP.td +++ b/llvm/lib/Target/ARM/ARMInstrVFP.td @@ -17,11 +17,14 @@ def SDT_VMOVDRR : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisVT<1, i32>, def SDT_VMOVRRD : SDTypeProfile<2, 1, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, SDTCisVT<2, f64>]>; +def SDT_VMOVSR : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i32>]>; + def arm_fmstat : SDNode<"ARMISD::FMSTAT", SDTNone, [SDNPInGlue, SDNPOutGlue]>; def arm_cmpfp : SDNode<"ARMISD::CMPFP", SDT_ARMFCmp, [SDNPOutGlue]>; def arm_cmpfp0 : SDNode<"ARMISD::CMPFPw0", SDT_CMPFP0, [SDNPOutGlue]>; def arm_fmdrr : SDNode<"ARMISD::VMOVDRR", SDT_VMOVDRR>; def arm_fmrrd : SDNode<"ARMISD::VMOVRRD", SDT_VMOVRRD>; +def arm_vmovsr : SDNode<"ARMISD::VMOVSR", SDT_VMOVSR>; def SDT_VMOVhr : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, i32>] >; def SDT_VMOVrh : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisFP<1>] >; @@ -1066,6 +1069,7 @@ def VMOVSR : AVConv4I<0b11100000, 0b1010, // pipelines. let D = VFPNeonDomain; } +def : Pat<(arm_vmovsr GPR:$Rt), (VMOVSR GPR:$Rt)>; let hasSideEffects = 0 in { def VMOVRRD : AVConv3I<0b11000101, 0b1011, |