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 @@ -14,6 +14,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" @@ -146,22 +147,26 @@ 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); + // Record the physreg defs. If the instruction is potentially predicated + // then do not clear its defs as it could be endup not being executed, + // so it doesn't really kill the register it writes in all cases. + if (!TII->isPredicated(*MI)) { + 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()); } - } 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 diff --git a/llvm/test/CodeGen/Hexagon/dead-code-elim-predicated-instr.mir b/llvm/test/CodeGen/Hexagon/dead-code-elim-predicated-instr.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/dead-code-elim-predicated-instr.mir @@ -0,0 +1,39 @@ +# 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 considers predicated instructions as always run. This causes the pass to delete +# as dead instructions writing to the same registers before the predicated instruction. +# If the instruction though is not ran because of the predication removing such an instruction is wrong +# and it shouldn't be done. +# This test makes sure that that is the case. + +--- +name: predicated_instruction_not_preserved +tracksRegLiveness: true + +body: | + ; CHECK-LABEL: name: predicated_instruction_not_preserved + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $r0 + ; CHECK: bb.1: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $r0 + ; CHECK: A2_nop implicit-def $p0 + ; CHECK: $r0 = C2_cmoveit $p0, 123 + ; CHECK: J2_jumpt killed $p0, %bb.1, implicit-def dead $pc + ; CHECK: J2_jumpr $r31, implicit-def dead $pc + bb.0: + liveins: $r0 + successors: %bb.1 + + bb.1: + successors: %bb.1 + liveins: $r0 + A2_nop implicit-def $p0 + $r1 = A2_sxth killed $r0 + $r0 = A2_tfrsi 1 + $r0 = C2_cmoveit $p0, 123 + J2_jumpt killed $p0, %bb.1, implicit-def dead $pc + J2_jumpr $r31, implicit-def dead $pc +...