Efficient 64b operations

Jan Hoogerbrugge hoogerbrugge@hotmail.com
Tue Feb 3 12:25:00 GMT 2004


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



More information about the Gcc mailing list