Alex Susu via llvm-dev
2017-Jul-14 09:57 UTC
[llvm-dev] Strange assertion error in RegisterCoalescer.cpp - "Missing recursion" - related to bundles needed for predicated blocks
Hello.
I get a "Missing recursion" assertion error in
RegisterCoalescer.cpp when using
bundles (bundles created but not finalized) such as:
3760B %vreg186<def,dead> = EQ_H %vreg163, %vreg65
* NOP_BPF 1; dbg:test.c:11:21
* %vreg187<def,tied1> = WHEREEQ
%vreg186<internal,tied0>
* %vreg188<def,tied1> = NOP_BITCONVERT_WH
%vreg11<tied0>
* %vreg189<def,tied3> = ORV_SPECIAL_H %vreg185,
%vreg185, %vreg79<tied0>
* %vreg190<def,tied1> = END_WHERE
%vreg189<internal,tied0>
// Bundle has finished. Now we COPY using the def of vreg190 created inside
the bundle
3776B %vreg191<def> = COPY %vreg190
3792B %vreg191<def,tied1> = NOP_BITCONVERT_HW
%vreg191<tied0>
The error I get in the RegisterCoalescer.cpp pass for the above code is:
3776B %vreg191<def> = COPY %vreg190
Considering merging to MSA128H with %vreg190 in %vreg191
RHS = %vreg190 [3760r,3776r:0) 0 at 3760r
LHS = %vreg191 [3776r,3792r:0)[3792r,3808r:1) 0 at 3776r 1
at 3792r
llc: /llvm/lib/CodeGen/RegisterCoalescer.cpp:2261: void
{anonymous}::JoinVals::computeAssignment(unsigned int,
{anonymous}::JoinVals&): Assertion
`Other.Vals[V.OtherVNI->id].isAnalyzed() && "Missing
recursion"' failed.
The error is given because I (the NOP_BITCONVERT_HW instruction) use
outside of the
bundle a vreg (virtual register) defined in the bundle and the
TwoAddressInstructionPass
creates a COPY instruction outside of the bundle just before the use, but then
the
RegisterCoalescer pass does NOT really know to handle a COPY using a vreg
defined inside a
bundle.
Similarly, another bundle triggering the same error and the following
instructions:
3696B %vreg181<def,dead> = EQ_H %vreg180, %vreg86
* NOP_BPF 1; dbg:test.c:11:21
* %vreg182<def,tied1> = WHEREEQ
%vreg181<internal,tied0>
* %vreg183<def,tied3> = SUBV_SPECIAL_H %vreg65,
%vreg78, %vreg78<tied0>
* %vreg79<def,tied3> = SUBCV_SPECIAL_H %vreg65,
%vreg179, %vreg77<tied0>
* %vreg184<def,tied1> = END_WHERE
%vreg79<internal,tied0>
// Bundle has finished. Pasting following instructions:
[...]
3856B %vreg189<def> = COPY %vreg79 // We COPY the def of
vreg79 created
inside the bundle
3872B %vreg189<def,tied3> = ORV_SPECIAL_H %vreg185, %vreg185,
%vreg189<tied0>
Here, I get a similar error from RegisterCoalescer:
3856B %vreg189<def> = COPY %vreg79; MSA128H:%vreg189,%vreg79
dbg:test.c:11:21
Considering merging to MSA128H with %vreg79 in %vreg189
RHS = %vreg79 [3696r,3856r:0) 0 at 3696r
LHS = %vreg189 [3856r,3872r:0)[3872r,3888r:1) 0 at 3856r 1
at 3872r
llc: /llvm/lib/CodeGen/RegisterCoalescer.cpp:2261: void
{anonymous}::JoinVals::computeAssignment(unsigned int,
{anonymous}::JoinVals&): Assertion
`Other.Vals[V.OtherVNI->id].isAnalyzed() && "Missing
recursion"' failed.
NOTE: I am aware that the ARM back end does something similar to support
its
predicated IT block-predication instruction family in ARM/Thumb2ITBlockPass.cpp.
Basically
this pass is creating a bundle for the predicated "block" of
instructions after the
TwoAddressInstructionPass and RegisterCoalescer passes have already run (before
running
the 2nd scheduling pass), to avoid the scheduler to change the order, etc of the
instructions in this predicated IT block; also Thumb2ITBlockPass moves any
eventual COPY
instructions in the predicated IT block before it.
But the ARM/Thumb2ITBlockPass.cpp does NOT experience the issues I
describe here
because his pass runs after the TwoAddressInstructionPass and RegisterCoalescer
passes,
while I create bundles before them since bundles (created but not finalized, a
small
detail that should not matter I guess) prevent the TwoAddressInstructionPass to
generate
COPY instructions inside the code they pack.
Can somebody help me with this error? (I would like to mention I prefer not
creating
an extra bundle with the instruction with the vreg use to avoid this error.
Also, I can
provide an entire debug output of llc, if required.)
Thank you very much,
Alex
PS: Another rather different possibility to help me address the issue of
avoiding
inserting new instructions in a block of predicated instructions (because such
things
alter the semantics of my program): should we maybe make the
TwoAddressInstructionPass and
RegisterCoalescer passes predication block aware?