[llvm] [DebugInfo][RegisterCoalescer] Drop DBG_VALUEs with unsupported register class (PR #143132)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 6 06:01:34 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-regalloc

@llvm/pr-subscribers-backend-x86

Author: Vladislav Dzhidzhoev (dzhidzhoev)

<details>
<summary>Changes</summary>

After the register inflation, some registers may be changed to a type that is not supported by DBG_VALUE. It may happen because MachineRegisterInfo::recomputeRegClass() doesn't take DBG_VALUEs into account.

MachineRegisterInfo::recomputeRegClass() was changed to compute constraints for a set of all uses and a set of non-dbg uses. If the computed classes don't match, it considers encountered DBG_VALUEs as illegal and returns a list of them for further processing.

RegisterCoalescer marks such unsupported DBG_VALUEs as undefs.

The reason for this change is a crash I encountered while trying to build compiler-rt builtins on macOS with CMAKE_BUILD_TYPE=RelWithDebInfo, LLVM_TARGETS_TO_BUILD=all, LLVM_ENABLE_ASSERTIONS=On, LLVM_ENABLE_EXPENSIVE_CHECKS=On.

Here's the error message:
```
*** Bad machine code: Invalid register class for subregister index ***
- function:    __addsf3
- basic block: %bb.29 if.then116.i (0x121015050) [4368B;4752B)
- instruction: DBG_VALUE %22.sub_8bit:gr32, $noreg, !"sticky", !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value), debug-location !261; llvm-project/compiler-rt/lib/builtins/fp_add_impl.inc:0 @[ llvm-project/compiler-rt/lib/builtins/addsf3.c:16:59 ] line no:136
- operand 0:   %22.sub_8bit:gr32
Register class GR32 does not fully support subreg index sub_8bit
fatal error: error in backend: Found 1 machine code errors.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /Users/vlad/Developer/llvm/llvm-build-native/bin/clang --target=arm64-apple-darwin24.5.0 -O2 -g -DNDEBUG -arch i386 -isysroot /Applications/Xcode-16.4.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk -isysroot /Applications/Xcode-16.4.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk -mmacosx-version-min=10.7 -fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer -DHAS_ASM_LSE -Werror=format-nonliteral -DDONT_DEFINE_EPRINTF -arch i386 -MD -MT CMakeFiles/clang_rt.builtins_i386_osx.dir/addsf3.c.o -MF CMakeFiles/clang_rt.builtins_i386_osx.dir/addsf3.c.o.d -o CMakeFiles/clang_rt.builtins_i386_osx.dir/addsf3.c.o -c /Users/vlad/Developer/llvm/llvm-project/compiler-rt/lib/builtins/addsf3.c
1.	<eof> parser at end of file
2.	Code generation
3.	Running pass 'Function Pass Manager' on module '/Users/vlad/Developer/llvm/llvm-project/compiler-rt/lib/builtins/addsf3.c'.
4.	Running pass 'Verify generated machine code' on function '@<!-- -->__addsf3'
 #<!-- -->0 0x00000001092c90d0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/Users/vlad/Developer/llvm/llvm-build-native/bin/clang-21+0x104c990d0)
...
 #<!-- -->7 0x0000000109238b58 llvm::report_fatal_error(llvm::Twine const&, bool) (/Users/vlad/Developer/llvm/llvm-build-native/bin/clang-21+0x104c08b58)
 #<!-- -->8 0x000000010671082c llvm::initializeMachineVerifierLegacyPassPass(llvm::PassRegistry&) (/Users/vlad/Developer/llvm/llvm-build-native/bin/clang-21+0x1020e082c)
 #<!-- -->9 0x0000000106711708 (anonymous namespace)::MachineVerifierLegacyPass::runOnMachineFunction(llvm::MachineFunction&) (/Users/vlad/Developer/llvm/llvm-build-native/bin/clang-21+0x1020e1708)
 #<!-- -->10 0x0000000106650068 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/Users/vlad/Developer/llvm/llvm-build-native/bin/clang-21+0x102020068)
...
clang: error: clang frontend command failed with exit code 70 (use -v to see invocation)
clang version 21.0.0git (git@<!-- -->github.com:llvm/llvm-project.git 351f15ba82f861cd7441f613db8317c353ca79c2)
Target: i386-apple-darwin24.5.0
Thread model: posix
InstalledDir: /Users/vlad/Developer/llvm/llvm-build-native/bin
Build config: +assertions, +expensive-checks
clang: note: diagnostic msg:
```

Full cmake config and build command:
```
cmake \
  -G Ninja \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DCMAKE_INSTALL_PREFIX="native" \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=On \
  -DLLVM_CCACHE_BUILD=On \
  -DLLVM_ENABLE_ASSERTIONS=On \
  -DLLVM_ENABLE_BINDINGS=Off \
  -DLLVM_ENABLE_CURL=On \
  -DLLVM_ENABLE_PROJECTS="llvm;clang;lldb;lld;cross-project-tests" \
  -DLLVM_ENABLE_REVERSE_ITERATION=On \
  -DLLVM_TARGETS_TO_BUILD=all \
  -DLLVM_LIT_ARGS="-sv -j 10" \
  -DLLDB_ENABLE_PYTHON=On \
  -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;compiler-rt;libunwind" \
  -DLLVM_ENABLE_EXPENSIVE_CHECKS=On \
  -DDEFAULT_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" \
  ../llvm-project/llvm
ninja runtimes/builtins-stamps/builtins-build
```

---
Full diff: https://github.com/llvm/llvm-project/pull/143132.diff


5 Files Affected:

- (modified) llvm/include/llvm/CodeGen/MachineRegisterInfo.h (+5-2) 
- (modified) llvm/lib/CodeGen/LiveRangeEdit.cpp (+1-1) 
- (modified) llvm/lib/CodeGen/MachineRegisterInfo.cpp (+23-7) 
- (modified) llvm/lib/CodeGen/RegisterCoalescer.cpp (+7-1) 
- (added) llvm/test/CodeGen/X86/coalesce-dbg-value.mir (+149) 


``````````diff
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index e579dc53ab061..354bfe87c35ff 100644
--- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -728,12 +728,15 @@ class MachineRegisterInfo {
 
   /// recomputeRegClass - Try to find a legal super-class of Reg's register
   /// class that still satisfies the constraints from the instructions using
-  /// Reg.  Returns true if Reg was upgraded.
+  /// Reg.
+  /// If Reg was upgraded, returns true and a list of debug value instructions
+  /// that became illegal after upgrade.
   ///
   /// This method can be used after constraints have been removed from a
   /// virtual register, for example after removing instructions or splitting
   /// the live range.
-  LLVM_ABI bool recomputeRegClass(Register Reg);
+  LLVM_ABI std::pair<bool, SmallVector<MachineInstr *, 8>>
+  recomputeRegClass(Register Reg);
 
   /// createVirtualRegister - Create and return a new virtual register in the
   /// function with the specified register class.
diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp
index a3858efbdc5e1..867b107a85731 100644
--- a/llvm/lib/CodeGen/LiveRangeEdit.cpp
+++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp
@@ -494,7 +494,7 @@ void LiveRangeEdit::calculateRegClassAndHint(MachineFunction &MF,
                                              VirtRegAuxInfo &VRAI) {
   for (unsigned I = 0, Size = size(); I < Size; ++I) {
     LiveInterval &LI = LIS.getInterval(get(I));
-    if (MRI.recomputeRegClass(LI.reg()))
+    if (MRI.recomputeRegClass(LI.reg()).first)
       LLVM_DEBUG({
         const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
         dbgs() << "Inflated " << printReg(LI.reg()) << " to "
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index b7135251781ad..bc34c7e0afb13 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -118,28 +118,44 @@ MachineRegisterInfo::constrainRegAttrs(Register Reg,
   return true;
 }
 
-bool
+std::pair<bool, SmallVector<MachineInstr *, 8>>
 MachineRegisterInfo::recomputeRegClass(Register Reg) {
   const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
   const TargetRegisterClass *OldRC = getRegClass(Reg);
   const TargetRegisterInfo *TRI = getTargetRegisterInfo();
+  // Largest legal super-class for non-debug uses.
   const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC, *MF);
+  // Largest legal super-class for all uses.
+  const TargetRegisterClass *NewRCWithDebug = NewRC;
+  SmallVector<MachineInstr *, 8> DebugInsns;
 
   // Stop early if there is no room to grow.
   if (NewRC == OldRC)
-    return false;
+    return {false, {}};
 
   // Accumulate constraints from all uses.
-  for (MachineOperand &MO : reg_nodbg_operands(Reg)) {
-    // Apply the effect of the given operand to NewRC.
+  for (MachineOperand &MO : reg_operands(Reg)) {
     MachineInstr *MI = MO.getParent();
     unsigned OpNo = &MO - &MI->getOperand(0);
-    NewRC = MI->getRegClassConstraintEffect(OpNo, NewRC, TII, TRI);
+    if (MO.isDebug()) {
+      DebugInsns.push_back(MI);
+    } else {
+      // Apply the effect of the given operand to NewRC.
+      NewRC = MI->getRegClassConstraintEffect(OpNo, NewRC, TII, TRI);
+    }
+    NewRCWithDebug =
+        MI->getRegClassConstraintEffect(OpNo, NewRCWithDebug, TII, TRI);
     if (!NewRC || NewRC == OldRC)
-      return false;
+      return {false, {}};
   }
   setRegClass(Reg, NewRC);
-  return true;
+
+  // Check if DBG_VALUEs are still legal.
+  if (NewRCWithDebug == NewRC)
+    return {true, {}};
+
+  // DBG_VALUEs can't use the new class and should be changed.
+  return {true, DebugInsns};
 }
 
 Register MachineRegisterInfo::createIncompleteVirtualRegister(StringRef Name) {
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index 2d25f097348af..97110332b4ef7 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -4335,11 +4335,17 @@ bool RegisterCoalescer::run(MachineFunction &fn) {
   for (Register Reg : InflateRegs) {
     if (MRI->reg_nodbg_empty(Reg))
       continue;
-    if (MRI->recomputeRegClass(Reg)) {
+
+    auto [Recomputed, IllegalDbgValues] = MRI->recomputeRegClass(Reg);
+    if (Recomputed) {
       LLVM_DEBUG(dbgs() << printReg(Reg) << " inflated to "
                         << TRI->getRegClassName(MRI->getRegClass(Reg)) << '\n');
       ++NumInflated;
 
+      // Mark undef debug value instructions that became illegal.
+      for (MachineInstr *MI : IllegalDbgValues)
+        MI->setDebugValueUndef();
+
       LiveInterval &LI = LIS->getInterval(Reg);
       if (LI.hasSubRanges()) {
         // If the inflated register class does not support subregisters anymore
diff --git a/llvm/test/CodeGen/X86/coalesce-dbg-value.mir b/llvm/test/CodeGen/X86/coalesce-dbg-value.mir
new file mode 100644
index 0000000000000..fc0037296e606
--- /dev/null
+++ b/llvm/test/CodeGen/X86/coalesce-dbg-value.mir
@@ -0,0 +1,149 @@
+# Check if DBG_VALUE is set to undef if it doesn't support an updated
+# register class.
+# Input was generated from compiler-rt/lib/builtins/adddf3.c.
+
+# RUN: llc -mtriple i386-apple-macosx10.7.0 -run-pass=register-coalescer %s -o - | FileCheck %s
+
+# CHECK-NOT: DBG_VALUE.*sub_8bit
+# CHECK: DBG_VALUE $noreg
+# CHECK-NOT: DBG_VALUE.*sub_8bit
+
+--- |
+  target datalayout = "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:128-n8:16:32-S128"
+  target triple = "i386-apple-macosx10.7.0"
+  
+  define i32 @foo(i1 %i) {
+  entry:
+    %shl = or i32 0, 1
+    br i1 %i, label %if.then, label %if.end
+  
+  if.then:                                     ; preds = %entry
+    %cmp = icmp ne i32 %shl, 0
+      #dbg_value(i1 %cmp, !4, !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value), !12)
+    %conv127.i = zext i1 %cmp to i32
+    %or = or i32 %shl, %conv127.i
+    br label %if.end
+  
+  if.end:                                      ; preds = %if.then, %entry
+    %res = phi i32 [ %or, %if.then ], [ 1, %entry ]
+    ret i32 %res
+  }
+  
+  !llvm.module.flags = !{!0}
+  !llvm.dbg.cu = !{!1}
+  
+  !0 = !{i32 2, !"Debug Info Version", i32 3}
+  !1 = distinct !DICompileUnit(language: DW_LANG_C11, file: !2, producer: "clang version 21.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !3, retainedTypes: !3)
+  !2 = !DIFile(filename: "foo.c", directory: "/")
+  !3 = !{}
+  !4 = !DILocalVariable(name: "sticky", scope: !5, file: !6, line: 136, type: !10)
+  !5 = distinct !DILexicalBlock(scope: !7, file: !6, line: 132, column: 23)
+  !6 = !DIFile(filename: "bar.inc", directory: "/")
+  !7 = distinct !DILexicalBlock(scope: !8, file: !6, line: 132, column: 7)
+  !8 = distinct !DISubprogram(name: "bar", scope: !6, file: !6, line: 17, type: !9, scopeLine: 17, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !3)
+  !9 = distinct !DISubroutineType(types: !3)
+  !10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11)
+  !11 = !DIBasicType(name: "_Bool", size: 8, encoding: DW_ATE_boolean)
+  !12 = !DILocation(line: 0, scope: !5, inlinedAt: !13)
+  !13 = distinct !DILocation(line: 16, column: 59, scope: !14)
+  !14 = distinct !DISubprogram(name: "foo", scope: !2, file: !2, line: 16, type: !15, scopeLine: 16, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, retainedNodes: !3)
+  !15 = !DISubroutineType(types: !3)
+...
+---
+name:            foo
+alignment:       16
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+failedISel:      false
+tracksRegLiveness: true
+hasWinCFI:       false
+noPhis:          true
+isSSA:           false
+noVRegs:         false
+hasFakeUses:     false
+callsEHReturn:   false
+callsUnwindInit: false
+hasEHContTarget: false
+hasEHScopes:     false
+hasEHFunclets:   false
+isOutlined:      false
+debugInstrRef:   false
+failsVerification: false
+tracksDebugUserValues: false
+registers:
+  - { id: 0, class: gr32, preferred-register: '', flags: [  ] }
+  - { id: 1, class: gr32_abcd, preferred-register: '', flags: [  ] }
+  - { id: 2, class: gr32, preferred-register: '', flags: [  ] }
+  - { id: 3, class: gr32, preferred-register: '', flags: [  ] }
+  - { id: 4, class: gr8, preferred-register: '', flags: [  ] }
+  - { id: 5, class: gr32_abcd, preferred-register: '', flags: [  ] }
+  - { id: 6, class: gr32_abcd, preferred-register: '', flags: [  ] }
+  - { id: 7, class: gr32, preferred-register: '', flags: [  ] }
+liveins:         []
+frameInfo:
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    4
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  functionContext: ''
+  maxCallFrameSize: 4294967295
+  cvBytesOfCalleeSavedRegisters: 0
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  hasTailCall:     false
+  isCalleeSavedInfoValid: false
+  localFrameSize:  0
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:
+  - { id: 0, type: default, offset: 0, size: 1, alignment: 16, stack-id: default, 
+      isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, 
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+stack:           []
+entry_values:    []
+callSites:       []
+debugValueSubstitutions: []
+constants:       []
+machineFunctionInfo:
+  amxProgModel:    None
+body:             |
+  bb.0.entry:
+    successors: %bb.1(0x40000000), %bb.3(0x40000000)
+  
+    %3:gr32 = MOV32ri 1
+    TEST8mi %fixed-stack.0, 1, $noreg, 0, $noreg, 1, implicit-def $eflags :: (load (s8) from %fixed-stack.0, align 16)
+    JCC_1 %bb.1, 5, implicit killed $eflags
+  
+  bb.3:
+    successors: %bb.2(0x80000000)
+  
+    %7:gr32 = COPY killed %3
+    JMP_1 %bb.2
+  
+  bb.1.if.then:
+    successors: %bb.2(0x80000000)
+  
+    %6:gr32_abcd = MOV32r0 implicit-def dead $eflags
+    TEST32rr %3, %3, implicit-def $eflags
+    %4:gr8 = SETCCr 5, implicit killed $eflags
+    DBG_VALUE %4, $noreg, !4, !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value),  debug-location !12
+    %5:gr32_abcd = COPY killed %6
+    %5.sub_8bit:gr32_abcd = COPY killed %4
+    %1:gr32_abcd = COPY killed %5
+    %1:gr32_abcd = OR32rr %1, killed %3, implicit-def dead $eflags
+    %7:gr32 = COPY killed %1
+  
+  bb.2.if.end:
+    %2:gr32 = COPY killed %7
+    $eax = COPY killed %2
+    RET 0, killed $eax
+...

``````````

</details>


https://github.com/llvm/llvm-project/pull/143132


More information about the llvm-commits mailing list