gcc.c-torture/execute/20000403-1.c tripped over this on an internal (16 bit) port doing SImode subtract. The comments for expand_binop() explicitly state that you can't rely on the target being set:
If TARGET is nonzero, the value is generated there, if it is convenient to do so. but we seem to have that expectation later: /* Main add/subtract of the input operands. */ x = expand_binop (word_mode, binoptab, op0_piece, op1_piece, target_piece, unsignedp, next_methods); The only place where target_piece is assigned is in the (i > 0) case: if (i > 0) { . . . emit_move_insn (target_piece, newx); } So it seems to me that in the (i == 0) case we need to see if target_piece happened to receive the result, and if not, assign it. It seems to me that this kind of bug should have been noticed already, so... am I missing something? 2005-03-21 DJ Delorie <[EMAIL PROTECTED]> * optabs.c (expand_binop): Make sure the first subword's result gets stored. Index: optabs.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/optabs.c,v retrieving revision 1.265 diff -p -U3 -r1.265 optabs.c --- optabs.c 16 Mar 2005 18:29:23 -0000 1.265 +++ optabs.c 22 Mar 2005 01:25:35 -0000 @@ -1534,6 +1534,11 @@ expand_binop (enum machine_mode mode, op } emit_move_insn (target_piece, newx); } + else + { + if (x != target_piece) + emit_move_insn (target_piece, x); + } carry_in = carry_out; }