Skip to content

Commit 0bb9a27

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
1 parent ea95668 commit 0bb9a27

File tree

4 files changed

+464
-63
lines changed

4 files changed

+464
-63
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -282,15 +282,27 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
282282
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
283283
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
284284
setOperationAction(ISD::FP_TO_SINT, MVT::i128, Custom);
285+
setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i32, Custom);
286+
setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i64, Custom);
287+
setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i128, Custom);
285288
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
286289
setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
287290
setOperationAction(ISD::FP_TO_UINT, MVT::i128, Custom);
291+
setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i32, Custom);
292+
setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i64, Custom);
293+
setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i128, Custom);
288294
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
289295
setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
290296
setOperationAction(ISD::SINT_TO_FP, MVT::i128, Custom);
297+
setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i32, Custom);
298+
setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i64, Custom);
299+
setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i128, Custom);
291300
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
292301
setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
293302
setOperationAction(ISD::UINT_TO_FP, MVT::i128, Custom);
303+
setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i32, Custom);
304+
setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i64, Custom);
305+
setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i128, Custom);
294306
setOperationAction(ISD::FP_ROUND, MVT::f32, Custom);
295307
setOperationAction(ISD::FP_ROUND, MVT::f64, Custom);
296308
setOperationAction(ISD::STRICT_FP_ROUND, MVT::f32, Custom);
@@ -2324,9 +2336,16 @@ getAArch64XALUOOp(AArch64CC::CondCode &CC, SDValue Op, SelectionDAG &DAG) {
23242336

23252337
SDValue AArch64TargetLowering::LowerF128Call(SDValue Op, SelectionDAG &DAG,
23262338
RTLIB::Libcall Call) const {
2327-
SmallVector<SDValue, 2> Ops(Op->op_begin(), Op->op_end());
2339+
bool IsStrict = Op->isStrictFPOpcode();
2340+
unsigned Offset = IsStrict ? 1 : 0;
2341+
SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue();
2342+
SmallVector<SDValue, 2> Ops(Op->op_begin() + Offset, Op->op_end());
23282343
MakeLibCallOptions CallOptions;
2329-
return makeLibCall(DAG, Call, MVT::f128, Ops, CallOptions, SDLoc(Op)).first;
2344+
SDValue Result;
2345+
SDLoc dl(Op);
2346+
std::tie(Result, Chain) = makeLibCall(DAG, Call, Op.getValueType(), Ops,
2347+
CallOptions, dl, Chain);
2348+
return IsStrict ? DAG.getMergeValues({Result, Chain}, dl) : Result;
23302349
}
23312350

23322351
// 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,
25872606

25882607
SDValue AArch64TargetLowering::LowerFP_TO_INT(SDValue Op,
25892608
SelectionDAG &DAG) const {
2590-
if (Op.getOperand(0).getValueType().isVector())
2609+
bool IsStrict = Op->isStrictFPOpcode();
2610+
SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
2611+
2612+
if (SrcVal.getValueType().isVector())
25912613
return LowerVectorFP_TO_INT(Op, DAG);
25922614

25932615
// f16 conversions are promoted to f32 when full fp16 is not supported.
2594-
if (Op.getOperand(0).getValueType() == MVT::f16 &&
2595-
!Subtarget->hasFullFP16()) {
2616+
if (SrcVal.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) {
2617+
assert(!IsStrict && "Lowering of strict fp16 not yet implemented");
25962618
SDLoc dl(Op);
25972619
return DAG.getNode(
25982620
Op.getOpcode(), dl, Op.getValueType(),
2599-
DAG.getNode(ISD::FP_EXTEND, dl, MVT::f32, Op.getOperand(0)));
2621+
DAG.getNode(ISD::FP_EXTEND, dl, MVT::f32, SrcVal));
26002622
}
26012623

2602-
if (Op.getOperand(0).getValueType() != MVT::f128) {
2624+
if (SrcVal.getValueType() != MVT::f128) {
26032625
// It's legal except when f128 is involved
26042626
return Op;
26052627
}
26062628

26072629
RTLIB::Libcall LC;
2608-
if (Op.getOpcode() == ISD::FP_TO_SINT)
2609-
LC = RTLIB::getFPTOSINT(Op.getOperand(0).getValueType(), Op.getValueType());
2630+
if (Op.getOpcode() == ISD::FP_TO_SINT ||
2631+
Op.getOpcode() == ISD::STRICT_FP_TO_SINT)
2632+
LC = RTLIB::getFPTOSINT(SrcVal.getValueType(), Op.getValueType());
26102633
else
2611-
LC = RTLIB::getFPTOUINT(Op.getOperand(0).getValueType(), Op.getValueType());
2634+
LC = RTLIB::getFPTOUINT(SrcVal.getValueType(), Op.getValueType());
26122635

2613-
SmallVector<SDValue, 2> Ops(Op->op_begin(), Op->op_end());
2614-
MakeLibCallOptions CallOptions;
2615-
return makeLibCall(DAG, LC, Op.getValueType(), Ops, CallOptions, SDLoc(Op)).first;
2636+
return LowerF128Call(Op, DAG, LC);
26162637
}
26172638

26182639
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
@@ -2648,18 +2669,22 @@ SDValue AArch64TargetLowering::LowerINT_TO_FP(SDValue Op,
26482669
if (Op.getValueType().isVector())
26492670
return LowerVectorINT_TO_FP(Op, DAG);
26502671

2672+
bool IsStrict = Op->isStrictFPOpcode();
2673+
SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
2674+
26512675
// f16 conversions are promoted to f32 when full fp16 is not supported.
26522676
if (Op.getValueType() == MVT::f16 &&
26532677
!Subtarget->hasFullFP16()) {
2678+
assert(!IsStrict && "Lowering of strict fp16 not yet implemented");
26542679
SDLoc dl(Op);
26552680
return DAG.getNode(
26562681
ISD::FP_ROUND, dl, MVT::f16,
2657-
DAG.getNode(Op.getOpcode(), dl, MVT::f32, Op.getOperand(0)),
2682+
DAG.getNode(Op.getOpcode(), dl, MVT::f32, SrcVal),
26582683
DAG.getIntPtrConstant(0, dl));
26592684
}
26602685

26612686
// i128 conversions are libcalls.
2662-
if (Op.getOperand(0).getValueType() == MVT::i128)
2687+
if (SrcVal.getValueType() == MVT::i128)
26632688
return SDValue();
26642689

26652690
// Other conversions are legal, unless it's to the completely software-based
@@ -2668,10 +2693,11 @@ SDValue AArch64TargetLowering::LowerINT_TO_FP(SDValue Op,
26682693
return Op;
26692694

26702695
RTLIB::Libcall LC;
2671-
if (Op.getOpcode() == ISD::SINT_TO_FP)
2672-
LC = RTLIB::getSINTTOFP(Op.getOperand(0).getValueType(), Op.getValueType());
2696+
if (Op.getOpcode() == ISD::SINT_TO_FP ||
2697+
Op.getOpcode() == ISD::STRICT_SINT_TO_FP)
2698+
LC = RTLIB::getSINTTOFP(SrcVal.getValueType(), Op.getValueType());
26732699
else
2674-
LC = RTLIB::getUINTTOFP(Op.getOperand(0).getValueType(), Op.getValueType());
2700+
LC = RTLIB::getUINTTOFP(SrcVal.getValueType(), Op.getValueType());
26752701

26762702
return LowerF128Call(Op, DAG, LC);
26772703
}
@@ -3262,9 +3288,13 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
32623288
return LowerPREFETCH(Op, DAG);
32633289
case ISD::SINT_TO_FP:
32643290
case ISD::UINT_TO_FP:
3291+
case ISD::STRICT_SINT_TO_FP:
3292+
case ISD::STRICT_UINT_TO_FP:
32653293
return LowerINT_TO_FP(Op, DAG);
32663294
case ISD::FP_TO_SINT:
32673295
case ISD::FP_TO_UINT:
3296+
case ISD::STRICT_FP_TO_SINT:
3297+
case ISD::STRICT_FP_TO_UINT:
32683298
return LowerFP_TO_INT(Op, DAG);
32693299
case ISD::FSINCOS:
32703300
return LowerFSINCOS(Op, DAG);

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3325,10 +3325,10 @@ defm FCVTNS : FPToIntegerUnscaled<0b00, 0b000, "fcvtns", int_aarch64_neon_fcvtns
33253325
defm FCVTNU : FPToIntegerUnscaled<0b00, 0b001, "fcvtnu", int_aarch64_neon_fcvtnu>;
33263326
defm FCVTPS : FPToIntegerUnscaled<0b01, 0b000, "fcvtps", int_aarch64_neon_fcvtps>;
33273327
defm FCVTPU : FPToIntegerUnscaled<0b01, 0b001, "fcvtpu", int_aarch64_neon_fcvtpu>;
3328-
defm FCVTZS : FPToIntegerUnscaled<0b11, 0b000, "fcvtzs", fp_to_sint>;
3329-
defm FCVTZU : FPToIntegerUnscaled<0b11, 0b001, "fcvtzu", fp_to_uint>;
3330-
defm FCVTZS : FPToIntegerScaled<0b11, 0b000, "fcvtzs", fp_to_sint>;
3331-
defm FCVTZU : FPToIntegerScaled<0b11, 0b001, "fcvtzu", fp_to_uint>;
3328+
defm FCVTZS : FPToIntegerUnscaled<0b11, 0b000, "fcvtzs", any_fp_to_sint>;
3329+
defm FCVTZU : FPToIntegerUnscaled<0b11, 0b001, "fcvtzu", any_fp_to_uint>;
3330+
defm FCVTZS : FPToIntegerScaled<0b11, 0b000, "fcvtzs", any_fp_to_sint>;
3331+
defm FCVTZU : FPToIntegerScaled<0b11, 0b001, "fcvtzu", any_fp_to_uint>;
33323332

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

3403-
defm SCVTF : IntegerToFP<0, "scvtf", sint_to_fp>;
3404-
defm UCVTF : IntegerToFP<1, "ucvtf", uint_to_fp>;
3403+
defm SCVTF : IntegerToFP<0, "scvtf", any_sint_to_fp>;
3404+
defm UCVTF : IntegerToFP<1, "ucvtf", any_uint_to_fp>;
34053405

34063406
//===----------------------------------------------------------------------===//
34073407
// Unscaled integer to floating point conversion instruction.

0 commit comments

Comments
 (0)