Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RegisterCoalescer] Clear instructions not recorded in ErasedInstrs but erased #79820

Merged
merged 5 commits into from
Feb 9, 2024

Conversation

DianQK
Copy link
Member

@DianQK DianQK commented Jan 29, 2024

Fixes #79718. Fixes #71178.

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.

Address sanitizer logs

=================================================================
==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@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

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 29, 2024

@llvm/pr-subscribers-backend-x86
@llvm/pr-subscribers-llvm-regalloc

@llvm/pr-subscribers-backend-loongarch

Author: Quentin Dian (DianQK)

Changes

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() &amp;&amp; "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&amp;, llvm::MachineInstr const*, llvm::Register&amp;, llvm::Register&amp;, unsigned int&amp;, unsigned int&amp;) /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&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/RegisterCoalescer.cpp:1972:11
    #<!-- -->5 0x7efc7fd6dbaa in (anonymous namespace)::RegisterCoalescer::copyCoalesceWorkList(llvm::MutableArrayRef&lt;llvm::MachineInstr*&gt;) /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&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/RegisterCoalescer.cpp:4228:5
    #<!-- -->8 0x7efc7f70f043 in llvm::MachineFunctionPass::runOnFunction(llvm::Function&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:93:13
    #<!-- -->9 0x7efc79d0db54 in llvm::FPPassManager::runOnFunction(llvm::Function&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1445:27
    #<!-- -->10 0x7efc79d260e3 in llvm::FPPassManager::runOnModule(llvm::Module&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1491:16
    #<!-- -->11 0x7efc79d0ea3f in (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1560:27
    #<!-- -->12 0x7efc79d0ea3f in llvm::legacy::PassManagerImpl::run(llvm::Module&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:542:44
    #<!-- -->13 0x55b3617ef9f4 in compileModule(char**, llvm::LLVMContext&amp;) /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@<!-- -->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&lt;llvm::MallocAllocator, 4096ul, 4096ul, 128ul&gt;::StartNewSlab() /home/dianqk/llvm/llvm-project/llvm/include/llvm/Support/Allocator.h:339:42
    #<!-- -->4 0x7efc7f03e5c1 in llvm::BumpPtrAllocatorImpl&lt;llvm::MallocAllocator, 4096ul, 4096ul, 128ul&gt;::Allocate(unsigned long, llvm::Align) /home/dianqk/llvm/llvm-project/llvm/include/llvm/Support/Allocator.h:195:5
    #<!-- -->5 0x7efc7f6e22bb in llvm::BumpPtrAllocatorImpl&lt;llvm::MallocAllocator, 4096ul, 4096ul, 128ul&gt;::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&lt;llvm::MachineInstr, 72ul, 8ul&gt;::Allocate&lt;llvm::MachineInstr, llvm::BumpPtrAllocatorImpl&lt;llvm::MallocAllocator, 4096ul, 4096ul, 128ul&gt;&gt;(llvm::BumpPtrAllocatorImpl&lt;llvm::MallocAllocator, 4096ul, 4096ul, 128ul&gt;&amp;) /home/dianqk/llvm/llvm-project/llvm/include/llvm/Support/Recycler.h:89:57
    #<!-- -->7 0x7efc7f6e22bb in llvm::MachineFunction::CreateMachineInstr(llvm::MCInstrDesc const&amp;, llvm::DebugLoc, bool) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/MachineFunction.cpp:399:35
    #<!-- -->8 0x7efc838dcb8a in llvm::BuildMI(llvm::MachineBasicBlock&amp;, llvm::MachineInstrBundleIterator&lt;llvm::MachineInstr, false&gt;, llvm::MIMetadata const&amp;, llvm::MCInstrDesc const&amp;, llvm::Register) /home/dianqk/llvm/llvm-project/llvm/include/llvm/CodeGen/MachineInstrBuilder.h:386:25
    #<!-- -->9 0x7efc838fbe8e in llvm::TargetInstrInfo::createPHISourceCopy(llvm::MachineBasicBlock&amp;, llvm::MachineInstrBundleIterator&lt;llvm::MachineInstr, false&gt;, llvm::DebugLoc const&amp;, 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&amp;, llvm::MachineInstrBundleIterator&lt;llvm::MachineInstr, false&gt;) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/PHIElimination.cpp:522:28
    #<!-- -->11 0x7efc7fbb6dfe in (anonymous namespace)::PHIElimination::EliminatePHINodes(llvm::MachineFunction&amp;, llvm::MachineBasicBlock&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/PHIElimination.cpp:243:5
    #<!-- -->12 0x7efc7fbb6dfe in (anonymous namespace)::PHIElimination::runOnMachineFunction(llvm::MachineFunction&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/PHIElimination.cpp:198:16
    #<!-- -->13 0x7efc7f70f043 in llvm::MachineFunctionPass::runOnFunction(llvm::Function&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:93:13
    #<!-- -->14 0x7efc79d0db54 in llvm::FPPassManager::runOnFunction(llvm::Function&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1445:27
    #<!-- -->15 0x7efc79d260e3 in llvm::FPPassManager::runOnModule(llvm::Module&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1491:16
    #<!-- -->16 0x7efc79d0ea3f in (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1560:27
    #<!-- -->17 0x7efc79d0ea3f in llvm::legacy::PassManagerImpl::run(llvm::Module&amp;) /home/dianqk/llvm/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:542:44
    #<!-- -->18 0x55b3617ef9f4 in compileModule(char**, llvm::LLVMContext&amp;) /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
=&gt;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>


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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/RegisterCoalescer.cpp (+11-5)
  • (added) llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir (+402)
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
new file mode 100644
index 000000000000000..5e0be0df636b8bf
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir
@@ -0,0 +1,402 @@
+# 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 | 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:             |
+  ; 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
+
+    %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
+
+...

@DianQK DianQK requested a review from aeubanks January 29, 2024 12:58
@bzEq bzEq requested a review from qcolombet January 29, 2024 13:09
ErasedInstrs.erase(CopyMI);
if (ErasedInstrs.erase(CopyMI))
// But we may encounter the instruction again in this iteration.
CurrentErasedInstrs.insert(CopyMI);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we end up with the same copy instruction twice in the worklist?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the debugging results, it looks like removePartialRedundancy changes the contents of the work list.

@arsenm
Copy link
Contributor

arsenm commented Jan 29, 2024

#73519 is potentially another attempt at solving the same issue

@DianQK
Copy link
Member Author

DianQK commented Jan 29, 2024

#73519 is potentially another attempt at solving the same issue

It does seem to be the same issue. I'm not sure which is the better way to handle this. Do you have any more suggestions?

(This PR seems to be missing multiple duplicates?)

@DianQK DianQK requested a review from nikic January 31, 2024 01:02
@DianQK
Copy link
Member Author

DianQK commented Feb 1, 2024

Ping~

Though I know very little about this part. But I think this at least fixes the crash, with no other regressions.

@DianQK
Copy link
Member Author

DianQK commented Feb 4, 2024

@qcolombet @arsenm
Could you continue to review it? Or submit a new fix? Thanks.

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is an easier to understand version of the fix. The test can be cleaned up a bit though.

Can you drop the IR section, delete the registers section, use -run-pass=none -simplify-mir to clean up most of the unnecessary bits?

Also can you add the test from #71178 and #73519

@DianQK
Copy link
Member Author

DianQK commented Feb 8, 2024

Also can you add the test from #71178 and #73519

Hmm, this PR doesn't fix it. This test case isn't stable, and I can't test it with RegisterCoalescer.

@DianQK
Copy link
Member Author

DianQK commented Feb 8, 2024

Also can you add the test from #71178 and #73519

Hmm, this PR doesn't fix it. This test case isn't stable, and I can't test it with RegisterCoalescer.

I think it's a similar but different issue.

@arsenm
Copy link
Contributor

arsenm commented Feb 8, 2024

Also can you add the test from #71178 and #73519

Hmm, this PR doesn't fix it. This test case isn't stable, and I can't test it with RegisterCoalescer.

I think it's a similar but different issue.

I think it's the same; it's from relying on the delete inst pointers from removePartialRedundancy

llvm/lib/CodeGen/RegisterCoalescer.cpp Outdated Show resolved Hide resolved
Progress |= Success;
if (Success || !Again)
MI = nullptr;
}
// Clear instructions not recorded in `ErasedInstrs` but erased.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole thing feels overcomplicated but I don't have any better suggestion

Copy link
Member Author

@DianQK DianQK Feb 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all because we are dancing with dangling pointers.
🔩🔩🔩
🔩💃🔩
🔩🔩🔩

@DianQK
Copy link
Member Author

DianQK commented Feb 9, 2024

Also can you add the test from #71178 and #73519

Hmm, this PR doesn't fix it. This test case isn't stable, and I can't test it with RegisterCoalescer.

I think it's a similar but different issue.

I think it's the same; it's from relying on the delete inst pointers from removePartialRedundancy

I found out why. It's a very specific case.
We erased an instruction in coalesceLocals and then created a new instruction because it was the same address, and we successfully deleted the record at ErasedInstrs. After that, we erased the new instruction again.
Finally, we will lose this record in while (copyCoalesceWorkList(WorkList)) since CurrentErasedInstrs only records one iteration.

@DianQK DianQK changed the title [RegisterCoalescer] Deferring deletion of instructions in ErasedInstrs until the end of an iteration [RegisterCoalescer] Clear instructions not recorded in ErasedInstrs but erased. Feb 9, 2024
@DianQK DianQK changed the title [RegisterCoalescer] Clear instructions not recorded in ErasedInstrs but erased. [RegisterCoalescer] Clear instructions not recorded in ErasedInstrs but erased Feb 9, 2024
@DianQK
Copy link
Member Author

DianQK commented Feb 9, 2024

Thanks for your patience in reviewing.

@DianQK DianQK merged commit 95b14da into llvm:main Feb 9, 2024
3 of 4 checks passed
@DianQK DianQK deleted the register-coalescer branch February 9, 2024 07:29
@DianQK
Copy link
Member Author

DianQK commented Feb 9, 2024

Oops, since #80147 I should rebase.

DianQK added a commit that referenced this pull request Feb 9, 2024
DianQK added a commit that referenced this pull request Feb 9, 2024
@DianQK
Copy link
Member Author

DianQK commented Feb 9, 2024

Oops, since #80147 I should rebase.

Fixed.

llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Feb 9, 2024
… but erased (llvm#79820)

Fixes llvm#79718. Fixes llvm#71178.

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

(cherry picked from commit 95b14da)
llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Feb 9, 2024
… but erased (llvm#79820)

Fixes llvm#79718. Fixes llvm#71178.

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

(cherry picked from commit 95b14da)
Copy link
Collaborator

@qcolombet qcolombet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry guys I'm late to the party.
Finally got time to look closer.
Ultimately I think the issue is we try to maintain a global state whereas the local and non-local worklist are not shared.

In this patch, I feel we are trying to reconstruct which list has been effectively modified and update the other one accordingly.

All in all, I think the complexity is not worth it.
Instead I would recommend that we stop being smart with ErasedInstrs and just remove that call to remove.

If the memory consumption is indeed a problem with ErasedInstrs growing, we can revisit.

@arsenm @DianQK what do you think?

@DianQK
Copy link
Member Author

DianQK commented Feb 14, 2024

Sorry guys I'm late to the party. Finally got time to look closer. Ultimately I think the issue is we try to maintain a global state whereas the local and non-local worklist are not shared.

In this patch, I feel we are trying to reconstruct which list has been effectively modified and update the other one accordingly.

All in all, I think the complexity is not worth it. Instead I would recommend that we stop being smart with ErasedInstrs and just remove that call to remove.

If the memory consumption is indeed a problem with ErasedInstrs growing, we can revisit.

@arsenm @DianQK what do you think?

I agree. ErasedInstrs makes maintenance complicated. I would be concerned that this issue would reappear again due to some sort of input. I think there is a need to redesign a solution.

tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
… but erased (llvm#79820)

Fixes llvm#79718. Fixes llvm#71178.

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

(cherry picked from commit 95b14da)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
… but erased (llvm#79820)

Fixes llvm#79718. Fixes llvm#71178.

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

(cherry picked from commit 95b14da)
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
… but erased (llvm#79820)

Fixes llvm#79718. Fixes llvm#71178.

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

(cherry picked from commit 95b14da)
@pointhex pointhex mentioned this pull request May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants