Global ISel for DBG_VALUE

Hi,

I am modifying a Codegen pass which need get register class for virtual register. However some debug case fails because the virtual register of DBG_VALUE don’t have a register class after global instruction selection. Is it a bug of global isel? If it is expected behavious, I may use getRegClassOrNull() and check if it returns nullptr. This issue can be duplicated with “llc -mtriple=aarch64 test/DebugInfo/Generic/two-cus-from-same-file.ll -O0 -o - -print-after-all”. We can see the register class of register operand of DBG_VALUE is not set.

*** IR Dump After AArch64 Instruction Selection (amdgpu-isel) ***:

Machine code for function main: IsSSA, TracksLiveness, Legalized, RegBankSelected, Selected

Function Live Ins: $w0, $x1

bb.1.entry:
liveins: $w0, $x1
DBG_VALUE %0:, $noreg, !“argc”, !DIExpression(), debug-location !19; foo.c:11:14 line no:11
DBG_VALUE %1:
, $noreg, !“argv”, !DIExpression(DW_OP_deref, DW_OP_deref), debug-location !20; foo.c:11:26 line no:11
ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp, debug-location !21; foo.c:12:3
%4:gpr64common = MOVaddr target-flags(aarch64-page) @str1, target-flags(aarch64-pageoff, aarch64-nc) @str1, debug-location !DILocation(line: 0, scope: !22); foo.c:0
$x0 = COPY %4:gpr64common, debug-location !21; foo.c:12:3
BL @puts, <regmask $fp $lr $b8 $b9 $b10 $b11 $b12 $b13 $b14 $b15 $d8 $d9 $d10 $d11 $d12 $d13 $d14 $d15 $h8 $h9 $h10 $h11 $h12 $h13 $h14 $h15 $s8 $s9 $s10 $s11 $s12 $s13 $s14 and 53 more…>, implicit-def $lr, implicit $sp, implicit $x0, implicit-def $w0, debug-location !21; foo.c:12:3
ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp, debug-location !21; foo.c:12:3
ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp, debug-location !23; foo.c:13:3
BL @foo, <regmask $fp $lr $b8 $b9 $b10 $b11 $b12 $b13 $b14 $b15 $d8 $d9 $d10 $d11 $d12 $d13 $d14 $d15 $h8 $h9 $h10 $h11 $h12 $h13 $h14 $h15 $s8 $s9 $s10 $s11 $s12 $s13 $s14 and 53 more…>, implicit-def $lr, implicit $sp, debug-location !23; foo.c:13:3
ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp, debug-location !23; foo.c:13:3
%5:gpr32 = COPY $wzr
$w0 = COPY %5:gpr32, debug-location !24; foo.c:14:3
RET_ReallyLR implicit $w0, debug-location !24; foo.c:14:3

Thanks
Yuanke

All virtual registers with uses, debug or not, need to be constrained while passing through the selector. The AArch64 implementation (and likely all of them) of select is not bothering to do this.

I believe this is falling through unprocessed here.

The registers need to be constrained with RBI.constrainGenericRegister, the same as COPY or any other instruction

Thanks, @arsenm. I try to change register bank to register class with below patch, but it seems the register bank is nullptr. So I wonder where should we set the register bank for DBG_VALUE.

diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 9a65687735fe..0f02f5694611 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2382,6 +2382,31 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
     if (I.isCopy())
       return selectCopy(I, TII, MRI, TRI, RBI);

+    if (I.isNonListDebugValue() && I.getOperand(0).isReg()) {
+      const Register Reg = I.getOperand(0).getReg();
+      const LLT Ty = MRI.getType(Reg);
+
+      const RegClassOrRegBank &RegClassOrBank =
+        MRI.getRegClassOrRegBank(Reg);
+
+      const TargetRegisterClass *RC
+        = RegClassOrBank.dyn_cast<const TargetRegisterClass *>();
+      if (!RC) {
+        if (!Ty.isValid()) {
+          LLVM_DEBUG(dbgs() << "DBG_VALUE operand has no type, not a gvreg?\n");
+          return false;
+        }
+        const RegisterBank &RB = *RegClassOrBank.get<const RegisterBank *>();
+        RC = getRegClassForTypeOnBank(Ty, RB);
+        if (!RC) {
+          LLVM_DEBUG(dbgs() << "DBG_VALUE operand has unexpected size/bank\n");
+          return false;
+        }
+      }
+
+      return RBI.constrainGenericRegister(Reg, *RC, MRI);
+    }
+
     return true;
   }

RegBankSelect also should have set the bank on the register

Thank you. I create a patch at ⚙ D129037 [globalisel] Select register bank for DBG_VALUE.