forked from OSchip/llvm-project
[AMDGPU] Really preserve LiveVariables in SILowerControlFlow
https://bugs.llvm.org/show_bug.cgi?id=52204 Differential Revision: https://reviews.llvm.org/D112731
This commit is contained in:
parent
7fbb0678fa
commit
be1a8f8834
|
@ -188,6 +188,12 @@ public:
|
|||
//===--------------------------------------------------------------------===//
|
||||
// API to update live variable information
|
||||
|
||||
/// Recompute liveness from scratch for a virtual register \p Reg that is
|
||||
/// known to have a single def that dominates all uses. This can be useful
|
||||
/// after removing some uses of \p Reg. It is not necessary for the whole
|
||||
/// machine function to be in SSA form.
|
||||
void recomputeForSingleDefVirtReg(Register Reg);
|
||||
|
||||
/// replaceKillInstruction - Update register kill info by replacing a kill
|
||||
/// instruction with a new one.
|
||||
void replaceKillInstruction(Register Reg, MachineInstr &OldMI,
|
||||
|
|
|
@ -669,6 +669,86 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void LiveVariables::recomputeForSingleDefVirtReg(Register Reg) {
|
||||
assert(Reg.isVirtual());
|
||||
|
||||
VarInfo &VI = getVarInfo(Reg);
|
||||
VI.AliveBlocks.clear();
|
||||
VI.Kills.clear();
|
||||
|
||||
MachineInstr &DefMI = *MRI->getUniqueVRegDef(Reg);
|
||||
MachineBasicBlock &DefBB = *DefMI.getParent();
|
||||
|
||||
// Handle the case where all uses have been removed.
|
||||
if (MRI->use_nodbg_empty(Reg)) {
|
||||
VI.Kills.push_back(&DefMI);
|
||||
DefMI.addRegisterDead(Reg, nullptr);
|
||||
return;
|
||||
}
|
||||
DefMI.clearRegisterDeads(Reg);
|
||||
|
||||
// Initialize a worklist of BBs that Reg is live-to-end of. (Here
|
||||
// "live-to-end" means Reg is live at the end of a block even if it is only
|
||||
// live because of phi uses in a successor. This is different from isLiveOut()
|
||||
// which does not consider phi uses.)
|
||||
SmallVector<MachineBasicBlock *> LiveToEndBlocks;
|
||||
SparseBitVector<> UseBlocks;
|
||||
for (auto &UseMO : MRI->use_nodbg_operands(Reg)) {
|
||||
UseMO.setIsKill(false);
|
||||
MachineInstr &UseMI = *UseMO.getParent();
|
||||
MachineBasicBlock &UseBB = *UseMI.getParent();
|
||||
UseBlocks.set(UseBB.getNumber());
|
||||
if (UseMI.isPHI()) {
|
||||
// If Reg is used in a phi then it is live-to-end of the corresponding
|
||||
// predecessor.
|
||||
unsigned Idx = UseMI.getOperandNo(&UseMO);
|
||||
LiveToEndBlocks.push_back(UseMI.getOperand(Idx + 1).getMBB());
|
||||
} else if (&UseBB == &DefBB) {
|
||||
// A non-phi use in the same BB as the single def must come after the def.
|
||||
} else {
|
||||
// Otherwise Reg must be live-to-end of all predecessors.
|
||||
LiveToEndBlocks.append(UseBB.pred_begin(), UseBB.pred_end());
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over the worklist adding blocks to AliveBlocks.
|
||||
bool LiveToEndOfDefBB = false;
|
||||
while (!LiveToEndBlocks.empty()) {
|
||||
MachineBasicBlock &BB = *LiveToEndBlocks.pop_back_val();
|
||||
if (&BB == &DefBB) {
|
||||
LiveToEndOfDefBB = true;
|
||||
continue;
|
||||
}
|
||||
if (VI.AliveBlocks.test(BB.getNumber()))
|
||||
continue;
|
||||
VI.AliveBlocks.set(BB.getNumber());
|
||||
LiveToEndBlocks.append(BB.pred_begin(), BB.pred_end());
|
||||
}
|
||||
|
||||
// Recompute kill flags. For each block in which Reg is used but is not
|
||||
// live-through, find the last instruction that uses Reg. Ignore phi nodes
|
||||
// because they should not be included in Kills.
|
||||
for (unsigned UseBBNum : UseBlocks) {
|
||||
if (VI.AliveBlocks.test(UseBBNum))
|
||||
continue;
|
||||
MachineBasicBlock &UseBB = *MF->getBlockNumbered(UseBBNum);
|
||||
if (&UseBB == &DefBB && LiveToEndOfDefBB)
|
||||
continue;
|
||||
for (auto &MI : reverse(UseBB)) {
|
||||
if (MI.isDebugOrPseudoInstr())
|
||||
continue;
|
||||
if (MI.isPHI())
|
||||
break;
|
||||
if (MI.readsRegister(Reg)) {
|
||||
assert(!MI.killsRegister(Reg));
|
||||
MI.addRegisterKilled(Reg, nullptr);
|
||||
VI.Kills.push_back(&MI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// replaceKillInstruction - Update register kill info by replacing a kill
|
||||
/// instruction with a new one.
|
||||
void LiveVariables::replaceKillInstruction(Register Reg, MachineInstr &OldMI,
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/CodeGen/LiveIntervals.h"
|
||||
#include "llvm/CodeGen/LiveVariables.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
|
||||
|
@ -70,6 +71,7 @@ private:
|
|||
const SIRegisterInfo *TRI = nullptr;
|
||||
const SIInstrInfo *TII = nullptr;
|
||||
LiveIntervals *LIS = nullptr;
|
||||
LiveVariables *LV = nullptr;
|
||||
MachineDominatorTree *MDT = nullptr;
|
||||
MachineRegisterInfo *MRI = nullptr;
|
||||
SetVector<MachineInstr*> LoweredEndCf;
|
||||
|
@ -237,6 +239,8 @@ void SILowerControlFlow::emitIf(MachineInstr &MI) {
|
|||
BuildMI(MBB, I, DL, TII->get(AndOpc), Tmp)
|
||||
.addReg(CopyReg)
|
||||
.add(Cond);
|
||||
if (LV)
|
||||
LV->replaceKillInstruction(Cond.getReg(), MI, *And);
|
||||
|
||||
setImpSCCDefDead(*And, true);
|
||||
|
||||
|
@ -254,6 +258,8 @@ void SILowerControlFlow::emitIf(MachineInstr &MI) {
|
|||
MachineInstr *SetExec =
|
||||
BuildMI(MBB, I, DL, TII->get(MovTermOpc), Exec)
|
||||
.addReg(Tmp, RegState::Kill);
|
||||
if (LV)
|
||||
LV->getVarInfo(Tmp).Kills.push_back(SetExec);
|
||||
|
||||
// Skip ahead to the unconditional branch in case there are other terminators
|
||||
// present.
|
||||
|
@ -307,6 +313,8 @@ void SILowerControlFlow::emitElse(MachineInstr &MI) {
|
|||
MachineInstr *OrSaveExec =
|
||||
BuildMI(MBB, Start, DL, TII->get(OrSaveExecOpc), SaveReg)
|
||||
.add(MI.getOperand(1)); // Saved EXEC
|
||||
if (LV)
|
||||
LV->replaceKillInstruction(MI.getOperand(1).getReg(), MI, *OrSaveExec);
|
||||
|
||||
MachineBasicBlock *DestBB = MI.getOperand(2).getMBB();
|
||||
|
||||
|
@ -380,15 +388,22 @@ void SILowerControlFlow::emitIfBreak(MachineInstr &MI) {
|
|||
And = BuildMI(MBB, &MI, DL, TII->get(AndOpc), AndReg)
|
||||
.addReg(Exec)
|
||||
.add(MI.getOperand(1));
|
||||
if (LV)
|
||||
LV->replaceKillInstruction(MI.getOperand(1).getReg(), MI, *And);
|
||||
Or = BuildMI(MBB, &MI, DL, TII->get(OrOpc), Dst)
|
||||
.addReg(AndReg)
|
||||
.add(MI.getOperand(2));
|
||||
if (LIS)
|
||||
LIS->createAndComputeVirtRegInterval(AndReg);
|
||||
} else
|
||||
} else {
|
||||
Or = BuildMI(MBB, &MI, DL, TII->get(OrOpc), Dst)
|
||||
.add(MI.getOperand(1))
|
||||
.add(MI.getOperand(2));
|
||||
if (LV)
|
||||
LV->replaceKillInstruction(MI.getOperand(1).getReg(), MI, *Or);
|
||||
}
|
||||
if (LV)
|
||||
LV->replaceKillInstruction(MI.getOperand(2).getReg(), MI, *Or);
|
||||
|
||||
if (LIS) {
|
||||
if (And)
|
||||
|
@ -490,6 +505,8 @@ MachineBasicBlock *SILowerControlFlow::emitEndCf(MachineInstr &MI) {
|
|||
BuildMI(MBB, InsPt, DL, TII->get(Opcode), Exec)
|
||||
.addReg(Exec)
|
||||
.add(MI.getOperand(0));
|
||||
if (LV)
|
||||
LV->replaceKillInstruction(MI.getOperand(0).getReg(), MI, *NewMI);
|
||||
|
||||
LoweredEndCf.insert(NewMI);
|
||||
|
||||
|
@ -581,7 +598,12 @@ void SILowerControlFlow::optimizeEndCf() {
|
|||
LLVM_DEBUG(dbgs() << "Skip redundant "; MI->dump());
|
||||
if (LIS)
|
||||
LIS->RemoveMachineInstrFromMaps(*MI);
|
||||
Register Reg;
|
||||
if (LV)
|
||||
Reg = TII->getNamedOperand(*MI, AMDGPU::OpName::src1)->getReg();
|
||||
MI->eraseFromParent();
|
||||
if (LV)
|
||||
LV->recomputeForSingleDefVirtReg(Reg);
|
||||
removeMBBifRedundant(MBB);
|
||||
}
|
||||
}
|
||||
|
@ -697,6 +719,8 @@ void SILowerControlFlow::lowerInitExec(MachineBasicBlock *MBB,
|
|||
auto BfeMI = BuildMI(*MBB, FirstMI, DL, TII->get(AMDGPU::S_BFE_U32), CountReg)
|
||||
.addReg(InputReg)
|
||||
.addImm((MI.getOperand(1).getImm() & Mask) | 0x70000);
|
||||
if (LV)
|
||||
LV->recomputeForSingleDefVirtReg(InputReg);
|
||||
auto BfmMI =
|
||||
BuildMI(*MBB, FirstMI, DL,
|
||||
TII->get(IsWave32 ? AMDGPU::S_BFM_B32 : AMDGPU::S_BFM_B64), Exec)
|
||||
|
@ -705,6 +729,8 @@ void SILowerControlFlow::lowerInitExec(MachineBasicBlock *MBB,
|
|||
auto CmpMI = BuildMI(*MBB, FirstMI, DL, TII->get(AMDGPU::S_CMP_EQ_U32))
|
||||
.addReg(CountReg, RegState::Kill)
|
||||
.addImm(WavefrontSize);
|
||||
if (LV)
|
||||
LV->getVarInfo(CountReg).Kills.push_back(CmpMI);
|
||||
auto CmovMI =
|
||||
BuildMI(*MBB, FirstMI, DL,
|
||||
TII->get(IsWave32 ? AMDGPU::S_CMOV_B32 : AMDGPU::S_CMOV_B64),
|
||||
|
@ -777,17 +803,14 @@ bool SILowerControlFlow::removeMBBifRedundant(MachineBasicBlock &MBB) {
|
|||
}
|
||||
|
||||
bool SILowerControlFlow::runOnMachineFunction(MachineFunction &MF) {
|
||||
// FIXME: This pass causes verification failures.
|
||||
// See: https://bugs.llvm.org/show_bug.cgi?id=52204
|
||||
MF.getProperties().set(
|
||||
MachineFunctionProperties::Property::FailsVerification);
|
||||
|
||||
const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
|
||||
TII = ST.getInstrInfo();
|
||||
TRI = &TII->getRegisterInfo();
|
||||
|
||||
// This doesn't actually need LiveIntervals, but we can preserve them.
|
||||
LIS = getAnalysisIfAvailable<LiveIntervals>();
|
||||
// This doesn't actually need LiveVariables, but we can preserve them.
|
||||
LV = getAnalysisIfAvailable<LiveVariables>();
|
||||
MDT = getAnalysisIfAvailable<MachineDominatorTree>();
|
||||
MRI = &MF.getRegInfo();
|
||||
BoolRC = TRI->getBoolRC();
|
||||
|
|
|
@ -1498,11 +1498,6 @@ void SIWholeQuadMode::lowerKillInstrs(bool IsWQM) {
|
|||
}
|
||||
|
||||
bool SIWholeQuadMode::runOnMachineFunction(MachineFunction &MF) {
|
||||
// This pass is a convenient place to re-enable machine verification after the
|
||||
// problems caused by SILowerControlFlow have been fixed.
|
||||
MF.getProperties().reset(
|
||||
MachineFunctionProperties::Property::FailsVerification);
|
||||
|
||||
LLVM_DEBUG(dbgs() << "SI Whole Quad Mode on " << MF.getName()
|
||||
<< " ------------- \n");
|
||||
LLVM_DEBUG(MF.dump(););
|
||||
|
|
Loading…
Reference in New Issue