This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Efficient 64b operations
- From: "Jan Hoogerbrugge" <hoogerbrugge at hotmail dot com>
- To: gcc at gcc dot gnu dot org
- Date: Tue, 03 Feb 2004 13:25:26 +0100
- Subject: Efficient 64b operations
- Bcc:
Hi,
I could use some advice to implement 64-bit long longs efficiently
for my target architecture (TriMedia). Let's consider addition (I have
similar problems with mult and sub). My target architecture provides
a carry operation to implement 64-bit operations with 32-bit operations.
The machine description contains:
(define_expand "adddi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "%r")
(match_operand:DI 2 "register_operand" "r")))]
""
{
rtx dstlo = gen_lowpart(SImode, operands[0]);
rtx src1lo = gen_lowpart(SImode, operands[1]);
rtx src2lo = gen_lowpart(SImode, operands[2]);
rtx dsthi = gen_highpart(SImode, operands[0]);
rtx src1hi = gen_highpart(SImode, operands[1]);
rtx src2hi = gen_highpart(SImode, operands[2]);
rtx tmp1 = gen_reg_rtx(SImode);
rtx tmp2 = gen_reg_rtx(SImode);
rtx tmp3 = gen_reg_rtx(SImode);
emit_insn(gen_addsi3(tmp1, src1lo, src2lo));
emit_insn(gen_carry(tmp2, src1lo, src2lo));
emit_insn(gen_addsi3(tmp3, src1hi, src2hi));
emit_insn(gen_addsi3(dsthi, tmp2, tmp3));
emit_move_insn(dstlo, tmp1);
DONE;
}
)
This works fine except that it could be better in the case
a 32 bit value is added to a 64-bit value. Here is an example
where "1" is added to a long long.
ident r1 -> r10 // 14 movsi/6 r1 == 1
ident r0 -> r9 // 13 movsi/5 r0 == 0
iadd r11 r9 -> r15 // 18 addsi3 add high parts
carry r12 r10 -> r6 // 17 carry compute carry
iadd r12 r10 -> r5 // 16 addsi3 add low parts
iadd r6 r15 -> r7 // 19 addsi3 add carry to high
part
As you can see, r0, which contains constant 0, is moved to r9
which is added to r11. That is silly. How to do this better?
I hoped that a simple optimiser would run after this expansion
to replace x+0 by x, etc. That does not seem to be the case.
Any idea whether peepholes for this would help?
Alternatively, I could test in the expansion whether I am adding
- two 64b registers,
- a 64b register and a 64b constant,
- a 64b register and a 32b register,
- or a 64b register and a 32b constant.
Any idea on how to do this? The which_alternative variable does not
seem to work.
Are there architectures where I could learn from?
Jan
_________________________________________________________________
MSN Search, for accurate results! http://search.msn.nl