//
//===----------------------------------------------------------------------===//
+#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"
const TargetRegisterInfo *TRI;
const MachineRegisterInfo *MRI;
const TargetInstrInfo *TII;
+ LiveIntervals *LIS;
BitVector LivePhysRegs;
public:
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
+ AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}
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!
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
// 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.
}
LivePhysRegs.clear();
+
+ for (auto Reg : RecalcRegs) {
+ LIS->removeInterval(Reg);
+ if (!MRI->reg_empty(Reg))
+ LIS->createAndComputeVirtRegInterval(Reg);
+ }
+
return AnyChanges;
}
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());
// This must be run just after RegisterCoalescing.
insertPass(&RegisterCoalescerID, &SIPreAllocateWWMRegsID, false);
+ if (EnableDCEInRA)
+ insertPass(&RenameIndependentSubregsID, &DeadMachineInstructionElimID);
+
TargetPassConfig::addOptimizedRegAlloc();
}
--- /dev/null
+# 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
+
+...
bb4:
%tmp5 = phi i32 [ %tmp3, %bb2 ], [ %tmp, %bb1 ]
+ store volatile i32 %tmp5, i32 addrspace(1)* undef
br label %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
}
%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
...
%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
...
%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 = 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
...
-# 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
---
-; 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--"