[llvm] [RegisterCoalescer] Deferring deletion of instructions in `ErasedInstrs` until the end of an iteration (PR #79820)

Quentin Dian via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 29 04:58:17 PST 2024


https://github.com/DianQK created https://github.com/llvm/llvm-project/pull/79820

Fixes #79718.

The same instructions may exist in an iteration. We cannot immediately delete instructions in `ErasedInstrs`.

Here's my debug logs, you can see that the instructions that are about to be processed have appeared in the work list ahead of time.

```
BB: foo:preheader work list:
BB: foo:bb3 work list:
BB: foo:bb4 work list:
%52:gpr = COPY %7:gpr in foo:bb4

BB: foo:bb2 work list:
%52:gpr = COPY %7:gpr in foo:bb4

BB: foo:bb6 work list:
%52:gpr = COPY %7:gpr in foo:bb4

BB: foo:loopexit work list:
%48:gpr = COPY %44:gpr in foo:bb4

BB: foo:bb5 work list:
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge // Instruction changes!

BB: foo:BB3 work list:
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge

BB: foo:preheader.preheader work list:
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge

BB: foo:BB6 work list:
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge
%43:gpr = COPY %45:gpr in foo:BB6

BB: foo:bb3.bb5_crit_edge work list:
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge // Same instruction!
%43:gpr = COPY %45:gpr in foo:BB6
%44:gpr = COPY %41:gpr in foo:bb3.bb5_crit_edge
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge // Same instruction!

BB: foo:bb1 work list:
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge
%43:gpr = COPY %45:gpr in foo:BB6
%44:gpr = COPY %41:gpr in foo:bb3.bb5_crit_edge
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge
%0:gpr = COPY %43:gpr in foo:bb1

BB: foo:start work list:
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge
%43:gpr = COPY %45:gpr in foo:BB6
%44:gpr = COPY %41:gpr in foo:bb3.bb5_crit_edge
%45:gpr = COPY %43:gpr in foo:bb3.bb5_crit_edge
%0:gpr = COPY %43:gpr in foo:bb1

llc: llvm-project/llvm/include/llvm/CodeGen/MachineOperand.h:370: Register llvm::MachineOperand::getReg() const: Assertion `isReg() && "This is not a register operand!"' failed.
```

This change is probably due to `removePartialRedundancy`.


<details><summary>Address sanitizer logs</summary>
<p>

```
=================================================================
==200228==ERROR: AddressSanitizer: use-after-poison on address 0x521000054728 at pc 0x7efc7fd597ad bp 0x7ffd3d4d1d10 sp 0x7ffd3d4d1d08
READ of size 8 at 0x521000054728 thread T0
    #0 0x7efc7fd597ac in llvm::MachineInstr::getOpcode() const /home/dianqk/llvm/llvm-project/llvm/include/llvm/CodeGen/MachineInstr.h:543:39
    #1 0x7efc7fd597ac in llvm::MachineInstr::isCopy() const /home/dianqk/llvm/llvm-project/llvm/include/llvm/CodeGen/MachineInstr.h:1392:12
    #2 0x7efc7fd597ac in isMoveInstr(llvm::TargetRegisterInfo const&, llvm::MachineInstr const*, llvm::Register&, llvm::Register&, unsigned int&, unsigned int&) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/RegisterCoalescer.cpp:419:13
    #3 0x7efc7fd57b06 in llvm::CoalescerPair::setRegisters(llvm::MachineInstr const*) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/RegisterCoalescer.cpp:459:8
    #4 0x7efc7fd7039c in (anonymous namespace)::RegisterCoalescer::joinCopy(llvm::MachineInstr*, bool&) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/RegisterCoalescer.cpp:1972:11
    #5 0x7efc7fd6dbaa in (anonymous namespace)::RegisterCoalescer::copyCoalesceWorkList(llvm::MutableArrayRef<llvm::MachineInstr*>) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/RegisterCoalescer.cpp:3995:20
    #6 0x7efc7fd5fcde in (anonymous namespace)::RegisterCoalescer::joinAllIntervals() /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/RegisterCoalescer.cpp:4156:10
    #7 0x7efc7fd5fcde in (anonymous namespace)::RegisterCoalescer::runOnMachineFunction(llvm::MachineFunction&) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/RegisterCoalescer.cpp:4228:5
    #8 0x7efc7f70f043 in llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:93:13
    #9 0x7efc79d0db54 in llvm::FPPassManager::runOnFunction(llvm::Function&) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1445:27
    #10 0x7efc79d260e3 in llvm::FPPassManager::runOnModule(llvm::Module&) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1491:16
    #11 0x7efc79d0ea3f in (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1560:27
    #12 0x7efc79d0ea3f in llvm::legacy::PassManagerImpl::run(llvm::Module&) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:542:44
    #13 0x55b3617ef9f4 in compileModule(char**, llvm::LLVMContext&) /home/dianqk/llvm/llvm-project/llvm/tools/llc/llc.cpp:743:8
    #14 0x55b3617e8c9f in main /home/dianqk/llvm/llvm-project/llvm/tools/llc/llc.cpp:412:22
    #15 0x7efc7823f0cd in __libc_start_call_main (/nix/store/p3jshbwxiwifm1py0yq544fmdyy98j8a-glibc-2.38-27/lib/libc.so.6+0x280cd) (BuildId: 155a1ecbcb77ab0451b398b8a9c19795d8e7b047)
    #16 0x7efc7823f188 in __libc_start_main at GLIBC_2.2.5 (/nix/store/p3jshbwxiwifm1py0yq544fmdyy98j8a-glibc-2.38-27/lib/libc.so.6+0x28188) (BuildId: 155a1ecbcb77ab0451b398b8a9c19795d8e7b047)
    #17 0x55b3616af774 in _start (/home/dianqk/llvm/llvm-project/build/bin/llc+0x97774)

0x521000054728 is located 2600 bytes inside of 4096-byte region [0x521000053d00,0x521000054d00)
allocated by thread T0 here:
    #0 0x55b3617e2050 in operator new(unsigned long, std::align_val_t) (/home/dianqk/llvm/llvm-project/build/bin/llc+0x1ca050)
    #1 0x7efc78c4142d in llvm::allocate_buffer(unsigned long, unsigned long) /home/dianqk/llvm/llvm-project/llvm/lib/Support/MemAlloc.cpp:16:10
    #2 0x7efc7f03e5c1 in llvm::MallocAllocator::Allocate(unsigned long, unsigned long) /home/dianqk/llvm/llvm-project/llvm/include/llvm/Support/AllocatorBase.h:92:12
    #3 0x7efc7f03e5c1 in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::StartNewSlab() /home/dianqk/llvm/llvm-project/llvm/include/llvm/Support/Allocator.h:339:42
    #4 0x7efc7f03e5c1 in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::Allocate(unsigned long, llvm::Align) /home/dianqk/llvm/llvm-project/llvm/include/llvm/Support/Allocator.h:195:5
    #5 0x7efc7f6e22bb in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::Allocate(unsigned long, unsigned long) /home/dianqk/llvm/llvm-project/llvm/include/llvm/Support/Allocator.h:209:12
    #6 0x7efc7f6e22bb in llvm::MachineInstr* llvm::Recycler<llvm::MachineInstr, 72ul, 8ul>::Allocate<llvm::MachineInstr, llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>>(llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>&) /home/dianqk/llvm/llvm-project/llvm/include/llvm/Support/Recycler.h:89:57
    #7 0x7efc7f6e22bb in llvm::MachineFunction::CreateMachineInstr(llvm::MCInstrDesc const&, llvm::DebugLoc, bool) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/MachineFunction.cpp:399:35
    #8 0x7efc838dcb8a in llvm::BuildMI(llvm::MachineBasicBlock&, llvm::MachineInstrBundleIterator<llvm::MachineInstr, false>, llvm::MIMetadata const&, llvm::MCInstrDesc const&, llvm::Register) /home/dianqk/llvm/llvm-project/llvm/include/llvm/CodeGen/MachineInstrBuilder.h:386:25
    #9 0x7efc838fbe8e in llvm::TargetInstrInfo::createPHISourceCopy(llvm::MachineBasicBlock&, llvm::MachineInstrBundleIterator<llvm::MachineInstr, false>, llvm::DebugLoc const&, llvm::Register, unsigned int, llvm::Register) const /home/dianqk/llvm/llvm-project/llvm/include/llvm/CodeGen/TargetInstrInfo.h:2048:12
    #10 0x7efc7fbc09c6 in (anonymous namespace)::PHIElimination::LowerPHINode(llvm::MachineBasicBlock&, llvm::MachineInstrBundleIterator<llvm::MachineInstr, false>) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/PHIElimination.cpp:522:28
    #11 0x7efc7fbb6dfe in (anonymous namespace)::PHIElimination::EliminatePHINodes(llvm::MachineFunction&, llvm::MachineBasicBlock&) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/PHIElimination.cpp:243:5
    #12 0x7efc7fbb6dfe in (anonymous namespace)::PHIElimination::runOnMachineFunction(llvm::MachineFunction&) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/PHIElimination.cpp:198:16
    #13 0x7efc7f70f043 in llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:93:13
    #14 0x7efc79d0db54 in llvm::FPPassManager::runOnFunction(llvm::Function&) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1445:27
    #15 0x7efc79d260e3 in llvm::FPPassManager::runOnModule(llvm::Module&) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1491:16
    #16 0x7efc79d0ea3f in (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1560:27
    #17 0x7efc79d0ea3f in llvm::legacy::PassManagerImpl::run(llvm::Module&) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:542:44
    #18 0x55b3617ef9f4 in compileModule(char**, llvm::LLVMContext&) /home/dianqk/llvm/llvm-project/llvm/tools/llc/llc.cpp:743:8
    #19 0x55b3617e8c9f in main /home/dianqk/llvm/llvm-project/llvm/tools/llc/llc.cpp:412:22
    #20 0x7efc7823f0cd in __libc_start_call_main (/nix/store/p3jshbwxiwifm1py0yq544fmdyy98j8a-glibc-2.38-27/lib/libc.so.6+0x280cd) (BuildId: 155a1ecbcb77ab0451b398b8a9c19795d8e7b047)

SUMMARY: AddressSanitizer: use-after-poison /home/dianqk/llvm/llvm-project/llvm/include/llvm/CodeGen/MachineInstr.h:543:39 in llvm::MachineInstr::getOpcode() const
Shadow bytes around the buggy address:
  0x521000054480: 00 00 00 00 00 00 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x521000054500: f7 00 00 00 00 00 00 00 00 f7 f7 f7 f7 f7 f7 f7
  0x521000054580: f7 f7 f7 f7 00 00 00 00 00 00 00 00 f7 f7 f7 f7
  0x521000054600: f7 f7 f7 f7 f7 f7 f7 00 00 00 00 00 00 00 00 f7
  0x521000054680: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 00 00 00 00 00 00
=>0x521000054700: 00 00 f7 f7 f7[f7]f7 f7 f7 f7 f7 f7 f7 00 00 00
  0x521000054780: 00 00 00 00 00 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x521000054800: 00 00 00 00 00 00 00 00 f7 f7 f7 f7 f7 f7 f7 f7
  0x521000054880: f7 f7 f7 00 00 00 00 00 00 00 00 f7 00 00 00 00
  0x521000054900: 00 00 00 00 00 f7 00 00 00 00 00 00 00 00 f7 00
  0x521000054980: 00 00 00 00 00 00 00 00 f7 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==200228==ABORTING
```

</p>
</details> 

>From 6528a77b15b3b9728f574e637e9c05d6d1e6b058 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Mon, 29 Jan 2024 18:58:04 +0800
Subject: [PATCH 1/2] Pre-commit test cases

---
 .../register-coalescer-crash-pr79718.mir      | 317 ++++++++++++++++++
 1 file changed, 317 insertions(+)
 create mode 100644 llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir

diff --git a/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir b/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir
new file mode 100644
index 000000000000000..13381318eee02ca
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir
@@ -0,0 +1,317 @@
+# XFAIL: *
+# RUN: llc -o - %s -mtriple=loongarch64 \
+# RUN:  -run-pass=register-coalescer -join-liveintervals=1 -join-splitedges=0 2>&1 | FileCheck %s
+
+--- |
+  source_filename = "register-coalescer-crash-pr79718.ll"
+  target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
+  target triple = "loongarch64"
+
+  define void @foo(ptr nocapture writeonly %0, i1 %1, i1 %2, i1 %3, i1 %4) local_unnamed_addr #0 {
+  start:
+    br label %bb1
+  bb1:                                              ; preds = %bb6, %start
+    %5 = phi i64 [ 0, %start ], [ %20, %bb6 ]
+    %6 = phi i64 [ 0, %start ], [ %21, %bb6 ]
+    %7 = phi i64 [ undef, %start ], [ %23, %bb6 ]
+    br label %bb2
+
+  bb2:                                              ; preds = %bb6, %bb1
+    %8 = phi i64 [ %5, %bb1 ], [ %20, %bb6 ]
+    %9 = phi i64 [ %6, %bb1 ], [ %21, %bb6 ]
+    %10 = phi i64 [ %6, %bb1 ], [ %22, %bb6 ]
+    %11 = phi i64 [ %7, %bb1 ], [ %23, %bb6 ]
+    br i1 %1, label %loopexit, label %preheader.preheader
+
+  preheader.preheader:                              ; preds = %bb2
+    br label %preheader
+
+  preheader:                                        ; preds = %bb4, %preheader.preheader
+    %12 = phi i64 [ %14, %bb4 ], [ %10, %preheader.preheader ]
+    %13 = load volatile { i64, i64 }, ptr null, align 4294967296
+    br i1 %2, label %bb3, label %bb5
+
+  bb3:                                              ; preds = %preheader
+    br i1 %3, label %bb4, label %bb3.bb5_crit_edge
+
+  bb4:                                              ; preds = %bb3
+    %14 = add i64 %12, 1
+    br i1 %4, label %loopexit, label %preheader
+
+  loopexit:                                         ; preds = %bb4, %bb2
+    %15 = phi i64 [ %9, %bb2 ], [ %14, %bb4 ]
+    %16 = phi i64 [ %10, %bb2 ], [ %14, %bb4 ]
+    store i8 0, ptr %0, align 1
+    br label %bb6
+
+  bb3.bb5_crit_edge:                                ; preds = %bb3
+    %17 = add i64 %12, 1
+    br label %bb5
+
+  bb5:                                              ; preds = %preheader, %bb3.bb5_crit_edge
+    %18 = phi i64 [ 1, %bb3.bb5_crit_edge ], [ 0, %preheader ]
+    %19 = phi i64 [ %17, %bb3.bb5_crit_edge ], [ %11, %preheader ]
+    store i64 0, ptr %0, align 8
+    br label %bb6
+
+  bb6:                                              ; preds = %bb5, %loopexit
+    %20 = phi i64 [ %19, %bb5 ], [ %8, %loopexit ]
+    %21 = phi i64 [ %18, %bb5 ], [ %15, %loopexit ]
+    %22 = phi i64 [ %18, %bb5 ], [ %16, %loopexit ]
+    %23 = phi i64 [ %19, %bb5 ], [ %11, %loopexit ]
+    %24 = icmp eq i64 %5, 1
+    br i1 %24, label %bb2, label %bb1
+  }
+
+  attributes #0 = { nofree norecurse noreturn nounwind }
+
+...
+---
+name:            foo
+alignment:       32
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+failedISel:      false
+tracksRegLiveness: true
+hasWinCFI:       false
+callsEHReturn:   false
+callsUnwindInit: false
+hasEHCatchret:   false
+hasEHScopes:     false
+hasEHFunclets:   false
+isOutlined:      false
+debugInstrRef:   false
+failsVerification: false
+tracksDebugUserValues: false
+registers:
+  - { id: 0, class: gpr, preferred-register: '' }
+  - { id: 1, class: gpr, preferred-register: '' }
+  - { id: 2, class: gpr, preferred-register: '' }
+  - { id: 3, class: gpr, preferred-register: '' }
+  - { id: 4, class: gpr, preferred-register: '' }
+  - { id: 5, class: gpr, preferred-register: '' }
+  - { id: 6, class: gpr, preferred-register: '' }
+  - { id: 7, class: gpr, preferred-register: '' }
+  - { id: 8, class: gpr, preferred-register: '' }
+  - { id: 9, class: gpr, preferred-register: '' }
+  - { id: 10, class: gpr, preferred-register: '' }
+  - { id: 11, class: gpr, preferred-register: '' }
+  - { id: 12, class: gpr, preferred-register: '' }
+  - { id: 13, class: gpr, preferred-register: '' }
+  - { id: 14, class: gpr, preferred-register: '' }
+  - { id: 15, class: gpr, preferred-register: '' }
+  - { id: 16, class: gpr, preferred-register: '' }
+  - { id: 17, class: gpr, preferred-register: '' }
+  - { id: 18, class: gpr, preferred-register: '' }
+  - { id: 19, class: gpr, preferred-register: '' }
+  - { id: 20, class: gpr, preferred-register: '' }
+  - { id: 21, class: gpr, preferred-register: '' }
+  - { id: 22, class: gpr, preferred-register: '' }
+  - { id: 23, class: gpr, preferred-register: '' }
+  - { id: 24, class: gpr, preferred-register: '' }
+  - { id: 25, class: gpr, preferred-register: '' }
+  - { id: 26, class: gpr, preferred-register: '' }
+  - { id: 27, class: gpr, preferred-register: '' }
+  - { id: 28, class: gpr, preferred-register: '' }
+  - { id: 29, class: gpr, preferred-register: '' }
+  - { id: 30, class: gpr, preferred-register: '' }
+  - { id: 31, class: gpr, preferred-register: '' }
+  - { id: 32, class: gpr, preferred-register: '' }
+  - { id: 33, class: gpr, preferred-register: '' }
+  - { id: 34, class: gpr, preferred-register: '' }
+  - { id: 35, class: gpr, preferred-register: '' }
+  - { id: 36, class: gpr, preferred-register: '' }
+  - { id: 37, class: gpr, preferred-register: '' }
+  - { id: 38, class: gpr, preferred-register: '' }
+  - { id: 39, class: gpr, preferred-register: '' }
+  - { id: 40, class: gpr, preferred-register: '' }
+  - { id: 41, class: gpr, preferred-register: '' }
+  - { id: 42, class: gpr, preferred-register: '' }
+  - { id: 43, class: gpr, preferred-register: '' }
+  - { id: 44, class: gpr, preferred-register: '' }
+  - { id: 45, class: gpr, preferred-register: '' }
+  - { id: 46, class: gpr, preferred-register: '' }
+  - { id: 47, class: gpr, preferred-register: '' }
+  - { id: 48, class: gpr, preferred-register: '' }
+  - { id: 49, class: gpr, preferred-register: '' }
+  - { id: 50, class: gpr, preferred-register: '' }
+  - { id: 51, class: gpr, preferred-register: '' }
+  - { id: 52, class: gpr, preferred-register: '' }
+  - { id: 53, class: gpr, preferred-register: '' }
+  - { id: 54, class: gpr, preferred-register: '' }
+  - { id: 55, class: gpr, preferred-register: '' }
+  - { id: 56, class: gpr, preferred-register: '' }
+  - { id: 57, class: gpr, preferred-register: '' }
+  - { id: 58, class: gpr, preferred-register: '' }
+liveins:
+  - { reg: '$r4', virtual-reg: '%18' }
+  - { reg: '$r5', virtual-reg: '%19' }
+  - { reg: '$r6', virtual-reg: '%20' }
+  - { reg: '$r7', virtual-reg: '%21' }
+  - { reg: '$r8', virtual-reg: '%22' }
+frameInfo:
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    1
+  adjustsStack:    false
+  hasCalls:        false
+  stackProtector:  ''
+  functionContext: ''
+  maxCallFrameSize: 4294967295
+  cvBytesOfCalleeSavedRegisters: 0
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  hasTailCall:     false
+  localFrameSize:  0
+  savePoint:       ''
+  restorePoint:    ''
+fixedStack:      []
+stack:           []
+entry_values:    []
+callSites:       []
+debugValueSubstitutions: []
+constants:       []
+machineFunctionInfo: {}
+body:             |
+  bb.0.start:
+    successors: %bb.1(0x80000000)
+    liveins: $r4, $r5, $r6, $r7, $r8
+
+    %22:gpr = COPY killed $r8
+    %21:gpr = COPY killed $r7
+    %20:gpr = COPY killed $r6
+    %19:gpr = COPY killed $r5
+    %18:gpr = COPY killed $r4
+    %29:gpr = COPY $r0
+    %27:gpr = COPY killed %29
+    %30:gpr = ANDI killed %19, 1
+    %41:gpr = ORI $r0, 1
+    %35:gpr = ANDI killed %20, 1
+    %36:gpr = ANDI killed %21, 1
+    %39:gpr = ANDI killed %22, 1
+    %43:gpr = COPY %27
+    %44:gpr = COPY killed %27
+    %45:gpr = IMPLICIT_DEF
+
+  bb.1.bb1:
+    successors: %bb.2(0x80000000)
+
+    %2:gpr = COPY killed %45
+    %1:gpr = COPY killed %44
+    %0:gpr = COPY killed %43
+    %46:gpr = COPY %0
+    %47:gpr = COPY %1
+    %48:gpr = COPY killed %1
+    %49:gpr = COPY killed %2
+
+  bb.2.bb2:
+    successors: %bb.12(0x40000000), %bb.3(0x40000000)
+
+    %6:gpr = COPY killed %49
+    %5:gpr = COPY killed %48
+    %4:gpr = COPY killed %47
+    %3:gpr = COPY killed %46
+    BEQZ %30, %bb.3
+
+  bb.12:
+    successors: %bb.8(0x80000000)
+
+    %51:gpr = COPY killed %4
+    %52:gpr = COPY killed %5
+    PseudoBR %bb.8
+
+  bb.3.preheader.preheader:
+    successors: %bb.4(0x80000000)
+
+    %50:gpr = COPY killed %5
+
+  bb.4.preheader:
+    successors: %bb.6(0x7c000000), %bb.5(0x04000000)
+
+    %7:gpr = COPY killed %50
+    dead %33:gpr = LD_D $r0, 8 :: (volatile load (s64) from `ptr null` + 8, basealign 4294967296)
+    dead %34:gpr = LD_D $r0, 0 :: (volatile load (s64) from `ptr null`, align 4294967296)
+    BNEZ %35, %bb.6
+
+  bb.5:
+    successors: %bb.10(0x80000000)
+
+    %32:gpr = COPY $r0
+    %31:gpr = COPY killed %32
+    %53:gpr = COPY killed %31
+    %54:gpr = COPY killed %6
+    PseudoBR %bb.10
+
+  bb.6.bb3:
+    successors: %bb.7(0x7c000000), %bb.9(0x04000000)
+
+    BEQZ %36, %bb.9
+    PseudoBR %bb.7
+
+  bb.7.bb4:
+    successors: %bb.8(0x04000000), %bb.4(0x7c000000)
+
+    %8:gpr = ADDI_D killed %7, 1
+    %50:gpr = COPY %8
+    %51:gpr = COPY %8
+    %52:gpr = COPY killed %8
+    BEQZ %39, %bb.4
+    PseudoBR %bb.8
+
+  bb.8.loopexit:
+    successors: %bb.11(0x80000000)
+
+    %10:gpr = COPY killed %52
+    %9:gpr = COPY killed %51
+    %40:gpr = COPY $r0
+    ST_B killed %40, %18, 0 :: (store (s8) into %ir.0)
+    %55:gpr = COPY killed %3
+    %56:gpr = COPY killed %9
+    %57:gpr = COPY killed %10
+    %58:gpr = COPY killed %6
+    PseudoBR %bb.11
+
+  bb.9.bb3.bb5_crit_edge:
+    successors: %bb.10(0x80000000)
+
+    %42:gpr = ADDI_D killed %7, 1
+    %53:gpr = COPY %41
+    %54:gpr = COPY killed %42
+
+  bb.10.bb5:
+    successors: %bb.11(0x80000000)
+
+    %13:gpr = COPY killed %54
+    %12:gpr = COPY killed %53
+    %38:gpr = COPY $r0
+    ST_D killed %38, %18, 0 :: (store (s64) into %ir.0)
+    %55:gpr = COPY %13
+    %56:gpr = COPY %12
+    %57:gpr = COPY killed %12
+    %58:gpr = COPY killed %13
+
+  bb.11.bb6:
+    successors: %bb.2(0x7c000000), %bb.1(0x04000000)
+
+    %17:gpr = COPY killed %58
+    %16:gpr = COPY killed %57
+    %15:gpr = COPY killed %56
+    %14:gpr = COPY killed %55
+    %43:gpr = COPY %14
+    %44:gpr = COPY %15
+    %45:gpr = COPY %17
+    %46:gpr = COPY killed %14
+    %47:gpr = COPY killed %15
+    %48:gpr = COPY killed %16
+    %49:gpr = COPY killed %17
+    BEQ %0, %41, %bb.2
+    PseudoBR %bb.1
+
+...

>From 9cb9ad2d4cb30013c17a2220587e56a927058757 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Mon, 29 Jan 2024 19:20:35 +0800
Subject: [PATCH 2/2] [RegisterCoalescer] Deferring deletion of instructions in
 `ErasedInstrs` until the end of an iteration

---
 llvm/lib/CodeGen/RegisterCoalescer.cpp        | 16 ++--
 .../register-coalescer-crash-pr79718.mir      | 89 ++++++++++++++++++-
 2 files changed, 98 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index cbb1a74049fbd7b..d3125fba67206b2 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -236,7 +236,8 @@ namespace {
     /// was successfully coalesced away. If it is not currently possible to
     /// coalesce this interval, but it may be possible if other things get
     /// coalesced, then it returns true by reference in 'Again'.
-    bool joinCopy(MachineInstr *CopyMI, bool &Again);
+    bool joinCopy(MachineInstr *CopyMI, bool &Again,
+                  SmallPtrSetImpl<MachineInstr *> &CurrentErasedInstrs);
 
     /// Attempt to join these two intervals.  On failure, this
     /// returns false.  The output "SrcInt" will not have been modified, so we
@@ -1964,7 +1965,9 @@ void RegisterCoalescer::setUndefOnPrunedSubRegUses(LiveInterval &LI,
   LIS->shrinkToUses(&LI);
 }
 
-bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
+bool RegisterCoalescer::joinCopy(
+    MachineInstr *CopyMI, bool &Again,
+    SmallPtrSetImpl<MachineInstr *> &CurrentErasedInstrs) {
   Again = false;
   LLVM_DEBUG(dbgs() << LIS->getInstructionIndex(*CopyMI) << '\t' << *CopyMI);
 
@@ -2156,7 +2159,9 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
   // CopyMI has been erased by joinIntervals at this point. Remove it from
   // ErasedInstrs since copyCoalesceWorkList() won't add a successful join back
   // to the work list. This keeps ErasedInstrs from growing needlessly.
-  ErasedInstrs.erase(CopyMI);
+  if (ErasedInstrs.erase(CopyMI))
+    // But we may encounter the instruction again in this iteration.
+    CurrentErasedInstrs.insert(CopyMI);
 
   // Rewrite all SrcReg operands to DstReg.
   // Also update DstReg operands to include DstIdx if it is set.
@@ -3982,17 +3987,18 @@ void RegisterCoalescer::lateLiveIntervalUpdate() {
 bool RegisterCoalescer::
 copyCoalesceWorkList(MutableArrayRef<MachineInstr*> CurrList) {
   bool Progress = false;
+  SmallPtrSet<MachineInstr *, 4> CurrentErasedInstrs;
   for (MachineInstr *&MI : CurrList) {
     if (!MI)
       continue;
     // Skip instruction pointers that have already been erased, for example by
     // dead code elimination.
-    if (ErasedInstrs.count(MI)) {
+    if (ErasedInstrs.count(MI) || CurrentErasedInstrs.count(MI)) {
       MI = nullptr;
       continue;
     }
     bool Again = false;
-    bool Success = joinCopy(MI, Again);
+    bool Success = joinCopy(MI, Again, CurrentErasedInstrs);
     Progress |= Success;
     if (Success || !Again)
       MI = nullptr;
diff --git a/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir b/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir
index 13381318eee02ca..5e0be0df636b8bf 100644
--- a/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir
+++ b/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir
@@ -1,6 +1,6 @@
-# XFAIL: *
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
 # RUN: llc -o - %s -mtriple=loongarch64 \
-# RUN:  -run-pass=register-coalescer -join-liveintervals=1 -join-splitedges=0 2>&1 | FileCheck %s
+# RUN:  -run-pass=register-coalescer -join-liveintervals=1 -join-splitedges=0 | FileCheck %s
 
 --- |
   source_filename = "register-coalescer-crash-pr79718.ll"
@@ -180,6 +180,91 @@ debugValueSubstitutions: []
 constants:       []
 machineFunctionInfo: {}
 body:             |
+  ; CHECK-LABEL: name: foo
+  ; CHECK: bb.0.start:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT:   liveins: $r4, $r5, $r6, $r7, $r8
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gpr = COPY $r8
+  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:gpr = COPY $r7
+  ; CHECK-NEXT:   [[COPY2:%[0-9]+]]:gpr = COPY $r6
+  ; CHECK-NEXT:   [[COPY3:%[0-9]+]]:gpr = COPY $r5
+  ; CHECK-NEXT:   [[COPY4:%[0-9]+]]:gpr = COPY $r4
+  ; CHECK-NEXT:   [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY3]], 1
+  ; CHECK-NEXT:   [[ORI:%[0-9]+]]:gpr = ORI $r0, 1
+  ; CHECK-NEXT:   [[ANDI1:%[0-9]+]]:gpr = ANDI [[COPY2]], 1
+  ; CHECK-NEXT:   [[ANDI2:%[0-9]+]]:gpr = ANDI [[COPY1]], 1
+  ; CHECK-NEXT:   [[ANDI3:%[0-9]+]]:gpr = ANDI [[COPY]], 1
+  ; CHECK-NEXT:   [[COPY5:%[0-9]+]]:gpr = COPY $r0
+  ; CHECK-NEXT:   [[COPY6:%[0-9]+]]:gpr = COPY $r0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1.bb1:
+  ; CHECK-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY7:%[0-9]+]]:gpr = COPY [[COPY5]]
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2.bb2:
+  ; CHECK-NEXT:   successors: %bb.3(0x40000000), %bb.4(0x40000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   BEQZ [[ANDI]], %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   successors: %bb.9(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   PseudoBR %bb.9
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.4.preheader.preheader:
+  ; CHECK-NEXT:   successors: %bb.5(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.5.preheader:
+  ; CHECK-NEXT:   successors: %bb.7(0x7c000000), %bb.6(0x04000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   dead [[LD_D:%[0-9]+]]:gpr = LD_D $r0, 8 :: (volatile load (s64) from `ptr null` + 8, basealign 4294967296)
+  ; CHECK-NEXT:   dead [[LD_D1:%[0-9]+]]:gpr = LD_D $r0, 0 :: (volatile load (s64) from `ptr null`, align 4294967296)
+  ; CHECK-NEXT:   BNEZ [[ANDI1]], %bb.7
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.6:
+  ; CHECK-NEXT:   successors: %bb.11(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY6:%[0-9]+]]:gpr = COPY $r0
+  ; CHECK-NEXT:   PseudoBR %bb.11
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.7.bb3:
+  ; CHECK-NEXT:   successors: %bb.8(0x7c000000), %bb.10(0x04000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   BEQZ [[ANDI2]], %bb.10
+  ; CHECK-NEXT:   PseudoBR %bb.8
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.8.bb4:
+  ; CHECK-NEXT:   successors: %bb.9(0x04000000), %bb.5(0x7c000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY6:%[0-9]+]]:gpr = ADDI_D [[COPY6]], 1
+  ; CHECK-NEXT:   BEQZ [[ANDI3]], %bb.5
+  ; CHECK-NEXT:   PseudoBR %bb.9
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.9.loopexit:
+  ; CHECK-NEXT:   successors: %bb.12(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   ST_B $r0, [[COPY4]], 0 :: (store (s8) into %ir.0)
+  ; CHECK-NEXT:   PseudoBR %bb.12
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.10.bb3.bb5_crit_edge:
+  ; CHECK-NEXT:   successors: %bb.11(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY5:%[0-9]+]]:gpr = ADDI_D [[COPY6]], 1
+  ; CHECK-NEXT:   [[COPY6:%[0-9]+]]:gpr = COPY [[ORI]]
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.11.bb5:
+  ; CHECK-NEXT:   successors: %bb.12(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   ST_D $r0, [[COPY4]], 0 :: (store (s64) into %ir.0)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.12.bb6:
+  ; CHECK-NEXT:   successors: %bb.2(0x7c000000), %bb.1(0x04000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   BEQ [[COPY7]], [[ORI]], %bb.2
+  ; CHECK-NEXT:   PseudoBR %bb.1
   bb.0.start:
     successors: %bb.1(0x80000000)
     liveins: $r4, $r5, $r6, $r7, $r8



More information about the llvm-commits mailing list