[llvm] be1a8f8 - [AMDGPU] Really preserve LiveVariables in SILowerControlFlow
Jay Foad via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 2 08:03:43 PDT 2021
Author: Jay Foad
Date: 2021-11-02T15:03:37Z
New Revision: be1a8f8834c9c515a192a27ae5c633ca9145d95f
URL: https://github.com/llvm/llvm-project/commit/be1a8f8834c9c515a192a27ae5c633ca9145d95f
DIFF: https://github.com/llvm/llvm-project/commit/be1a8f8834c9c515a192a27ae5c633ca9145d95f.diff
LOG: [AMDGPU] Really preserve LiveVariables in SILowerControlFlow
https://bugs.llvm.org/show_bug.cgi?id=52204
Differential Revision: https://reviews.llvm.org/D112731
Added:
Modified:
llvm/include/llvm/CodeGen/LiveVariables.h
llvm/lib/CodeGen/LiveVariables.cpp
llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp
llvm/lib/Target/AMDGPU/SIWholeQuadMode.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/LiveVariables.h b/llvm/include/llvm/CodeGen/LiveVariables.h
index 9b0667bbbeb01..dee316677b258 100644
--- a/llvm/include/llvm/CodeGen/LiveVariables.h
+++ b/llvm/include/llvm/CodeGen/LiveVariables.h
@@ -188,6 +188,12 @@ class LiveVariables : public MachineFunctionPass {
//===--------------------------------------------------------------------===//
// 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,
diff --git a/llvm/lib/CodeGen/LiveVariables.cpp b/llvm/lib/CodeGen/LiveVariables.cpp
index 300a9059de88c..51ba4b7e53eba 100644
--- a/llvm/lib/CodeGen/LiveVariables.cpp
+++ b/llvm/lib/CodeGen/LiveVariables.cpp
@@ -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
diff erent 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,
diff --git a/llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp b/llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp
index 10696939d369f..ec89de25ec11b 100644
--- a/llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp
+++ b/llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp
@@ -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 @@ class SILowerControlFlow : public MachineFunctionPass {
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();
diff --git a/llvm/lib/Target/AMDGPU/SIWholeQuadMode.cpp b/llvm/lib/Target/AMDGPU/SIWholeQuadMode.cpp
index 1f6781301bfe1..38548eaf94785 100644
--- a/llvm/lib/Target/AMDGPU/SIWholeQuadMode.cpp
+++ b/llvm/lib/Target/AMDGPU/SIWholeQuadMode.cpp
@@ -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(););
More information about the llvm-commits
mailing list