[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