Folks,
I'm running into something which looks like a bug in linearscan allocator. Of
course I can't be 100% sure it's not some unobvious mistake on my part, so
I'd like to hear your opinion.
First, I attach two files -- LLVM asm and the asm for my target. The problem
with assembler is: on line 171 it uses register gr2, which is copied from gr6
above, on line 161. The only predecessor of this basic block is jump on line
90. The problem is that gr6 is not initialized in the interval from the
function entry till the jump.
I also attach the debug dumps from my backend.
The basic block in question is shortcirc_done.1 (line 198 in the log). It
starts with:
Folks,
I'm running into something which looks like a bug in linearscan allocator. Of
course I can't be 100% sure it's not some unobvious mistake on my part, so
I'd like to hear your opinion.
Yes, there's a known bug in the linear scan allocator. It causes a few
of the nightly tests to fail.
I'll defer to the experts on your analysis below, but if you're close to
finding this problem, you might want to talk to Alkis who wrote linear
scan (I think).
First, I attach two files -- LLVM asm and the asm for my target. The problem
with assembler is: on line 171 it uses register gr2, which is copied from gr6
above, on line 161. The only predecessor of this basic block is jump on line
90. The problem is that gr6 is not initialized in the interval from the
function entry till the jump.
Okay, I see the problem. You need to tell the compiler that the
conditional branches are terminators. You're getting code that looks like
this:
I'm guessing that those copies are inserted by the register allocator, and
in particular, that is probably where gr6 is supposed to get it's value.
If you set the isTerminator flag on your 'if <>0 goto LBB11;' things will
probably magically start working for you, as the copies will be inserted
BEFORE the branch instead of after it.
Also, if you haven't already, you might want to teach TargetInstrInfo
that '=' is a move instruction (implement isMoveInstr), so instructinos
like 'gr1 = gr1' will go away and you'll get coallescing.
-Chris
I also attach the debug dumps from my backend.
The basic block in question is shortcirc_done.1 (line 198 in the log). It
starts with:
> First, I attach two files -- LLVM asm and the asm for my target. The
> problem with assembler is: on line 171 it uses register gr2, which is
> copied from gr6 above, on line 161. The only predecessor of this basic
> block is jump on line 90. The problem is that gr6 is not initialized in
> the interval from the function entry till the jump.
Okay, I see the problem. You need to tell the compiler that the
conditional branches are terminators. You're getting code that looks like
this:
I'm guessing that those copies are inserted by the register allocator, and
in particular, that is probably where gr6 is supposed to get it's value.
If you set the isTerminator flag on your 'if <>0 goto LBB11;' things will
probably magically start working for you, as the copies will be inserted
BEFORE the branch instead of after it.
Also, if you haven't already, you might want to teach TargetInstrInfo
that '=' is a move instruction (implement isMoveInstr), so instructinos
like 'gr1 = gr1' will go away and you'll get coallescing.
BTW, is it possible to set some instruction flag, instead of overriding a
function? Something like:
Also, if you do 'tblgen target.td' it will spit out all of the records
to stdout so you can visually inspect them.
> Also, if you haven't already, you might want to teach TargetInstrInfo
> that '=' is a move instruction (implement isMoveInstr), so instructinos
> like 'gr1 = gr1' will go away and you'll get coallescing.
BTW, is it possible to set some instruction flag, instead of overriding a
function? Something like:
let isMove = 1 in
def MOVE :.....
That would make sense, but no not currently. If you wanted to teach
it how to do that (similar to the isTerminator functionality), it would be
a great patch.
Also, if you do 'tblgen target.td' it will spit out all of the records
to stdout so you can visually inspect them.
> > Also, if you haven't already, you might want to teach TargetInstrInfo
> > that '=' is a move instruction (implement isMoveInstr), so instructinos
> > like 'gr1 = gr1' will go away and you'll get coallescing.
>
> BTW, is it possible to set some instruction flag, instead of overriding a
> function? Something like:
>
> let isMove = 1 in
> def MOVE :.....
That would make sense, but no not currently. If you wanted to teach
it how to do that (similar to the isTerminator functionality), it would be
a great patch.
> BTW, is it possible to set some instruction flag, instead of overriding a
> function? Something like:
>
> let isMove = 1 in
> def MOVE :.....
That would make sense, but no not currently. If you wanted to teach
it how to do that (similar to the isTerminator functionality), it would be
a great patch.
Actually, I just realized why this isn't possible: isMoveInstr is a
predicate that returns three things: the boolean and the two registers
being moved.
The idea is that a move does not necessarily have to be a simple: 'X = Y'
type of operation. On RISC machines, it might be an 'or' with the zero
register. In particular, the method takes an instance of a MachineInstr
because some instances of a particular opcode might be moves and some
might not be.