From 99d364d1f430f9727eb5d5e71889790f2dcab3e6 Mon Sep 17 00:00:00 2001 From: Daniil Fukalov <1671137+dfukalov@users.noreply.github.com> Date: Mon, 5 Sep 2022 17:07:55 +0300 Subject: [PATCH] [MachineVerifier] Fix crash on early clobbered subreg operands. MachineVerifier tried to checkLivenessAtDef() ignoring it is actually a subreg. The issue was with processing two subregs of the same reg are used in the same instruction (e.g. inline asm): "def early-clobber" and other just "def". Reviewed By: foad Differential Revision: https://reviews.llvm.org/D126661 --- llvm/lib/CodeGen/MachineVerifier.cpp | 14 +++++++-- .../verifier-ec-subreg-liveness.mir | 31 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 llvm/test/MachineVerifier/verifier-ec-subreg-liveness.mir diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index 416fe14868f8..a5aef3b03782 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -2290,8 +2290,18 @@ void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO, bool SubRangeCheck, LaneBitmask LaneMask) { if (const VNInfo *VNI = LR.getVNInfoAt(DefIdx)) { - assert(VNI && "NULL valno is not allowed"); - if (VNI->def != DefIdx) { + // The LR can correspond to the whole reg and its def slot is not obliged + // to be the same as the MO' def slot. E.g. when we check here "normal" + // subreg MO but there is other EC subreg MO in the same instruction so the + // whole reg has EC def slot and differs from the currently checked MO' def + // slot. For example: + // %0 [16e,32r:0) 0@16e L..3 [16e,32r:0) 0@16e L..C [16r,32r:0) 0@16r + // Check that there is an early-clobber def of the same superregister + // somewhere is performed in visitMachineFunctionAfter() + if (((SubRangeCheck || MO->getSubReg() == 0) && VNI->def != DefIdx) || + !SlotIndex::isSameInstr(VNI->def, DefIdx) || + (VNI->def != DefIdx && + (!VNI->def.isEarlyClobber() || !DefIdx.isRegister()))) { report("Inconsistent valno->def", MO, MONum); report_context_liverange(LR); report_context_vreg_regunit(VRegOrUnit); diff --git a/llvm/test/MachineVerifier/verifier-ec-subreg-liveness.mir b/llvm/test/MachineVerifier/verifier-ec-subreg-liveness.mir new file mode 100644 index 000000000000..5f14d577224e --- /dev/null +++ b/llvm/test/MachineVerifier/verifier-ec-subreg-liveness.mir @@ -0,0 +1,31 @@ +# RUN: llc -mtriple amdgcn-amd-amdhsa -run-pass=liveintervals,pipeliner -verify-machineinstrs -o - %s | FileCheck %s +# REQUIRES: amdgpu-registered-target + +# This test checks that the verifier doesn't crash on early clobbered subreg arguments. + +--- +name: sub0 +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0_vgpr1 + + ; CHECK-NOT: *** Bad machine code: Inconsistent valno->def *** + INLINEASM &"", 0 /* attdialect */, 1835019 /* regdef-ec:VGPR_32 */, def undef early-clobber %0.sub0:vreg_64, 1835018 /* regdef:VGPR_32 */, def undef %0.sub1:vreg_64 + FLAT_STORE_DWORDX2 $vgpr0_vgpr1, %0, 0, 0, implicit $exec, implicit $flat_scr :: (store (s64)) + S_ENDPGM 0 + +... +--- +name: sub1 +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0_vgpr1 + + ; CHECK-NOT: *** Bad machine code: Inconsistent valno->def *** + INLINEASM &"", 0 /* attdialect */, 1835018 /* regdef:VGPR_32 */, def undef %0.sub0:vreg_64, 1835019 /* regdef-ec:VGPR_32 */, def undef early-clobber %0.sub1:vreg_64 + FLAT_STORE_DWORDX2 $vgpr0_vgpr1, %0, 0, 0, implicit $exec, implicit $flat_scr :: (store (s64)) + S_ENDPGM 0 + +...