diff options
| author | Christof Douma <Christof.Douma@arm.com> | 2018-03-23 13:02:03 +0000 | 
|---|---|---|
| committer | Christof Douma <Christof.Douma@arm.com> | 2018-03-23 13:02:03 +0000 | 
| commit | 4a025cc79d30ba67485cb56639ec89913fce2969 (patch) | |
| tree | 48364051d83cdeda06c5044a88a5e6ea04ae59c4 /llvm/lib/Target | |
| parent | f73c3ece7f1004dd5c1b8351a90172258018dd12 (diff) | |
| download | bcm5719-llvm-4a025cc79d30ba67485cb56639ec89913fce2969.tar.gz bcm5719-llvm-4a025cc79d30ba67485cb56639ec89913fce2969.zip  | |
[ARM] Support float literals under XO
When targeting execute-only and fp-armv8, float constants in a compare
resulted in instruction selection failures. This is now fixed by using
vmov.f32 where possible, otherwise the floating point constant is
lowered into a integer constant that is moved into a floating point
register.
This patch also restores using fpcmp with immediate 0 under fp-armv8.
Change-Id: Ie87229706f4ed879a0c0cf66631b6047ed6c6443
llvm-svn: 328313
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,  | 

