Skip to content

Commit 589eb95

Browse files
Varnikeaokblast
authored andcommitted
[ARM] Add instruction selection for strict FP (llvm#160696)
This consists of marking the various strict opcodes as legal, and adjusting instruction selection patterns so that 'op' is 'any_op'. The changes are similar to those in D114946 for AArch64. Custom lowering and promotion are set for some FP16 strict ops to work correctly. This PR is part of the work on adding strict FP support in ARM, which was previously discussed in llvm#137101.
1 parent ce071c8 commit 589eb95

File tree

8 files changed

+1896
-139
lines changed

8 files changed

+1896
-139
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -601,10 +601,20 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
601601
setOperationAction(ISD::FP_TO_SINT_SAT, MVT::i64, Custom);
602602
setOperationAction(ISD::FP_TO_UINT_SAT, MVT::i64, Custom);
603603

604-
if (!Subtarget->hasVFP2Base())
604+
if (!Subtarget->hasVFP2Base()) {
605605
setAllExpand(MVT::f32);
606-
if (!Subtarget->hasFP64())
606+
} else {
607+
for (auto Op : {ISD::STRICT_FADD, ISD::STRICT_FSUB, ISD::STRICT_FMUL,
608+
ISD::STRICT_FDIV, ISD::STRICT_FMA, ISD::STRICT_FSQRT})
609+
setOperationAction(Op, MVT::f32, Legal);
610+
}
611+
if (!Subtarget->hasFP64()) {
607612
setAllExpand(MVT::f64);
613+
} else {
614+
for (auto Op : {ISD::STRICT_FADD, ISD::STRICT_FSUB, ISD::STRICT_FMUL,
615+
ISD::STRICT_FDIV, ISD::STRICT_FMA, ISD::STRICT_FSQRT})
616+
setOperationAction(Op, MVT::f64, Legal);
617+
}
608618
}
609619

610620
if (Subtarget->hasFullFP16()) {
@@ -1281,12 +1291,16 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
12811291
if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
12821292
setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);
12831293
setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand);
1294+
setOperationAction(ISD::STRICT_FP16_TO_FP, MVT::f64, LibCall);
1295+
setOperationAction(ISD::STRICT_FP_TO_FP16, MVT::f64, LibCall);
12841296
}
12851297

12861298
// fp16 is a special v7 extension that adds f16 <-> f32 conversions.
12871299
if (!Subtarget->hasFP16()) {
12881300
setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand);
12891301
setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand);
1302+
setOperationAction(ISD::STRICT_FP16_TO_FP, MVT::f32, LibCall);
1303+
setOperationAction(ISD::STRICT_FP_TO_FP16, MVT::f32, LibCall);
12901304
}
12911305

12921306
// Strict floating-point comparisons need custom lowering.
@@ -1333,31 +1347,42 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
13331347
}
13341348

13351349
// FP16 often need to be promoted to call lib functions
1350+
// clang-format off
13361351
if (Subtarget->hasFullFP16()) {
1337-
setOperationAction(ISD::FREM, MVT::f16, Promote);
1338-
setOperationAction(ISD::FCOPYSIGN, MVT::f16, Expand);
1339-
setOperationAction(ISD::FSIN, MVT::f16, Promote);
1340-
setOperationAction(ISD::FCOS, MVT::f16, Promote);
1341-
setOperationAction(ISD::FTAN, MVT::f16, Promote);
1342-
setOperationAction(ISD::FSINCOS, MVT::f16, Promote);
1343-
setOperationAction(ISD::FPOWI, MVT::f16, Promote);
1344-
setOperationAction(ISD::FPOW, MVT::f16, Promote);
1345-
setOperationAction(ISD::FEXP, MVT::f16, Promote);
1346-
setOperationAction(ISD::FEXP2, MVT::f16, Promote);
1347-
setOperationAction(ISD::FEXP10, MVT::f16, Promote);
1348-
setOperationAction(ISD::FLOG, MVT::f16, Promote);
1349-
setOperationAction(ISD::FLOG10, MVT::f16, Promote);
1350-
setOperationAction(ISD::FLOG2, MVT::f16, Promote);
13511352
setOperationAction(ISD::LRINT, MVT::f16, Expand);
13521353
setOperationAction(ISD::LROUND, MVT::f16, Expand);
1353-
1354-
setOperationAction(ISD::FROUND, MVT::f16, Legal);
1355-
setOperationAction(ISD::FROUNDEVEN, MVT::f16, Legal);
1356-
setOperationAction(ISD::FTRUNC, MVT::f16, Legal);
1357-
setOperationAction(ISD::FNEARBYINT, MVT::f16, Legal);
1358-
setOperationAction(ISD::FRINT, MVT::f16, Legal);
1359-
setOperationAction(ISD::FFLOOR, MVT::f16, Legal);
1360-
setOperationAction(ISD::FCEIL, MVT::f16, Legal);
1354+
setOperationAction(ISD::FCOPYSIGN, MVT::f16, Expand);
1355+
1356+
for (auto Op : {ISD::FREM, ISD::FPOW, ISD::FPOWI,
1357+
ISD::FCOS, ISD::FSIN, ISD::FSINCOS,
1358+
ISD::FSINCOSPI, ISD::FMODF, ISD::FACOS,
1359+
ISD::FASIN, ISD::FATAN, ISD::FATAN2,
1360+
ISD::FCOSH, ISD::FSINH, ISD::FTANH,
1361+
ISD::FTAN, ISD::FEXP, ISD::FEXP2,
1362+
ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
1363+
ISD::FLOG10, ISD::STRICT_FREM, ISD::STRICT_FPOW,
1364+
ISD::STRICT_FPOWI, ISD::STRICT_FCOS, ISD::STRICT_FSIN,
1365+
ISD::STRICT_FACOS, ISD::STRICT_FASIN, ISD::STRICT_FATAN,
1366+
ISD::STRICT_FATAN2, ISD::STRICT_FCOSH, ISD::STRICT_FSINH,
1367+
ISD::STRICT_FTANH, ISD::STRICT_FEXP, ISD::STRICT_FEXP2,
1368+
ISD::STRICT_FLOG, ISD::STRICT_FLOG2, ISD::STRICT_FLOG10,
1369+
ISD::STRICT_FTAN}) {
1370+
setOperationAction(Op, MVT::f16, Promote);
1371+
}
1372+
1373+
// Round-to-integer need custom lowering for fp16, as Promote doesn't work
1374+
// because the result type is integer.
1375+
for (auto Op : {ISD::STRICT_LROUND, ISD::STRICT_LLROUND, ISD::STRICT_LRINT, ISD::STRICT_LLRINT})
1376+
setOperationAction(Op, MVT::f16, Custom);
1377+
1378+
for (auto Op : {ISD::FROUND, ISD::FROUNDEVEN, ISD::FTRUNC,
1379+
ISD::FNEARBYINT, ISD::FRINT, ISD::FFLOOR,
1380+
ISD::FCEIL, ISD::STRICT_FROUND, ISD::STRICT_FROUNDEVEN,
1381+
ISD::STRICT_FTRUNC, ISD::STRICT_FNEARBYINT, ISD::STRICT_FRINT,
1382+
ISD::STRICT_FFLOOR, ISD::STRICT_FCEIL}) {
1383+
setOperationAction(Op, MVT::f16, Legal);
1384+
}
1385+
// clang-format on
13611386
}
13621387

13631388
if (Subtarget->hasNEON()) {
@@ -10725,6 +10750,19 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
1072510750
return LowerCMP(Op, DAG);
1072610751
case ISD::ABS:
1072710752
return LowerABS(Op, DAG);
10753+
case ISD::STRICT_LROUND:
10754+
case ISD::STRICT_LLROUND:
10755+
case ISD::STRICT_LRINT:
10756+
case ISD::STRICT_LLRINT: {
10757+
assert((Op.getOperand(1).getValueType() == MVT::f16 ||
10758+
Op.getOperand(1).getValueType() == MVT::bf16) &&
10759+
"Expected custom lowering of rounding operations only for f16");
10760+
SDLoc DL(Op);
10761+
SDValue Ext = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
10762+
{Op.getOperand(0), Op.getOperand(1)});
10763+
return DAG.getNode(Op.getOpcode(), DL, {Op.getValueType(), MVT::Other},
10764+
{Ext.getValue(1), Ext.getValue(0)});
10765+
}
1072810766
}
1072910767
}
1073010768

llvm/lib/Target/ARM/ARMInstrInfo.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,15 +473,15 @@ def xor_su : PatFrag<(ops node:$lhs, node:$rhs), (xor node:$lhs, node:$rhs)>;
473473

474474
// An 'fmul' node with a single use.
475475
let HasOneUse = 1 in
476-
def fmul_su : PatFrag<(ops node:$lhs, node:$rhs), (fmul node:$lhs, node:$rhs)>;
476+
def fmul_su : PatFrag<(ops node:$lhs, node:$rhs), (any_fmul node:$lhs, node:$rhs)>;
477477

478478
// An 'fadd' node which checks for single non-hazardous use.
479-
def fadd_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fadd node:$lhs, node:$rhs),[{
479+
def fadd_mlx : PatFrag<(ops node:$lhs, node:$rhs),(any_fadd node:$lhs, node:$rhs),[{
480480
return hasNoVMLxHazardUse(N);
481481
}]>;
482482

483483
// An 'fsub' node which checks for single non-hazardous use.
484-
def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{
484+
def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(any_fsub node:$lhs, node:$rhs),[{
485485
return hasNoVMLxHazardUse(N);
486486
}]>;
487487

0 commit comments

Comments
 (0)