Skip to content

Commit

Permalink
[AMDGPU] Add MachineDCE pass after RenameIndependentSubregs
Browse files Browse the repository at this point in the history
Detect dead lanes can create some dead defs. Then RenameIndependentSubregs
will break a REG_SEQUENCE which may use these dead defs. At this point
a dead instruction can be removed but we do not run a DCE anymore.

MachineDCE was only running before live variable analysis. The patch
adds a mean to preserve LiveIntervals and SlotIndexes in case it works
past this.

Differential Revision: https://reviews.llvm.org/D59626

llvm-svn: 357805
  • Loading branch information
rampitec committed Apr 5, 2019
1 parent d2225d0 commit c8f78f8
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 4 deletions.
30 changes: 28 additions & 2 deletions llvm/lib/CodeGen/DeadMachineInstructionElim.cpp
Expand Up @@ -10,7 +10,9 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
Expand All @@ -32,6 +34,7 @@ namespace {
const TargetRegisterInfo *TRI;
const MachineRegisterInfo *MRI;
const TargetInstrInfo *TII;
LiveIntervals *LIS;
BitVector LivePhysRegs;

public:
Expand All @@ -41,7 +44,7 @@ namespace {
}

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}

Expand Down Expand Up @@ -78,9 +81,15 @@ bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const {
unsigned Reg = MO.getReg();
if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
// Don't delete live physreg defs, or any reserved register defs.
if (LivePhysRegs.test(Reg) || MRI->isReserved(Reg))
// Do not remove physreg defs if we have LIS as we may be unable
// to accurately recompute its liveness.
if (LivePhysRegs.test(Reg) || MRI->isReserved(Reg) || LIS)
return false;
} else {
// An instruction can also use its def in case if it is a tied operand.
// TODO: Technically we can also remove it if def dominates the use.
// This can happen when two instructions define different subregs
// of the same register.
for (const MachineInstr &Use : MRI->use_nodbg_instructions(Reg)) {
if (&Use != MI)
// This def has a non-debug use. Don't delete the instruction!
Expand All @@ -102,6 +111,8 @@ bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) {
MRI = &MF.getRegInfo();
TRI = MF.getSubtarget().getRegisterInfo();
TII = MF.getSubtarget().getInstrInfo();
LIS = getAnalysisIfAvailable<LiveIntervals>();
DenseSet<unsigned> RecalcRegs;

// Loop over all instructions in all blocks, from bottom to top, so that it's
// more likely that chains of dependent but ultimately dead instructions will
Expand All @@ -127,6 +138,14 @@ bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) {
// If the instruction is dead, delete it!
if (isDead(MI)) {
LLVM_DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << *MI);
if (LIS) {
for (const MachineOperand &MO : MI->operands()) {
if (MO.isReg() && TRI->isVirtualRegister(MO.getReg()))
RecalcRegs.insert(MO.getReg());
}
LIS->RemoveMachineInstrFromMaps(*MI);
}

// It is possible that some DBG_VALUE instructions refer to this
// instruction. They get marked as undef and will be deleted
// in the live debug variable analysis.
Expand Down Expand Up @@ -170,5 +189,12 @@ bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) {
}

LivePhysRegs.clear();

for (auto Reg : RecalcRegs) {
LIS->removeInterval(Reg);
if (!MRI->reg_empty(Reg))
LIS->createAndComputeVirtRegInterval(Reg);
}

return AnyChanges;
}
9 changes: 9 additions & 0 deletions llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
Expand Up @@ -163,6 +163,12 @@ static cl::opt<bool> EnableSIModeRegisterPass(
cl::init(true),
cl::Hidden);

// Option is used in lit tests to prevent deadcoding of patterns inspected.
static cl::opt<bool>
EnableDCEInRA("amdgpu-dce-in-ra",
cl::init(true), cl::Hidden,
cl::desc("Enable machine DCE inside regalloc"));

extern "C" void LLVMInitializeAMDGPUTarget() {
// Register the target
RegisterTargetMachine<R600TargetMachine> X(getTheAMDGPUTarget());
Expand Down Expand Up @@ -901,6 +907,9 @@ void GCNPassConfig::addOptimizedRegAlloc() {
// This must be run just after RegisterCoalescing.
insertPass(&RegisterCoalescerID, &SIPreAllocateWWMRegsID, false);

if (EnableDCEInRA)
insertPass(&RenameIndependentSubregsID, &DeadMachineInstructionElimID);

TargetPassConfig::addOptimizedRegAlloc();
}

Expand Down
18 changes: 18 additions & 0 deletions llvm/test/CodeGen/AMDGPU/dead-lane.mir
@@ -0,0 +1,18 @@
# RUN: llc -march=amdgcn -mcpu=tonga %s -start-before detect-dead-lanes -stop-before machine-scheduler -verify-machineinstrs -o - | FileCheck -check-prefix=GCN %s

# GCN-LABEL: name: dead_lane
# GCN: bb.0:
# GCN-NEXT: undef %3.sub0:vreg_64 = V_MAC_F32_e32 undef %1:vgpr_32, undef %1:vgpr_32, undef %3.sub0, implicit $exec
# GCN-NEXT: FLAT_STORE_DWORD undef %4:vreg_64, %3.sub0,
---
name: dead_lane
tracksRegLiveness: true
body: |
bb.0:
%1:vgpr_32 = V_MAC_F32_e32 undef %0:vgpr_32, undef %0:vgpr_32, undef %0:vgpr_32, implicit $exec
%2:vgpr_32 = V_MAC_F32_e32 undef %0:vgpr_32, undef %0:vgpr_32, undef %0:vgpr_32, implicit $exec
%3:vreg_64 = REG_SEQUENCE %1:vgpr_32, %subreg.sub0, %2:vgpr_32, %subreg.sub1
FLAT_STORE_DWORD undef %4:vreg_64, %3.sub0, 0, 0, 0, implicit $exec, implicit $flat_scr
S_ENDPGM 0
...
1 change: 1 addition & 0 deletions llvm/test/CodeGen/AMDGPU/salu-to-valu.ll
Expand Up @@ -475,6 +475,7 @@ bb2:

bb4:
%tmp5 = phi i32 [ %tmp3, %bb2 ], [ %tmp, %bb1 ]
store volatile i32 %tmp5, i32 addrspace(1)* undef
br label %bb1
}

Expand Down
1 change: 1 addition & 0 deletions llvm/test/CodeGen/AMDGPU/sdwa-peephole.ll
Expand Up @@ -523,5 +523,6 @@ bb2: ; preds = %bb1

bb11: ; preds = %bb10, %bb2
%tmp12 = phi <2 x i32> [ %tmp6, %bb2 ], [ %tmp, %bb1 ]
store volatile <2 x i32> %tmp12, <2 x i32> addrspace(1)* undef
br label %bb1
}
4 changes: 4 additions & 0 deletions llvm/test/CodeGen/AMDGPU/shrink-carry.mir
Expand Up @@ -21,6 +21,7 @@ body: |
%2 = IMPLICIT_DEF
%3 = V_CMP_GT_U32_e64 %0, %1, implicit $exec
%4, %5 = V_SUBBREV_U32_e64 0, %0, %3, 0, implicit $exec
GLOBAL_STORE_DWORD undef $vgpr0_vgpr1, %4, 0, 0, 0, implicit $exec
...

Expand All @@ -45,6 +46,7 @@ body: |
%2 = IMPLICIT_DEF
%3 = V_CMP_GT_U32_e64 %0, %1, implicit $exec
%4, %5 = V_SUBB_U32_e64 %0, 0, %3, 0, implicit $exec
GLOBAL_STORE_DWORD undef $vgpr0_vgpr1, %4, 0, 0, 0, implicit $exec
...

Expand All @@ -69,6 +71,7 @@ body: |
%2 = IMPLICIT_DEF
%3 = V_CMP_GT_U32_e64 %0, %1, implicit $exec
%4, %5 = V_ADDC_U32_e64 0, %0, %3, 0, implicit $exec
GLOBAL_STORE_DWORD undef $vgpr0_vgpr1, %4, 0, 0, 0, implicit $exec
...

Expand All @@ -93,5 +96,6 @@ body: |
%2 = IMPLICIT_DEF
%3 = V_CMP_GT_U32_e64 %0, %1, implicit $exec
%4, %5 = V_ADDC_U32_e64 %0, 0, %3, 0, implicit $exec
GLOBAL_STORE_DWORD undef $vgpr0_vgpr1, %4, 0, 0, 0, implicit $exec
...
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/AMDGPU/spill-empty-live-interval.mir
@@ -1,4 +1,4 @@
# RUN: llc -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -stress-regalloc=1 -start-before=simple-register-coalescing -stop-after=greedy -o - %s | FileCheck %s
# RUN: llc -mtriple=amdgcn-amd-amdhsa -amdgpu-dce-in-ra=0 -verify-machineinstrs -stress-regalloc=1 -start-before=simple-register-coalescing -stop-after=greedy -o - %s | FileCheck %s
# https://bugs.llvm.org/show_bug.cgi?id=33620

---
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/AMDGPU/subreg-coalescer-undef-use.ll
@@ -1,4 +1,4 @@
; RUN: llc -march=amdgcn -mcpu=tahiti -o - %s | FileCheck %s
; RUN: llc -march=amdgcn -mcpu=tahiti -amdgpu-dce-in-ra=0 -o - %s | FileCheck %s
; Don't crash when the use of an undefined value is only detected by the
; register coalescer because it is hidden with subregister insert/extract.
target triple="amdgcn--"
Expand Down

0 comments on commit c8f78f8

Please sign in to comment.