[llvm] [MachineSink] Fix missing sinks along critical edges (PR #97618)
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 11 13:01:40 PDT 2024
mshockwave wrote:
Hi @alexfh thanks for discovering this bug. I think you just found a really interesting issue caused by an old bug.
Here is the MachineFunction right before the crash:
```
# Machine code for function _f: IsSSA, TracksLiveness
Function Live Ins: $x0 in %6, $w1 in %7
bb.0.entry:
successors: %bb.1(0x30000000), %bb.2(0x50000000); %bb.1(37.50%), %bb.2(62.50%)
liveins: $x0, $w1
%7:gpr32 = COPY $w1
%6:gpr64common = COPY $x0
%8:gpr32 = COPY %7:gpr32
%9:gpr32 = LDRSBWui %6:gpr64common, 0 :: (load (s8) from %ir.project)
%11:gpr64all = IMPLICIT_DEF
%10:gpr64 = INSERT_SUBREG %11:gpr64all(tied-def 0), %9:gpr32, %subreg.sub_32
%12:gpr64sp = ANDXri killed %10:gpr64, 4103
%0:gpr64 = COPY %12:gpr64sp
%1:gpr64all = COPY %12:gpr64sp
TBZW %9:gpr32, 31, %bb.2
B %bb.1
bb.1.cond.true.i9.i.i:
; predecessors: %bb.0
successors: %bb.5(0x40000000), %bb.4(0x40000000); %bb.5(50.00%), %bb.4(50.00%)
%13:gpr64 = LDRXui %6:gpr64common, 0 :: (load (s64) from %ir.project)
%2:gpr64 = COPY %13:gpr64
TBNZW %8:gpr32, 0, %bb.5
B %bb.4
bb.2._ZNKSt3__u12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE16__get_short_sizeEv.exit.i.i.i:
; predecessors: %bb.0
successors: %bb.5(0x40000000), %bb.4(0x40000000); %bb.5(50.00%), %bb.4(50.00%)
%18:gpr64 = COPY %1:gpr64all
TBNZW %8:gpr32, 0, %bb.5
B %bb.4
bb.3.for.cond.i:
; predecessors: %bb.4
successors: %bb.5(0x04000000), %bb.4(0x7c000000); %bb.5(3.12%), %bb.4(96.88%)
%15:gpr64sp = ADDXri %5:gpr64sp, 1, 0
%4:gpr64all = COPY %15:gpr64sp
CBZX %19:gpr64, %bb.5
B %bb.4
bb.4.for.body.i:
; predecessors: %bb.1, %bb.2, %bb.3
successors: %bb.6(0x04000000), %bb.3(0x7c000000); %bb.6(3.12%), %bb.3(96.88%)
%19:gpr64 = PHI %19:gpr64, %bb.3, %2:gpr64, %bb.1, %18:gpr64, %bb.2
%5:gpr64sp = PHI %6:gpr64common, %bb.1, %4:gpr64all, %bb.3, %6:gpr64common, %bb.2
%14:gpr32 = LDRBBui %5:gpr64sp, 0 :: (load (s8) from %ir.__first.sroa.0.010.i)
CBZW killed %14:gpr32, %bb.6
B %bb.3
bb.5.common.ret:
; predecessors: %bb.1, %bb.2, %bb.3, %bb.6, %bb.7
RET_ReallyLR
bb.6.cond.false:
; predecessors: %bb.4
successors: %bb.5(0x30000000), %bb.7(0x50000000); %bb.5(37.50%), %bb.7(62.50%)
%16:gpr32 = COPY %1.sub_32:gpr64all
TBNZW killed %16:gpr32, 7, %bb.5
B %bb.7
bb.7.cond.end.i.thread.i.i72:
; predecessors: %bb.6
successors: %bb.5(0x80000000); %bb.5(100.00%)
STRXui %0:gpr64, %6:gpr64common, 0 :: (store (s64) into %ir.project)
B %bb.5
# End machine code for function _f.
```
MachineSink thinks it's profitable to sink `%0:gpr64 = COPY %12:gpr64sp` from bb.0 to bb.4 after the critical edge between those two blocks are broken. But bb.4 is not even a successor of bb.0, hence the assertion failure.
The reason it thought bb.0 - bb.4 is even a critical edge in the first place is because bb.4 is the `SuccToSinkTo` block w.r.t the current block (i.e. bb.0) returned from `FindSuccToSinkTo`. MachineSink consider the edge between current block and `SuccToSinkTo` a critical edge if `SuccToSinkTo` has more than one predecessor -- which is true for most of the cases. However, `FindSuccToSinkTo` not only return a (immediate) successor block but also look beyond to all descendant blocks: https://github.com/llvm/llvm-project/blob/43024a465120315464490ca9c6074553cd968089/llvm/lib/CodeGen/MachineSink.cpp#L1202 . Which is why `FindSuccToSinkTo` return bb.4 despite the fact that bb.4 is not even a successor of bb.0. (The reason I said this is an old bug because the logics of looking into descendant blocks has been there for a long time)
I think a simple fix on `isLegalToBreakCriticalEdge` to reject cases like this should fix the issue. I'm cooking a patch right now...
https://github.com/llvm/llvm-project/pull/97618
More information about the llvm-commits
mailing list