Commit 0bb9a27c authored by John Brawn's avatar John Brawn
Browse files

[FPEnv][AArch64] Add lowering and instruction selection for strict conversions

Strict fp-to-int and int-to-fp conversions can be handled in the same way that
the non-strict versions are (by using the appropriate instruction or converting
to a function call when we have no instruction).

Differential Revision: https://reviews.llvm.org/D73625
parent ea956685
Loading
Loading
Loading
Loading
+48 −18
Original line number Diff line number Diff line
@@ -282,15 +282,27 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
  setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
  setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
  setOperationAction(ISD::FP_TO_SINT, MVT::i128, Custom);
  setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i32, Custom);
  setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i64, Custom);
  setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i128, Custom);
  setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
  setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
  setOperationAction(ISD::FP_TO_UINT, MVT::i128, Custom);
  setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i32, Custom);
  setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i64, Custom);
  setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i128, Custom);
  setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
  setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
  setOperationAction(ISD::SINT_TO_FP, MVT::i128, Custom);
  setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i32, Custom);
  setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i64, Custom);
  setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i128, Custom);
  setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
  setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
  setOperationAction(ISD::UINT_TO_FP, MVT::i128, Custom);
  setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i32, Custom);
  setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i64, Custom);
  setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i128, Custom);
  setOperationAction(ISD::FP_ROUND, MVT::f32, Custom);
  setOperationAction(ISD::FP_ROUND, MVT::f64, Custom);
  setOperationAction(ISD::STRICT_FP_ROUND, MVT::f32, Custom);
@@ -2324,9 +2336,16 @@ getAArch64XALUOOp(AArch64CC::CondCode &CC, SDValue Op, SelectionDAG &DAG) {
SDValue AArch64TargetLowering::LowerF128Call(SDValue Op, SelectionDAG &DAG,
                                             RTLIB::Libcall Call) const {
  SmallVector<SDValue, 2> Ops(Op->op_begin(), Op->op_end());
  bool IsStrict = Op->isStrictFPOpcode();
  unsigned Offset = IsStrict ? 1 : 0;
  SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue();
  SmallVector<SDValue, 2> Ops(Op->op_begin() + Offset, Op->op_end());
  MakeLibCallOptions CallOptions;
  return makeLibCall(DAG, Call, MVT::f128, Ops, CallOptions, SDLoc(Op)).first;
  SDValue Result;
  SDLoc dl(Op);
  std::tie(Result, Chain) = makeLibCall(DAG, Call, Op.getValueType(), Ops,
                                        CallOptions, dl, Chain);
  return IsStrict ? DAG.getMergeValues({Result, Chain}, dl) : Result;
}
// Returns true if the given Op is the overflow flag result of an overflow
@@ -2587,32 +2606,34 @@ SDValue AArch64TargetLowering::LowerVectorFP_TO_INT(SDValue Op,
SDValue AArch64TargetLowering::LowerFP_TO_INT(SDValue Op,
                                              SelectionDAG &DAG) const {
  if (Op.getOperand(0).getValueType().isVector())
  bool IsStrict = Op->isStrictFPOpcode();
  SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
  if (SrcVal.getValueType().isVector())
    return LowerVectorFP_TO_INT(Op, DAG);
  // f16 conversions are promoted to f32 when full fp16 is not supported.
  if (Op.getOperand(0).getValueType() == MVT::f16 &&
      !Subtarget->hasFullFP16()) {
  if (SrcVal.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) {
    assert(!IsStrict && "Lowering of strict fp16 not yet implemented");
    SDLoc dl(Op);
    return DAG.getNode(
        Op.getOpcode(), dl, Op.getValueType(),
        DAG.getNode(ISD::FP_EXTEND, dl, MVT::f32, Op.getOperand(0)));
        DAG.getNode(ISD::FP_EXTEND, dl, MVT::f32, SrcVal));
  }
  if (Op.getOperand(0).getValueType() != MVT::f128) {
  if (SrcVal.getValueType() != MVT::f128) {
    // It's legal except when f128 is involved
    return Op;
  }
  RTLIB::Libcall LC;
  if (Op.getOpcode() == ISD::FP_TO_SINT)
    LC = RTLIB::getFPTOSINT(Op.getOperand(0).getValueType(), Op.getValueType());
  if (Op.getOpcode() == ISD::FP_TO_SINT ||
      Op.getOpcode() == ISD::STRICT_FP_TO_SINT)
    LC = RTLIB::getFPTOSINT(SrcVal.getValueType(), Op.getValueType());
  else
    LC = RTLIB::getFPTOUINT(Op.getOperand(0).getValueType(), Op.getValueType());
    LC = RTLIB::getFPTOUINT(SrcVal.getValueType(), Op.getValueType());
  SmallVector<SDValue, 2> Ops(Op->op_begin(), Op->op_end());
  MakeLibCallOptions CallOptions;
  return makeLibCall(DAG, LC, Op.getValueType(), Ops, CallOptions, SDLoc(Op)).first;
  return LowerF128Call(Op, DAG, LC);
}
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
@@ -2648,18 +2669,22 @@ SDValue AArch64TargetLowering::LowerINT_TO_FP(SDValue Op,
  if (Op.getValueType().isVector())
    return LowerVectorINT_TO_FP(Op, DAG);
  bool IsStrict = Op->isStrictFPOpcode();
  SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
  // f16 conversions are promoted to f32 when full fp16 is not supported.
  if (Op.getValueType() == MVT::f16 &&
      !Subtarget->hasFullFP16()) {
    assert(!IsStrict && "Lowering of strict fp16 not yet implemented");
    SDLoc dl(Op);
    return DAG.getNode(
        ISD::FP_ROUND, dl, MVT::f16,
        DAG.getNode(Op.getOpcode(), dl, MVT::f32, Op.getOperand(0)),
        DAG.getNode(Op.getOpcode(), dl, MVT::f32, SrcVal),
        DAG.getIntPtrConstant(0, dl));
  }
  // i128 conversions are libcalls.
  if (Op.getOperand(0).getValueType() == MVT::i128)
  if (SrcVal.getValueType() == MVT::i128)
    return SDValue();
  // Other conversions are legal, unless it's to the completely software-based
@@ -2668,10 +2693,11 @@ SDValue AArch64TargetLowering::LowerINT_TO_FP(SDValue Op,
    return Op;
  RTLIB::Libcall LC;
  if (Op.getOpcode() == ISD::SINT_TO_FP)
    LC = RTLIB::getSINTTOFP(Op.getOperand(0).getValueType(), Op.getValueType());
  if (Op.getOpcode() == ISD::SINT_TO_FP ||
      Op.getOpcode() == ISD::STRICT_SINT_TO_FP)
    LC = RTLIB::getSINTTOFP(SrcVal.getValueType(), Op.getValueType());
  else
    LC = RTLIB::getUINTTOFP(Op.getOperand(0).getValueType(), Op.getValueType());
    LC = RTLIB::getUINTTOFP(SrcVal.getValueType(), Op.getValueType());
  return LowerF128Call(Op, DAG, LC);
}
@@ -3262,9 +3288,13 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
    return LowerPREFETCH(Op, DAG);
  case ISD::SINT_TO_FP:
  case ISD::UINT_TO_FP:
  case ISD::STRICT_SINT_TO_FP:
  case ISD::STRICT_UINT_TO_FP:
    return LowerINT_TO_FP(Op, DAG);
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
  case ISD::STRICT_FP_TO_SINT:
  case ISD::STRICT_FP_TO_UINT:
    return LowerFP_TO_INT(Op, DAG);
  case ISD::FSINCOS:
    return LowerFSINCOS(Op, DAG);
+6 −6
Original line number Diff line number Diff line
@@ -3325,10 +3325,10 @@ defm FCVTNS : FPToIntegerUnscaled<0b00, 0b000, "fcvtns", int_aarch64_neon_fcvtns
defm FCVTNU : FPToIntegerUnscaled<0b00, 0b001, "fcvtnu", int_aarch64_neon_fcvtnu>;
defm FCVTPS : FPToIntegerUnscaled<0b01, 0b000, "fcvtps", int_aarch64_neon_fcvtps>;
defm FCVTPU : FPToIntegerUnscaled<0b01, 0b001, "fcvtpu", int_aarch64_neon_fcvtpu>;
defm FCVTZS : FPToIntegerUnscaled<0b11, 0b000, "fcvtzs", fp_to_sint>;
defm FCVTZU : FPToIntegerUnscaled<0b11, 0b001, "fcvtzu", fp_to_uint>;
defm FCVTZS : FPToIntegerScaled<0b11, 0b000, "fcvtzs", fp_to_sint>;
defm FCVTZU : FPToIntegerScaled<0b11, 0b001, "fcvtzu", fp_to_uint>;
defm FCVTZS : FPToIntegerUnscaled<0b11, 0b000, "fcvtzs", any_fp_to_sint>;
defm FCVTZU : FPToIntegerUnscaled<0b11, 0b001, "fcvtzu", any_fp_to_uint>;
defm FCVTZS : FPToIntegerScaled<0b11, 0b000, "fcvtzs", any_fp_to_sint>;
defm FCVTZU : FPToIntegerScaled<0b11, 0b001, "fcvtzu", any_fp_to_uint>;

multiclass FPToIntegerIntPats<Intrinsic round, string INST> {
  def : Pat<(i32 (round f16:$Rn)), (!cast<Instruction>(INST # UWHr) $Rn)>;
@@ -3400,8 +3400,8 @@ def : Pat<(i64 (llround f64:$Rn)),
// Scaled integer to floating point conversion instructions.
//===----------------------------------------------------------------------===//

defm SCVTF : IntegerToFP<0, "scvtf", sint_to_fp>;
defm UCVTF : IntegerToFP<1, "ucvtf", uint_to_fp>;
defm SCVTF : IntegerToFP<0, "scvtf", any_sint_to_fp>;
defm UCVTF : IntegerToFP<1, "ucvtf", any_uint_to_fp>;

//===----------------------------------------------------------------------===//
// Unscaled integer to floating point conversion instruction.
+408 −19

File changed.

Preview size limit exceeded, changes collapsed.

+2 −20
Original line number Diff line number Diff line
@@ -8,18 +8,8 @@
define <1 x double> @test_sitofp(<1 x i1> %in) #0 {
; CHECK-LABEL: test_sitofp:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    sub sp, sp, #16 ; =16
; CHECK-NEXT:    .cfi_def_cfa_offset 16
; CHECK-NEXT:    sbfx w8, w0, #0, #1
; CHECK-NEXT:    mov w9, #1127219200
; CHECK-NEXT:    eor w8, w8, #0x80000000
; CHECK-NEXT:    stp w8, w9, [sp, #8]
; CHECK-NEXT:    ldr d0, [sp, #8]
; CHECK-NEXT:    mov x8, #2147483648
; CHECK-NEXT:    movk x8, #17200, lsl #48
; CHECK-NEXT:    fmov d1, x8
; CHECK-NEXT:    fsub d0, d0, d1
; CHECK-NEXT:    add sp, sp, #16 ; =16
; CHECK-NEXT:    scvtf d0, w8
; CHECK-NEXT:    ret
entry:
  %0 = call <1 x double> @llvm.experimental.constrained.sitofp.v1f64.v1i1(<1 x i1> %in, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
@@ -29,16 +19,8 @@ entry:
define <1 x double> @test_uitofp(<1 x i1> %in) #0 {
; CHECK-LABEL: test_uitofp:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    sub sp, sp, #16 ; =16
; CHECK-NEXT:    .cfi_def_cfa_offset 16
; CHECK-NEXT:    and w8, w0, #0x1
; CHECK-NEXT:    mov w9, #1127219200
; CHECK-NEXT:    stp w8, w9, [sp, #8]
; CHECK-NEXT:    ldr d0, [sp, #8]
; CHECK-NEXT:    mov x8, #4841369599423283200
; CHECK-NEXT:    fmov d1, x8
; CHECK-NEXT:    fsub d0, d0, d1
; CHECK-NEXT:    add sp, sp, #16 ; =16
; CHECK-NEXT:    ucvtf d0, w8
; CHECK-NEXT:    ret
entry:
  %0 = call <1 x double> @llvm.experimental.constrained.uitofp.v1f64.v1i1(<1 x i1> %in, metadata !"round.dynamic", metadata !"fpexcept.strict") #0