[LLVMdev] Variable length condition code for SETCC and SELECT?
B. Scott Michel
scottm at aero.org
Thu Jun 5 17:44:33 PDT 2008
After a hiatus on the CellSPU development, I've got all of the
instructions necessary to get the llvm-gcc frontend to build. I've now
discovered a new and interesting problem that I'm not sure how to solve
cleanly and it's due to the fact that CellSPU has no fixed size
condition flags. CellSPU's condition flags depend on the size of what's
being compared, i.e., if both arguments to SETCC are i32, then a
corresponding i32 comparison should be generated. Similarly, if both
arguments to SETCC are i16 or i8, then a corresponding i16 or i8
comparison should be generated.
Another nice feature in the CellSPU architecture is the selb instruction
that directly corresponds to SELECT. Again, though, if SETCC is i32,
then SELECT has to be i32; if SETCC is i16, then SELECT has to be i16, etc.
Currently, I've got what looks to be a promotion problem showing up when
compiling _addvsi3.c during the libgcc2 phase of llvm-gcc. The optimized
selection DAG is show below:
Optimized lowered selection DAG:
SelectionDAG has 20 nodes:
0x14ffca0: ch = EntryToken
0x14ffca0: <multiple use>
0x1500710: i32 = Register #1025
0x1500770: i32,ch = CopyFromReg 0x14ffca0, 0x1500710
0x14ffca0: <multiple use>
0x1500820: i32 = Register #1026
0x1500880: i32,ch = CopyFromReg 0x14ffca0, 0x1500820
0x1500880: <multiple use>
0x1500770: <multiple use>
0x1500a00: i32 = add 0x1500880, 0x1500770
0x1500b50: ch = setgt
0x14ffca0: <multiple use>
0x1501030: i32 = Register #1024
0x1500a00: <multiple use>
0x1501090: ch = CopyToReg 0x14ffca0, 0x1501030, 0x1500a00
0x14ffca0: <multiple use>
0x1501330: ch = TokenFactor 0x1501090, 0x14ffca0
0x1500880: <multiple use>
0x15004c0: i32 = Constant <4294967295>
0x1500b50: <multiple use>
0x1500bb0: i1 = setcc 0x1500880, 0x15004c0, 0x1500b50
0x1500a00: <multiple use>
0x1500770: <multiple use>
0x1500ab0: ch = setlt
0x1500e90: i1 = setcc 0x1500a00, 0x1500770, 0x1500ab0
0x1500a00: <multiple use>
0x1500770: <multiple use>
0x1500b50: <multiple use>
0x1500c80: i1 = setcc 0x1500a00, 0x1500770, 0x1500b50
0x1500f60: i1 = select 0x1500bb0, 0x1500e90, 0x1500c80
0x15011b0: i1 = Constant <1>
0x1501220: i1 = xor 0x1500f60, 0x15011b0
0x15012d0: ch = BasicBlock <bb20 0x14ff930>
0x15013e0: ch = brcond 0x1501330, 0x1501220, 0x15012d0
The setcc's are promoted to i32, since they are comparing i32 operands.
The problem arises when the select (0x1500f60) is promoted by
SelectionDAGLegalize::PromoteOp(), because the select's i1 is promoted
to i8, which triggers an assert because select's arguments (i32) don't
match the new, promoted value type.
It's possible to convince the SELECT case inside of
SelectionDAGLegalize::PromoteOp() that it should really look at the
operands' value type and then return a result promoted to the operands'
value (i32, in this case.) But that doesn't work, because further on, we
don't know to promote the i1 constant <1> to i32, and another assert
gets triggered because select's i32 is larger/not equal to the
constant's new promotion to i8.
It'd be easy to hack PromoteOp to make a pass to determine all operands'
promoted value types, take the max, then figure out some way to
re-promote them to maximal promoted value type. Except that this is a
non-optimal solution requiring PromoteOp to potentially traverse the
operand tree twice.
Any suggestions or ideas?
-scooter
More information about the llvm-dev
mailing list