Flags and Custom Inserters in code generation

What guarantees, if any, does the scheduler make when two selection
nodes are linked by a Flag type? Can I expect the machine instructions
that are selected from the two nodes to be scheduled consecutively?

I'm trying to implement code generation for SELECT_CC nodes in a back
end that I'm working on. The compare operations on the architecture
communicate via bits in a global status register, much like on MSP430.
In fact, I've modeled my implementation after that of the MSP430. So I
have custom target nodes akin to MSP430cmp and MSP430selectcc and
pseudo-instructions like MSP430::Select16. The back end lowers SELECT_CC
nodes to MSP430cmp/MSP430selectcc pairs that are linked together by Flag
values. The instruction selection pass converts the MSP430selectcc node
to a MSP430::Select16 pseudo-instruction which is later expanded to a
condition branch by a custom inserter.

I'm still trying to figure out exactly why, but for some inputs the
DeadMachineInstructionElim pass eliminates the compare instruction. What
appears to be happening is that one of the register-to-register move
instructions of the block occurs between the compare and conditional
branch when the pass iterates over the instructions in reverse order.
Since the architecture's move instruction defines the status register,
the define by the compare instruction is deemed unused. And so the
instruction is eliminated.

Any ideas on why a move instruction would be showing up between the
compare and branch?


Hi Ken,

I have also been hit by the same issue on one of our backends, where the CopyRegToReg instruction is cloberring the flags. It took me quite some time to understand why. The culprit is the PHIElimination phase which assumes CopyRegToReg does NOT clobbers the flags.

I attached the patch I have been using for llvm-2.6.

It is taking advantage of the fact that the only implicit register def / use is for the flags, at least for my backends; the patch could require some tweaking for your backend.

Best regards,

PHIElimination.patch (1.72 KB)

Hi Ken,

you can work around this issue by setting isTerminator = 1 for both the
comparison and the branch instruction. The PHI elimination pass inserts
all moves before the terminator group of the basic block.
This was proposed in
http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-July/023709.html and
works for me.