[RISCV] Start merging demanded reasoning - starting with load/stores [nfc]

This change merges the logic for reasoning about demanded portions of the VTYPE register between the main dataflow algorithm and the backwards mutation post pass. In the process, we get to delete a bunch of now redundant code.

This should be entirely NFC. I included a slight hack (see TODO) to avoid changing behavior in the post pass while being able to use the generalized logic in the prepass. I will fix the TODO in a separate change once this lands.

Differential Revision: https://reviews.llvm.org/D127983
This commit is contained in:
Philip Reames 2022-06-16 14:34:53 -07:00 committed by Philip Reames
parent d764aa7fc6
commit 2fa2cee6a8
1 changed files with 34 additions and 56 deletions

View File

@ -296,6 +296,15 @@ struct DemandedFields {
bool usedVTYPE() {
return SEW || LMUL || SEWLMULRatio || TailPolicy || MaskPolicy;
}
// Mark all VTYPE subfields and properties as demanded
void demandVTYPE() {
SEW = true;
LMUL = true;
SEWLMULRatio = true;
TailPolicy = true;
MaskPolicy = true;
}
};
/// Return true if the two values of the VTYPE register provided are
@ -332,17 +341,24 @@ static bool areCompatibleVTYPEs(uint64_t VType1,
/// Return the fields and properties demanded by the provided instruction.
static DemandedFields getDemanded(const MachineInstr &MI) {
// Warning: This function has to work on both the lowered (i.e. post
// emitVSETVLIs) and pre-lowering forms. The main implication of this is
// that it can't use the value of a SEW, VL, or Policy operand as they might
// be stale after lowering.
// Most instructions don't use any of these subfeilds.
DemandedFields Res;
// Start conservative if registers are used
if (MI.isCall() || MI.isInlineAsm() || MI.readsRegister(RISCV::VL))
Res.VL = true;
if (MI.isCall() || MI.isInlineAsm() || MI.readsRegister(RISCV::VTYPE)) {
Res.SEW = true;
Res.LMUL = true;
Res.SEWLMULRatio = true;
Res.TailPolicy = true;
Res.MaskPolicy = true;
if (MI.isCall() || MI.isInlineAsm() || MI.readsRegister(RISCV::VTYPE))
Res.demandVTYPE();
// Start conservative on the unlowered form too
uint64_t TSFlags = MI.getDesc().TSFlags;
if (RISCVII::hasSEWOp(TSFlags)) {
Res.demandVTYPE();
if (RISCVII::hasVLOp(TSFlags))
Res.VL = true;
}
// Loads and stores with implicit EEW do not demand SEW or LMUL directly.
@ -537,7 +553,16 @@ public:
MaskAgnostic == Require.MaskAgnostic)
return true;
return false;
DemandedFields Used = getDemanded(MI);
// Store instructions don't use the policy fields.
// TODO: Move this into getDemanded; it is here only to avoid changing
// behavior of the post pass in an otherwise NFC code restructure.
uint64_t TSFlags = MI.getDesc().TSFlags;
if (RISCVII::hasSEWOp(TSFlags) && MI.getNumExplicitDefs() == 0) {
Used.TailPolicy = false;
Used.MaskPolicy = false;
}
return areCompatibleVTYPEs(encodeVTYPE(), Require.encodeVTYPE(), Used);
}
// Determine whether the vector instructions requirements represented by
@ -562,37 +587,7 @@ public:
if (SEW == Require.SEW)
return true;
// The AVL must match.
if (!hasSameAVL(Require))
return false;
if (hasCompatibleVTYPE(MI, Require))
return true;
// Store instructions don't use the policy fields.
const bool StoreOp = MI.getNumExplicitDefs() == 0;
if (StoreOp && VLMul == Require.VLMul && SEW == Require.SEW)
return true;
// Anything else is not compatible.
return false;
}
bool isCompatibleWithLoadStoreEEW(unsigned EEW,
const VSETVLIInfo &Require) const {
assert(isValid() && Require.isValid() &&
"Can't compare invalid VSETVLIInfos");
assert(!Require.SEWLMULRatioOnly &&
"Expected a valid VTYPE for instruction!");
assert(EEW == Require.SEW && "Mismatched EEW/SEW for store");
if (isUnknown() || hasSEWLMULRatioOnly())
return false;
if (!hasSameAVL(Require))
return false;
return getSEWLMULRatio() == ::getSEWLMULRatio(EEW, Require.VLMul);
return hasSameAVL(Require) && hasCompatibleVTYPE(MI, Require);
}
bool operator==(const VSETVLIInfo &Other) const {
@ -958,21 +953,6 @@ static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
return NewInfo;
}
static bool canSkipVSETVLIForLoadStore(const MachineInstr &MI,
const VSETVLIInfo &Require,
const VSETVLIInfo &CurInfo) {
Optional<unsigned> EEW = getEEWForLoadStore(MI);
if (!EEW)
return false;
// Stores can ignore the tail and mask policies.
const bool StoreOp = MI.getNumExplicitDefs() == 0;
if (!StoreOp && !CurInfo.hasSamePolicy(Require))
return false;
return CurInfo.isCompatibleWithLoadStoreEEW(*EEW, Require);
}
/// Return true if a VSETVLI is required to transition from CurInfo to Require
/// before MI.
bool RISCVInsertVSETVLI::needVSETVLI(const MachineInstr &MI,
@ -1015,9 +995,7 @@ bool RISCVInsertVSETVLI::needVSETVLI(const MachineInstr &MI,
}
}
// If this is a unit-stride or strided load/store, we may be able to use the
// EMUL=(EEW/SEW)*LMUL relationship to avoid changing VTYPE.
return CurInfo.isUnknown() || !canSkipVSETVLIForLoadStore(MI, Require, CurInfo);
return true;
}
// Given an incoming state reaching MI, modifies that state so that it is minimally