-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[NFC][RISCV] Keep AVLReg define instr inside VSETVLInfo #89180
Conversation
@llvm/pr-subscribers-backend-risc-v Author: Piyou Chen (BeMg) ChangesCurrently, the vsetvli pass tracks the define instruction through This patch keeps the AVLReg DefMI within VSETVLInfo during construction. And replace This information is useful when vsetvli pass live in post-ra situation. The testcases don't change because the VReg always has a unique def in SSA. Full diff: https://github.com/llvm/llvm-project/pull/89180.diff 1 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
index 331253e39c0acb..222123aa706e4f 100644
--- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
@@ -153,7 +153,7 @@ static std::optional<unsigned> getEEWForLoadStore(const MachineInstr &MI) {
}
}
-static bool isNonZeroLoadImmediate(MachineInstr &MI) {
+static bool isNonZeroLoadImmediate(const MachineInstr &MI) {
return MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(1).isReg() && MI.getOperand(2).isImm() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
@@ -438,6 +438,8 @@ class VSETVLIInfo {
unsigned AVLImm;
};
+ const MachineInstr *AVLDefMI;
+
enum : uint8_t {
Uninitialized,
AVLIsReg,
@@ -454,7 +456,7 @@ class VSETVLIInfo {
public:
VSETVLIInfo()
- : AVLImm(0), TailAgnostic(false), MaskAgnostic(false),
+ : AVLImm(0), AVLDefMI(nullptr), TailAgnostic(false), MaskAgnostic(false),
SEWLMULRatioOnly(false) {}
static VSETVLIInfo getUnknown() {
@@ -478,6 +480,8 @@ class VSETVLIInfo {
State = AVLIsImm;
}
+ void setAVLDefMI(const MachineInstr *DefMI) { AVLDefMI = DefMI; }
+
bool hasAVLImm() const { return State == AVLIsImm; }
bool hasAVLReg() const { return State == AVLIsReg; }
Register getAVLReg() const {
@@ -489,13 +493,16 @@ class VSETVLIInfo {
return AVLImm;
}
+ const MachineInstr *getAVLDefMI() const { return AVLDefMI; }
+
void setAVL(VSETVLIInfo Info) {
assert(Info.isValid());
if (Info.isUnknown())
setUnknown();
- else if (Info.hasAVLReg())
+ else if (Info.hasAVLReg()) {
setAVLReg(Info.getAVLReg());
- else {
+ setAVLDefMI(Info.getAVLDefMI());
+ } else {
assert(Info.hasAVLImm());
setAVLImm(Info.getAVLImm());
}
@@ -512,8 +519,7 @@ class VSETVLIInfo {
if (hasAVLReg()) {
if (getAVLReg() == RISCV::X0)
return true;
- if (MachineInstr *MI = MRI.getVRegDef(getAVLReg());
- MI && isNonZeroLoadImmediate(*MI))
+ if (getAVLDefMI() && isNonZeroLoadImmediate(*getAVLDefMI()))
return true;
return false;
}
@@ -792,7 +798,8 @@ INITIALIZE_PASS(RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME,
// Return a VSETVLIInfo representing the changes made by this VSETVLI or
// VSETIVLI instruction.
-static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
+static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI,
+ const MachineRegisterInfo &MRI) {
VSETVLIInfo NewInfo;
if (MI.getOpcode() == RISCV::PseudoVSETIVLI) {
NewInfo.setAVLImm(MI.getOperand(1).getImm());
@@ -803,6 +810,8 @@ static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
assert((AVLReg != RISCV::X0 || MI.getOperand(0).getReg() != RISCV::X0) &&
"Can't handle X0, X0 vsetvli yet");
NewInfo.setAVLReg(AVLReg);
+ if (AVLReg.isVirtual())
+ NewInfo.setAVLDefMI(MRI.getVRegDef(AVLReg));
}
NewInfo.setVTYPE(MI.getOperand(2).getImm());
@@ -875,6 +884,8 @@ static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags,
InstrInfo.setAVLImm(Imm);
} else {
InstrInfo.setAVLReg(VLOp.getReg());
+ if (VLOp.getReg().isVirtual())
+ InstrInfo.setAVLDefMI(MRI->getVRegDef(VLOp.getReg()));
}
} else {
assert(isScalarExtractInstr(MI));
@@ -892,9 +903,10 @@ static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags,
// register AVLs to avoid extending live ranges without being sure we can
// kill the original source reg entirely.
if (InstrInfo.hasAVLReg() && InstrInfo.getAVLReg().isVirtual()) {
- MachineInstr *DefMI = MRI->getVRegDef(InstrInfo.getAVLReg());
- if (DefMI && isVectorConfigInstr(*DefMI)) {
- VSETVLIInfo DefInstrInfo = getInfoForVSETVLI(*DefMI);
+ if (InstrInfo.getAVLDefMI() &&
+ isVectorConfigInstr(*InstrInfo.getAVLDefMI())) {
+ VSETVLIInfo DefInstrInfo =
+ getInfoForVSETVLI(*InstrInfo.getAVLDefMI(), *MRI);
if (DefInstrInfo.hasSameVLMAX(InstrInfo) &&
(DefInstrInfo.hasAVLImm() || DefInstrInfo.getAVLReg() == RISCV::X0)) {
InstrInfo.setAVL(DefInstrInfo);
@@ -934,9 +946,9 @@ void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB,
// same, we can use the X0, X0 form.
if (Info.hasSameVLMAX(PrevInfo) && Info.hasAVLReg() &&
Info.getAVLReg().isVirtual()) {
- if (MachineInstr *DefMI = MRI->getVRegDef(Info.getAVLReg())) {
- if (isVectorConfigInstr(*DefMI)) {
- VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI);
+ if (Info.getAVLDefMI()) {
+ if (isVectorConfigInstr(*Info.getAVLDefMI())) {
+ VSETVLIInfo DefInfo = getInfoForVSETVLI(*Info.getAVLDefMI(), *MRI);
if (DefInfo.hasSameAVL(PrevInfo) && DefInfo.hasSameVLMAX(PrevInfo)) {
BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0))
.addReg(RISCV::X0, RegState::Define | RegState::Dead)
@@ -1056,9 +1068,9 @@ bool RISCVInsertVSETVLI::needVSETVLI(const MachineInstr &MI,
// VSETVLI here.
if (Require.hasAVLReg() && Require.getAVLReg().isVirtual() &&
CurInfo.hasCompatibleVTYPE(Used, Require)) {
- if (MachineInstr *DefMI = MRI->getVRegDef(Require.getAVLReg())) {
- if (isVectorConfigInstr(*DefMI)) {
- VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI);
+ if (Require.getAVLDefMI()) {
+ if (isVectorConfigInstr(*Require.getAVLDefMI())) {
+ VSETVLIInfo DefInfo = getInfoForVSETVLI(*Require.getAVLDefMI(), *MRI);
if (DefInfo.hasSameAVL(CurInfo) && DefInfo.hasSameVLMAX(CurInfo))
return false;
}
@@ -1145,13 +1157,15 @@ void RISCVInsertVSETVLI::transferBefore(VSETVLIInfo &Info,
void RISCVInsertVSETVLI::transferAfter(VSETVLIInfo &Info,
const MachineInstr &MI) const {
if (isVectorConfigInstr(MI)) {
- Info = getInfoForVSETVLI(MI);
+ Info = getInfoForVSETVLI(MI, *MRI);
return;
}
if (RISCV::isFaultFirstLoad(MI)) {
// Update AVL to vl-output of the fault first load.
Info.setAVLReg(MI.getOperand(1).getReg());
+ if (MI.getOperand(1).getReg().isVirtual())
+ Info.setAVLDefMI(MRI->getVRegDef(MI.getOperand(1).getReg()));
return;
}
@@ -1270,7 +1284,7 @@ bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo &Require,
// We found a VSET(I)VLI make sure it matches the output of the
// predecessor block.
- VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI);
+ VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI, *MRI);
if (!DefInfo.hasSameAVL(PBBInfo.Exit) ||
!DefInfo.hasSameVTYPE(PBBInfo.Exit))
return true;
@@ -1418,7 +1432,7 @@ void RISCVInsertVSETVLI::doPRE(MachineBasicBlock &MBB) {
// we need to prove the value is available at the point we're going
// to insert the vsetvli at.
if (AvailableInfo.hasAVLReg() && RISCV::X0 != AvailableInfo.getAVLReg()) {
- MachineInstr *AVLDefMI = MRI->getVRegDef(AvailableInfo.getAVLReg());
+ const MachineInstr *AVLDefMI = AvailableInfo.getAVLDefMI();
if (!AVLDefMI)
return;
// This is an inline dominance check which covers the case of
@@ -1504,8 +1518,8 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
if (Used.VLZeroness) {
if (isVLPreservingConfig(PrevMI))
return false;
- if (!getInfoForVSETVLI(PrevMI).hasEquallyZeroAVL(getInfoForVSETVLI(MI),
- MRI))
+ if (!getInfoForVSETVLI(PrevMI, MRI)
+ .hasEquallyZeroAVL(getInfoForVSETVLI(MI, MRI), MRI))
return false;
}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the PR title be marked with NFC
cee023a
to
cae0c63
Compare
We currently use AVLIsReg to represent VLMAX as well as a dummy value for whenever the VL is ignored by vmv.x.s. This splits them out into separate states so that AVLIsReg is always a virtual register and should help with tracking the definition inside VSETVLIInfo directly in llvm#89180. This is almost an NFC but it sets the kill flag for x0 in more places.
cae0c63
to
efc895c
Compare
Base on #89964, replace AVLIsReg with AVLIsDefMI. |
We currently use AVLIsReg to represent VLMAX as well as a dummy value for whenever the VL is ignored by vmv.x.s. This splits them out into separate states so that AVLIsReg is always a virtual register and should help with tracking the definition inside VSETVLIInfo directly in #89180. This is almost an NFC but it sets the kill flag for x0 in more places.
return; | ||
} | ||
|
||
if (RISCV::isFaultFirstLoad(MI)) { | ||
// Update AVL to vl-output of the fault first load. | ||
Info.setAVLReg(MI.getOperand(1).getReg()); | ||
Info.setAVLDefMI(MRI->getVRegDef(MI.getOperand(1).getReg())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just making a note, I don't think we have any pseudos that have more than one scalar def, but if we did then we would also need to track the operand number.
VSETVLIInfo DefInstrInfo = getInfoForVSETVLI(*DefMI); | ||
if (InstrInfo.hasAVLDefMI()) { | ||
const MachineInstr *DefMI = InstrInfo.getAVLDefMI(); | ||
if (DefMI && isVectorConfigInstr(*DefMI)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DefMI should never be null, what do you think about changing getAVLDefMI()
to return a const reference? Looks like a lot of the uses require dereferencing it anyway.
assert(hasAVLReg()); | ||
return AVLReg; | ||
assert(hasAVLDefMI()); | ||
return AVLDefMI->getOperand(0).getReg(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the AVL comes from the def of a fault first load then I think it will come from the first operand. I think we might need to track the operand number then in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about keeping both AVLReg and AVLDefMI inside VSETVLInfo? Tracking the operand number looks too indirect because we just want AVLReg here.
RISCVInsertVSETVLI::insertVSETVLI
is only place need AVLReg actually.
Register AVLReg = Info.getAVLReg();
MRI->constrainRegClass(AVLReg, &RISCV::GPRNoX0RegClass);
BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLI))
.addReg(RISCV::X0, RegState::Define | RegState::Dead)
.addReg(AVLReg)
.addImm(Info.encodeVTYPE());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that also works, as long as we can fit it inside the existing union, something like this maybe?
struct Def { const MachineInstr *DefMI; Register Reg; };
union {
Def AVLDef;
unsigned AVLImm;
};
Would need to also update the == and AVL comparison methods to check the register too I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to use std::pair here but it has a non-trivial copy constructor unfortunately
efc895c
to
25ecf90
Compare
Rebase with main branch |
Update
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Hopefully then in #70549 we can replace the AVLDef struct with VNInfo or whatever is needed to track definitions post-SSA.
bfbb42a
to
5c42b12
Compare
Rebase with main |
5c42b12
to
c5522ce
Compare
Currently, the vsetvli pass track the define instruction through MRI->getVRegDef due to the SSA form. This patch keeps the AVLReg DefMI within VSETVLInfo during construction. And replace MRI->getVRegDef(AVLReg) with getAVLRegDefMI(). This information is useful when vsetvli pass live in post-ra situation. The testcases don't change because the VReg always has a unique def in SSA.
c5522ce
to
bedde94
Compare
Currently, the vsetvli pass tracks the define instruction through
MRI->getVRegDef
due to the SSA form.This patch keeps the AVLReg DefMI within VSETVLInfo during construction. And replace
MRI->getVRegDef(AVLReg)
withgetAVLRegDefMI()
.This information is useful when vsetvli pass live in post-ra situation.
The testcases don't change because the VReg always has a unique def in SSA.