Dead Code During Manual ISel
During (manual) instruction selection (ISel) for my target with a non RISC instruction set I generate dead code. Manual ISel is required because multiple values are returned by the instruction.
Description
Example C code:
void postinc(volatile int *dst, volatile int *src1, volatile int *src2) {
int rhs = *src2++;
int dummy1 = *src2++; // create long chain
int dummy2 = *src1++; // create long chain
int lhs = *src1++;
*dst++ = lhs - rhs; // should gen SUB (Adst)++,(Alhs)++,Rrhs
// consume incremented pointers
int src1_1 = *src1++;
int src2_1 = *src2++;
*dst = src1_1 + src2_1;
}
The optimal instruction SUB (Adst)++,(Alhs)++,Rrhs
loads the value from memory, subtracts the values, writes the result into memory and returns two results: the incremented pointers for the destination and source operand.
During ISel I generate the correct SUB
instruction and rewire all results:
- incremented destination pointer
- incremented source pointer
- new output chain
-
LOAD
out-chain (to kill theLOAD
)
After that:
-
STORE
has no uses (it’s dead as wished) -
SUB
is used bySTORE
only -
LOAD
(lhs) is used bySUB
only
BUT dead code is generated for the remaining LOAD
and SUB
operations! There is a second SUB
instruction generated!
Work-Around
As far as I can see SelectionDAGISel::DoInstructionSelection()
skips operations that are not used. STORE
does not have uses and is skipped. But LOAD
and SUB
in my example have uses, and therefore code is generated for them.
My work-around is to mark the replaced nodes STORE
, LOAD
and SUB
by X->setNodeId(-1);
and to skip ISEL for these node in my Target::Select(SDNode *N)
method (if (-1 == N->getNodeId()) return;
).
I do not like my work-around. Is there another solution?