diff --git a/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp b/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp --- a/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp +++ b/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" @@ -33,7 +34,7 @@ const TargetRegisterInfo *TRI; const MachineRegisterInfo *MRI; const TargetInstrInfo *TII; - BitVector LivePhysRegs; + LivePhysRegs LiveRegs; public: static char ID; // Pass identification, replacement for typeid @@ -79,7 +80,7 @@ Register Reg = MO.getReg(); if (Register::isPhysicalRegister(Reg)) { // Don't delete live physreg defs, or any reserved register defs. - if (LivePhysRegs.test(Reg) || MRI->isReserved(Reg)) + if (!LiveRegs.available(*MRI, Reg) || MRI->isReserved(Reg)) return false; } else { if (MO.isDead()) { @@ -112,21 +113,15 @@ MRI = &MF.getRegInfo(); TRI = MF.getSubtarget().getRegisterInfo(); TII = MF.getSubtarget().getInstrInfo(); + LiveRegs.init(*TRI); // 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 // be cleaned up. for (MachineBasicBlock &MBB : make_range(MF.rbegin(), MF.rend())) { - // Start out assuming that reserved registers are live out of this block. - LivePhysRegs = MRI->getReservedRegs(); - // Add live-ins from successors to LivePhysRegs. Normally, physregs are not - // live across blocks, but some targets (x86) can have flags live out of a - // block. - for (MachineBasicBlock::succ_iterator S = MBB.succ_begin(), - E = MBB.succ_end(); S != E; S++) - for (const auto &LI : (*S)->liveins()) - LivePhysRegs.set(LI.PhysReg); + // Add live-ins from successors to LivePhysRegs. + LiveRegs.addLiveOutsNoPristines(MBB); // Now scan the instructions and delete dead ones, tracking physreg // liveness as we go. @@ -146,39 +141,12 @@ continue; } - // Record the physreg defs. - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isDef()) { - Register Reg = MO.getReg(); - if (Register::isPhysicalRegister(Reg)) { - // Check the subreg set, not the alias set, because a def - // of a super-register may still be partially live after - // this def. - for (MCSubRegIterator SR(Reg, TRI,/*IncludeSelf=*/true); - SR.isValid(); ++SR) - LivePhysRegs.reset(*SR); - } - } else if (MO.isRegMask()) { - // Register mask of preserved registers. All clobbers are dead. - LivePhysRegs.clearBitsNotInMask(MO.getRegMask()); - } - } - // Record the physreg uses, after the defs, in case a physreg is - // both defined and used in the same instruction. - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isUse()) { - Register Reg = MO.getReg(); - if (Register::isPhysicalRegister(Reg)) { - for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) - LivePhysRegs.set(*AI); - } - } - } + // Update live-regs by passing past this instruction and recording + // uses/defs. in a backward fashion. + LiveRegs.stepBackward(*MI); } } - LivePhysRegs.clear(); + LiveRegs.clear(); return AnyChanges; } diff --git a/llvm/test/CodeGen/Hexagon/dead-code-elim-sub-reg-livein.mir b/llvm/test/CodeGen/Hexagon/dead-code-elim-sub-reg-livein.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/dead-code-elim-sub-reg-livein.mir @@ -0,0 +1,35 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=hexagon -run-pass dead-mi-elimination -verify-machineinstrs %s -o - | FileCheck %s + +# DeadMachineCodeElimination needs to add the subregisters of the live-ins of a block to avoid +# deleting instructions writing to parts of a super register. +# This test is making sure that this happens. + +--- +name: livein_sub_reg_not_preserved +tracksRegLiveness: true + +body: | + ; CHECK-LABEL: name: livein_sub_reg_not_preserved + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $d0, $r2 + ; CHECK: bb.1: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $d0, $r2 + ; CHECK: $r0 = A2_tfrsi 1 + ; CHECK: A2_nop implicit-def $p0 + ; CHECK: J2_jumpt killed $p0, %bb.1, implicit-def dead $pc + ; CHECK: J2_jumpr $r31, implicit-def dead $pc + bb.0: + liveins: $d0, $r2 + successors: %bb.1 + + bb.1: + successors: %bb.1 + liveins: $d0, $r2 + $r0 = A2_tfrsi 1 + A2_nop implicit-def $p0 + J2_jumpt killed $p0, %bb.1, implicit-def dead $pc + J2_jumpr $r31, implicit-def dead $pc +...