Skip to content

Commit 5be66d0

Browse files
authored
[NFC][AMDGPU] Let IR level callers query the FMA/FMAD predicates (#213310)
isFMADLegal and isFMAFasterThanFMulAndFAdd read the denormal mode out of the MachineFunction, so nothing before instruction selection can ask them whether an fmul/fadd pair will be fused. Take an explicit DenormalFPEnv instead, and make the existing MachineFunction / SelectionDAG / MachineInstr entry points thin wrappers over it. Also override the IR level isFMAFasterThanFMulAndFAdd hook. The two views agree by construction, since SIModeRegisterDefaults copies its denormal fields out of getDenormalFPEnv. isFMADLegal uses VT as written and does not look through vectors, so a vector type reports false, as in the SelectionDAG overload it was extracted from. The patch is preparation for querying these from getArithmeticInstrCost and a revived isProfitableToSinkOperands. Contributes to #211092 Assisted-By: Claude Opus 5
1 parent a432964 commit 5be66d0

3 files changed

Lines changed: 56 additions & 19 deletions

File tree

llvm/lib/Target/AMDGPU/SIISelLowering.cpp

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ static cl::opt<bool> UseDivergentRegisterIndexing(
6969
cl::desc("Use indirect register addressing for divergent indexes"),
7070
cl::init(false));
7171

72+
static DenormalFPEnv getDenormalFPEnv(const MachineFunction &MF) {
73+
return MF.getInfo<SIMachineFunctionInfo>()->getMode().getDenormalFPEnv();
74+
}
75+
7276
static bool denormalModeIsFlushAllF32(const MachineFunction &MF) {
7377
const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
7478
return Info->getMode().FP32Denormals == DenormalMode::getPreserveSign();
@@ -7438,9 +7442,11 @@ LLT SITargetLowering::getPreferredShiftAmountTy(LLT Ty) const {
74387442
// however does not support denormals, so we do report fma as faster if we have
74397443
// a fast fma device and require denormals.
74407444
//
7441-
bool SITargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
7442-
EVT VT) const {
7445+
bool SITargetLowering::isFMAFasterThanFMulAndFAdd(EVT VT,
7446+
DenormalFPEnv FPEnv) const {
74437447
VT = VT.getScalarType();
7448+
if (!VT.isSimple())
7449+
return false;
74447450

74457451
switch (VT.getSimpleVT().SimpleTy) {
74467452
case MVT::f32: {
@@ -7451,7 +7457,7 @@ bool SITargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
74517457
// Otherwise f32 mad is always full rate and returns the same result as
74527458
// the separate operations so should be preferred over fma.
74537459
// However does not support denormals.
7454-
if (!denormalModeIsFlushAllF32(MF))
7460+
if (FPEnv.F32Mode != DenormalMode::getPreserveSign())
74557461
return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
74567462

74577463
// If the subtarget has v_fmac_f32, that's just as good as v_mac_f32.
@@ -7461,14 +7467,27 @@ bool SITargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
74617467
return true;
74627468
case MVT::f16:
74637469
case MVT::bf16:
7464-
return Subtarget->has16BitInsts() && !denormalModeIsFlushAllF64F16(MF);
7470+
return Subtarget->has16BitInsts() &&
7471+
FPEnv.DefaultMode != DenormalMode::getPreserveSign();
74657472
default:
74667473
break;
74677474
}
74687475

74697476
return false;
74707477
}
74717478

7479+
bool SITargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
7480+
EVT VT) const {
7481+
return isFMAFasterThanFMulAndFAdd(VT, getDenormalFPEnv(MF));
7482+
}
7483+
7484+
bool SITargetLowering::isFMAFasterThanFMulAndFAdd(const Function &F,
7485+
Type *Ty) const {
7486+
return isFMAFasterThanFMulAndFAdd(
7487+
getValueType(F.getDataLayout(), Ty, /*AllowUnknown=*/true),
7488+
F.getDenormalFPEnv());
7489+
}
7490+
74727491
bool SITargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
74737492
LLT Ty) const {
74747493
switch (Ty.getScalarSizeInBits()) {
@@ -7485,33 +7504,36 @@ bool SITargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
74857504
return false;
74867505
}
74877506

7507+
bool SITargetLowering::isFMADLegal(EVT VT, DenormalFPEnv FPEnv) const {
7508+
// TODO: Check future ftz flag
7509+
// v_mad_f32/v_mac_f32 do not support denormals.
7510+
if (VT == MVT::f32)
7511+
return Subtarget->hasMadMacF32Insts() &&
7512+
FPEnv.F32Mode == DenormalMode::getPreserveSign();
7513+
if (VT == MVT::f16)
7514+
return Subtarget->hasMadF16() &&
7515+
FPEnv.DefaultMode == DenormalMode::getPreserveSign();
7516+
7517+
return false;
7518+
}
7519+
74887520
bool SITargetLowering::isFMADLegal(const MachineInstr &MI, LLT Ty) const {
74897521
if (!Ty.isScalar())
74907522
return false;
74917523

7524+
DenormalFPEnv FPEnv = getDenormalFPEnv(*MI.getMF());
74927525
if (Ty.getScalarSizeInBits() == 16)
7493-
return Subtarget->hasMadF16() && denormalModeIsFlushAllF64F16(*MI.getMF());
7526+
return isFMADLegal(MVT::f16, FPEnv);
74947527
if (Ty.getScalarSizeInBits() == 32)
7495-
return Subtarget->hasMadMacF32Insts() &&
7496-
denormalModeIsFlushAllF32(*MI.getMF());
7528+
return isFMADLegal(MVT::f32, FPEnv);
74977529

74987530
return false;
74997531
}
75007532

75017533
bool SITargetLowering::isFMADLegal(const SelectionDAG &DAG,
75027534
const SDNode *N) const {
7503-
// TODO: Check future ftz flag
7504-
// v_mad_f32/v_mac_f32 do not support denormals.
7505-
EVT VT = N->getValueType(0);
7506-
if (VT == MVT::f32)
7507-
return Subtarget->hasMadMacF32Insts() &&
7508-
denormalModeIsFlushAllF32(DAG.getMachineFunction());
7509-
if (VT == MVT::f16) {
7510-
return Subtarget->hasMadF16() &&
7511-
denormalModeIsFlushAllF64F16(DAG.getMachineFunction());
7512-
}
7513-
7514-
return false;
7535+
return isFMADLegal(N->getValueType(0),
7536+
getDenormalFPEnv(DAG.getMachineFunction()));
75157537
}
75167538

75177539
//===----------------------------------------------------------------------===//

llvm/lib/Target/AMDGPU/SIISelLowering.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "AMDGPUArgumentUsageInfo.h"
1818
#include "AMDGPUISelLowering.h"
1919
#include "SIDefines.h"
20+
#include "llvm/ADT/FloatingPointMode.h"
2021
#include "llvm/CodeGen/MachineFunction.h"
2122

2223
namespace llvm {
@@ -506,6 +507,15 @@ class SITargetLowering final : public AMDGPUTargetLowering {
506507
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override;
507508
bool isFMADLegal(const MachineInstr &MI, const LLT Ty) const override;
508509

510+
/// Variants for IR level callers, which have no MachineFunction to read the
511+
/// denormal mode from and must pass \p FPEnv explicitly.
512+
bool isFMAFasterThanFMulAndFAdd(EVT VT, DenormalFPEnv FPEnv) const;
513+
514+
/// \p VT is used as written, so a vector type reports false.
515+
bool isFMADLegal(EVT VT, DenormalFPEnv FPEnv) const;
516+
517+
bool isFMAFasterThanFMulAndFAdd(const Function &F, Type *Ty) const override;
518+
509519
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const;
510520
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const;
511521
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const;

llvm/lib/Target/AMDGPU/SIModeRegisterDefaults.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ struct SIModeRegisterDefaults {
5656
FP64FP16Denormals == Other.FP64FP16Denormals;
5757
}
5858

59+
/// Get the denormal handling described by this mode.
60+
DenormalFPEnv getDenormalFPEnv() const {
61+
return DenormalFPEnv(FP64FP16Denormals, FP32Denormals);
62+
}
63+
5964
/// Get the encoding value for the FP_DENORM bits of the mode register for the
6065
/// FP32 denormal mode.
6166
uint32_t fpDenormModeSPValue() const {

0 commit comments

Comments
 (0)