diff options
author | Jeremy Morse <jeremy.morse@sony.com> | 2021-10-18 11:37:51 +0100 |
---|---|---|
committer | Jeremy Morse <jeremy.morse@sony.com> | 2021-10-18 11:52:45 +0100 |
commit | c4ede6d60892a5101d159b4876ad76fc8eefc837 (patch) | |
tree | 60f282b78328d09cbd6a889eecedcb773319bab1 | |
parent | d8bc7e40ce1cdd8c1a3fac7937ce1ea85c262728 (diff) | |
download | llvm-c4ede6d60892a5101d159b4876ad76fc8eefc837.tar.gz |
[DebugInfo][InstrRef] Avoid a crash during DBG_PHI maintenence
With D110105, the isDebug flag for register uses is now a proxy for whether
the instruction is a debug instruction; that causes DBG_PHIs to have their
operands updated by calls to updateDbgUsersToReg, which is the correct
behaviour. However: that function only expects to receive DBG_VALUE
instructions and asserts such.
This patch splits the updating-action into a lambda, and applies it to the
appropriate operands for each kind of debug instruction. Tested with an
ARM test that stimulates this function: I've added some DBG_PHI
instructions that should be updated in the same way as DBG_VALUEs.
Differential Revision: https://reviews.llvm.org/D108641
-rw-r--r-- | llvm/include/llvm/CodeGen/MachineRegisterInfo.h | 39 | ||||
-rw-r--r-- | llvm/test/DebugInfo/ARM/machine-cp-updates-dbg-reg.mir | 4 |
2 files changed, 30 insertions, 13 deletions
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 3756dc1b4588..dbabfe5f0f32 100644 --- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -821,7 +821,7 @@ public: /// deleted during LiveDebugVariables analysis. void markUsesInDebugValueAsUndef(Register Reg) const; - /// updateDbgUsersToReg - Update a collection of DBG_VALUE instructions + /// updateDbgUsersToReg - Update a collection of debug instructions /// to refer to the designated register. void updateDbgUsersToReg(MCRegister OldReg, MCRegister NewReg, ArrayRef<MachineInstr *> Users) const { @@ -829,21 +829,34 @@ public: for (MCRegUnitIterator RUI(OldReg, getTargetRegisterInfo()); RUI.isValid(); ++RUI) OldRegUnits.insert(*RUI); - for (MachineInstr *MI : Users) { - assert(MI->isDebugValue()); - for (auto &Op : MI->debug_operands()) { - if (Op.isReg()) { - for (MCRegUnitIterator RUI(OldReg, getTargetRegisterInfo()); - RUI.isValid(); ++RUI) { - if (OldRegUnits.contains(*RUI)) { - Op.setReg(NewReg); - break; - } + + // If this operand is a register, check whether it overlaps with OldReg. + // If it does, replace with NewReg. + auto UpdateOp = [this, &NewReg, &OldReg, &OldRegUnits](MachineOperand &Op) { + if (Op.isReg()) { + for (MCRegUnitIterator RUI(OldReg, getTargetRegisterInfo()); + RUI.isValid(); ++RUI) { + if (OldRegUnits.contains(*RUI)) { + Op.setReg(NewReg); + break; } } } - assert(MI->hasDebugOperandForReg(NewReg) && - "Expected debug value to have some overlap with OldReg"); + }; + + // Iterate through (possibly several) operands to DBG_VALUEs and update + // each. For DBG_PHIs, only one operand will be present. + for (MachineInstr *MI : Users) { + if (MI->isDebugValue()) { + for (auto &Op : MI->debug_operands()) + UpdateOp(Op); + assert(MI->hasDebugOperandForReg(NewReg) && + "Expected debug value to have some overlap with OldReg"); + } else if (MI->isDebugPHI()) { + UpdateOp(MI->getOperand(0)); + } else { + llvm_unreachable("Non-DBG_VALUE, Non-DBG_PHI debug instr updated"); + } } } diff --git a/llvm/test/DebugInfo/ARM/machine-cp-updates-dbg-reg.mir b/llvm/test/DebugInfo/ARM/machine-cp-updates-dbg-reg.mir index 3e7003d878f3..8e25f8b92d3e 100644 --- a/llvm/test/DebugInfo/ARM/machine-cp-updates-dbg-reg.mir +++ b/llvm/test/DebugInfo/ARM/machine-cp-updates-dbg-reg.mir @@ -3,10 +3,13 @@ ## Ensure that when the destination register of a copy instruction is used by a ## DBG_VALUE/DBG_VALUE_LIST, and then that instruction is deleted during copy ## propagation, the debug use is updated to the source register. +## +## Do the same for DBG_PHI instructions. # CHECK: ![[VAR_V:[0-9]+]] = !DILocalVariable(name: "v" # CHECK-LABEL: body: +# CHECK: DBG_PHI $r0, 1 # CHECK: DBG_VALUE $r0, $noreg, ![[VAR_V]], !DIExpression() # CHECK: DBG_VALUE_LIST ![[VAR_V]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 4, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), $r0, 0 @@ -179,6 +182,7 @@ body: | dead renamable $r1 = LDRi12 undef renamable $r0, 0, 14 /* CC::al */, $noreg :: (volatile load (s32) from `i32* undef`) renamable $r4 = COPY killed renamable $r0 + DBG_PHI $r4, 1 DBG_VALUE $r4, $noreg, !30, !DIExpression(), debug-location !40 DBG_VALUE_LIST !30, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 4, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), $r4, 0, debug-location !40 $r0 = COPY killed renamable $r4 |