This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Expanding instructions with condition codes inter-deps
- From: "Paulo J. Matos" <paulo at matos-sorge dot com>
- To: gcc at gcc dot gnu dot org
- Date: Mon, 17 Oct 2011 11:50:08 +0100
- Subject: Expanding instructions with condition codes inter-deps
Hi,
To negate a double word (HImode) register, I used to take the
instruction all the way to assembly generation and then expand into
three assembly instructions like so:
xor %t0, #ffff ; invert bits in top word of op0
nadd %b0, #0 ; negate bottom bits of op0
addc %t0, #0 ; add carry to top bits of op0
The interesting thing about this sequence is that the carry added to the
top bits of op0, is the carry generated by the previous instruction.
If I instead of taking the neghi rule all the way to assembly, and
instead expand it I get:
(define_expand "neghi2"
[(set (match_operand:HI 0 "register_operand")
(neg:HI (match_operand:HI 1 "general_operand")))
(clobber (reg:CC RCC))]
""
{
rtx op0_low = gen_lowpart(QImode, operands[0]);
rtx op0_high = gen_highpart(QImode, operands[0]);
emit_move_insn(operands[0], operands[1]);
emit_insn(gen_xorqi3(op0_high, op0_high, GEN_INT(-1)));
emit_insn(gen_negqi2(op0_low, op0_low));
emit_insn(gen_addc_internal(op0_high, op0_high, const0_rtx));
DONE;
})
addc_internal looks like:
(define_insn "addc_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=c")
(plus:QI
(plus:QI
(ltu:QI (reg:CC RCC) (const_int 0))
(match_operand:QI 1 "nonimmediate_operand" "%0"))
(match_operand:QI 2 "general_operand" "cwmi")))
(clobber (reg:CC RCC))]
""
"addc\\t%0,%f2")
The problem is that GCC sometimes moves nadd and addc around. It might
swap their order or insert instructions in-between that set the carry
flag. This ends up generating code which won't work properly.
What's the best way to instruct GCC during neghi2 expansion that the
carry read by addc internal is the one generated by negqi2 and so no
instructions setting carry should be inserted between them and that
their order should not be changed? (for example, it would be ok to
output negqi2, xorqi3 and addc_internal since xorqi3 only sets N and Z,
not the Carry bit).
Cheers,
--
PMatos