Skip to content

Commit

Permalink
[RegisterCoalescer] Clear instructions not recorded in ErasedInstrs
Browse files Browse the repository at this point in the history
… but erased (#79820)

Fixes #79718. Fixes #71178.

The same instructions may exist in an iteration. We cannot immediately
delete instructions in `ErasedInstrs`.
  • Loading branch information
DianQK authored Feb 9, 2024
1 parent b2cd50d commit 95b14da
Show file tree
Hide file tree
Showing 3 changed files with 338 additions and 5 deletions.
27 changes: 22 additions & 5 deletions llvm/lib/CodeGen/RegisterCoalescer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -3982,21 +3987,33 @@ 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;
}
// Clear instructions not recorded in `ErasedInstrs` but erased.
if (!CurrentErasedInstrs.empty()) {
for (MachineInstr *&MI : CurrList) {
if (MI && CurrentErasedInstrs.count(MI))
MI = nullptr;
}
for (MachineInstr *&MI : WorkList) {
if (MI && CurrentErasedInstrs.count(MI))
MI = nullptr;
}
}
return Progress;
}

Expand Down
213 changes: 213 additions & 0 deletions llvm/test/CodeGen/LoongArch/register-coalescer-crash-pr79718.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# 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

---
name: foo
tracksRegLiveness: true
body: |
; CHECK-LABEL: name: foo
; CHECK: bb.0:
; 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:
; CHECK-NEXT: successors: %bb.2(0x80000000)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY7:%[0-9]+]]:gpr = COPY [[COPY5]]
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; 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:
; CHECK-NEXT: successors: %bb.5(0x80000000)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.5:
; CHECK-NEXT: successors: %bb.7(0x7c000000), %bb.6(0x04000000)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: dead [[LD_D:%[0-9]+]]:gpr = LD_D $r0, 8
; CHECK-NEXT: dead [[LD_D1:%[0-9]+]]:gpr = LD_D $r0, 0
; 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:
; 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:
; 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:
; CHECK-NEXT: successors: %bb.12(0x80000000)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: ST_B $r0, [[COPY4]], 0
; CHECK-NEXT: PseudoBR %bb.12
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.10:
; 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:
; CHECK-NEXT: successors: %bb.12(0x80000000)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: ST_D $r0, [[COPY4]], 0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.12:
; 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:
liveins: $r4, $r5, $r6, $r7, $r8
%0:gpr = COPY killed $r8
%1:gpr = COPY killed $r7
%2:gpr = COPY killed $r6
%3:gpr = COPY killed $r5
%4:gpr = COPY killed $r4
%5:gpr = COPY $r0
%6:gpr = COPY killed %5
%7:gpr = ANDI killed %3, 1
%8:gpr = ORI $r0, 1
%9:gpr = ANDI killed %2, 1
%10:gpr = ANDI killed %1, 1
%11:gpr = ANDI killed %0, 1
%12:gpr = COPY %6
%13:gpr = COPY killed %6
%14:gpr = IMPLICIT_DEF
bb.1:
%15:gpr = COPY killed %14
%16:gpr = COPY killed %13
%17:gpr = COPY killed %12
%18:gpr = COPY %17
%19:gpr = COPY %16
%20:gpr = COPY killed %16
%21:gpr = COPY killed %15
bb.2:
successors: %bb.3, %bb.4
%22:gpr = COPY killed %21
%23:gpr = COPY killed %20
%24:gpr = COPY killed %19
%25:gpr = COPY killed %18
BEQZ %7, %bb.4
bb.3:
%26:gpr = COPY killed %24
%27:gpr = COPY killed %23
PseudoBR %bb.9
bb.4:
%28:gpr = COPY killed %23
bb.5:
successors: %bb.7(0x7c000000), %bb.6(0x04000000)
%29:gpr = COPY killed %28
dead %30:gpr = LD_D $r0, 8
dead %31:gpr = LD_D $r0, 0
BNEZ %9, %bb.7
bb.6:
%32:gpr = COPY $r0
%33:gpr = COPY killed %32
%34:gpr = COPY killed %33
%35:gpr = COPY killed %22
PseudoBR %bb.11
bb.7:
successors: %bb.8(0x7c000000), %bb.10(0x04000000)
BEQZ %10, %bb.10
PseudoBR %bb.8
bb.8:
successors: %bb.9(0x04000000), %bb.5(0x7c000000)
%36:gpr = ADDI_D killed %29, 1
%28:gpr = COPY %36
%26:gpr = COPY %36
%27:gpr = COPY killed %36
BEQZ %11, %bb.5
PseudoBR %bb.9
bb.9:
%37:gpr = COPY killed %27
%38:gpr = COPY killed %26
%39:gpr = COPY $r0
ST_B killed %39, %4, 0
%40:gpr = COPY killed %25
%41:gpr = COPY killed %38
%42:gpr = COPY killed %37
%43:gpr = COPY killed %22
PseudoBR %bb.12
bb.10:
%44:gpr = ADDI_D killed %29, 1
%34:gpr = COPY %8
%35:gpr = COPY killed %44
bb.11:
%45:gpr = COPY killed %35
%46:gpr = COPY killed %34
%47:gpr = COPY $r0
ST_D killed %47, %4, 0
%40:gpr = COPY %45
%41:gpr = COPY %46
%42:gpr = COPY killed %46
%43:gpr = COPY killed %45
bb.12:
successors: %bb.2(0x7c000000), %bb.1(0x04000000)
%48:gpr = COPY killed %43
%49:gpr = COPY killed %42
%50:gpr = COPY killed %41
%51:gpr = COPY killed %40
%12:gpr = COPY %51
%13:gpr = COPY %50
%14:gpr = COPY %48
%18:gpr = COPY killed %51
%19:gpr = COPY killed %50
%20:gpr = COPY killed %49
%21:gpr = COPY killed %48
BEQ %17, %8, %bb.2
PseudoBR %bb.1
...
103 changes: 103 additions & 0 deletions llvm/test/CodeGen/X86/PR71178-register-coalescer-crash.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
; RUN: llc < %s -mtriple=x86_64 -- | FileCheck %s

define i32 @h(i1 %arg, i32 %arg1) {
; CHECK-LABEL: h:
; CHECK: # %bb.0: # %bb
; CHECK-NEXT: movl $1, %eax
; CHECK-NEXT: movabsq $9166129423, %rcx # imm = 0x22258090F
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: jmp .LBB0_1
; CHECK-NEXT: .p2align 4, 0x90
; CHECK-NEXT: .LBB0_9: # %bb18
; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: testb $1, %dil
; CHECK-NEXT: jne .LBB0_10
; CHECK-NEXT: .LBB0_1: # %bb4
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: testq %rdx, %rdx
; CHECK-NEXT: jne .LBB0_2
; CHECK-NEXT: # %bb.7: # %bb16
; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: testb $1, %dil
; CHECK-NEXT: jne .LBB0_9
; CHECK-NEXT: # %bb.8: # %bb17
; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: movq %rcx, %rdx
; CHECK-NEXT: jmp .LBB0_9
; CHECK-NEXT: .LBB0_2: # %bb9
; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: testb $1, %dil
; CHECK-NEXT: testb $1, %dil
; CHECK-NEXT: je .LBB0_4
; CHECK-NEXT: # %bb.3: # %bb13
; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: .LBB0_4: # %bb14
; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: cmpl $1, %esi
; CHECK-NEXT: je .LBB0_1
; CHECK-NEXT: # %bb.5: # %bb14
; CHECK-NEXT: movl %eax, %r8d
; CHECK-NEXT: testl %esi, %esi
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: jne .LBB0_6
; CHECK-NEXT: .LBB0_10: # %bb22
; CHECK-NEXT: retq
; CHECK-NEXT: .LBB0_6: # %bb22.loopexit1
; CHECK-NEXT: movl %r8d, %eax
; CHECK-NEXT: retq
bb:
br label %bb2

bb2: ; preds = %bb14, %bb
%i = phi i64 [ %i5, %bb14 ], [ 0, %bb ]
%i3 = phi i32 [ %i15, %bb14 ], [ 1, %bb ]
br label %bb4

bb4: ; preds = %bb18, %bb2
%i5 = phi i64 [ %i19, %bb18 ], [ %i, %bb2 ]
%i6 = phi i64 [ %i20, %bb18 ], [ %i, %bb2 ]
%i7 = phi i32 [ 0, %bb18 ], [ %i3, %bb2 ]
%i8 = icmp eq i64 %i6, 0
br i1 %i8, label %bb16, label %bb9

bb9: ; preds = %bb4
br i1 %arg, label %bb12, label %bb10

bb10: ; preds = %bb9
%i11 = sdiv i64 0, 0
br label %bb12

bb12: ; preds = %bb10, %bb9
br i1 %arg, label %bb13, label %bb14

bb13: ; preds = %bb12
br label %bb14

bb14: ; preds = %bb13, %bb12
%i15 = phi i32 [ 0, %bb13 ], [ %i7, %bb12 ]
switch i32 %arg1, label %bb22 [
i32 0, label %bb21
i32 1, label %bb2
]

bb16: ; preds = %bb4
br i1 %arg, label %bb18, label %bb17

bb17: ; preds = %bb16
br label %bb18

bb18: ; preds = %bb17, %bb16
%i19 = phi i64 [ 9166129423, %bb17 ], [ %i5, %bb16 ]
%i20 = phi i64 [ 9166129423, %bb17 ], [ %i6, %bb16 ]
br i1 %arg, label %bb22, label %bb4

bb21: ; preds = %bb14
br label %bb22

bb22: ; preds = %bb21, %bb18, %bb14
%i23 = phi i32 [ %arg1, %bb21 ], [ %i15, %bb14 ], [ 0, %bb18 ]
ret i32 %i23
}

0 comments on commit 95b14da

Please sign in to comment.