[BACK]Return to README CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpn / ia64

Annotation of OpenXM_contrib/gmp/mpn/ia64/README, Revision 1.1.1.1

1.1       ohara       1: Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
                      2:
                      3: This file is part of the GNU MP Library.
                      4:
                      5: The GNU MP Library is free software; you can redistribute it and/or modify
                      6: it under the terms of the GNU Lesser General Public License as published by
                      7: the Free Software Foundation; either version 2.1 of the License, or (at your
                      8: option) any later version.
                      9:
                     10: The GNU MP Library is distributed in the hope that it will be useful, but
                     11: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     13: License for more details.
                     14:
                     15: You should have received a copy of the GNU Lesser General Public License
                     16: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     17: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     18: 02111-1307, USA.
                     19:
                     20:
                     21:
                     22:
                     23:
                     24:
                     25: The IA-64 ISA keeps instructions three and three in 128 bit bundles.
                     26: Programmers/compilers need to put explicit breaks `;;' when there are
                     27: WAW or RAW dependencies.  Such breaks can typically just be at the end
                     28: of a bundle, with some exceptions.
                     29:
                     30: The Itanium and Itanium 2 implementations can under ideal conditions
                     31: execute two bundles per cycle.  The Itanium 2 allows 4 of these
                     32: instructions to do integer operations, while the Itanium 2 allows all
                     33: 6 to be integer operations.
                     34:
                     35: Taken cloop branches seem to insert a bubble into the pipeline most of
                     36: the time.
                     37:
                     38: Loads to the fp registers bypass the L1 cache and thus get extremely
                     39: long latencies, 9 cycles on the Itanium and 7 cycles on the Itanium 2.
                     40:
                     41: The software pipeline stuff using br.ctop instruction causes delays,
                     42: since many issue slots are taken up by instructions with zero
                     43: predicates, and since about many extra instructions are needed to set
                     44: things up.  These features are designed for code density, not maximum
                     45: speed.
                     46:
                     47: Misc pipeline limitations (Itanium):
                     48: * The getf.sig instruction can only execute in M0.
                     49: * At most four integer instructions/cycle.
                     50: * Nops take up resources like any plain instructions.
                     51:
                     52: ================================================================
                     53: mpn_add_n, mpn_sub_n:
                     54:
                     55: The current code runs at 3 cycles/limb.  Unrolling could clearly bring
                     56: down the time to 2 cycles/limb.
                     57:
                     58: ================================================================
                     59: mpn_addmul_1:
                     60:
                     61: The current code runs at 3.7 cycles/limb, but that somewhat odd timing
                     62: is reached only for huge operands.  It uses the mod-scheduled software
                     63: pipelining feature.  The reason for the poor speed for small operands
                     64: is that mod-scheduled loops have a very long start-up overhead.
                     65:
                     66: For optimal speed, we need to load two 64-bit limbs with the ldfp8
                     67: instruction, and stay away from mod-scheduled loops.  Since rp and up
                     68: might be mutually aligned in two ways, we will need two loop variants,
                     69: with the same basic structure:
                     70:
                     71:   { .mfi       getf.sig
                     72:                xma.l
                     73:           (p6) cmp.leu         p6, p7 =
                     74: } { .mfi       stf8
                     75:                xma.hu
                     76:           (p7) cmp.ltu         p6, p7 =
                     77:                ;;
                     78: } { .mib       getf.sig
                     79:           (p6) add 1
                     80:                nop.b
                     81: } { .mib       ldfp8            = [up], 16
                     82:           (p7) add
                     83:                nop.b
                     84:                ;;
                     85:   { .mfi       getf.sig
                     86:                xma.l
                     87:           (p6) cmp.leu         p6, p7 =
                     88: } { .mfi       stf8
                     89:                xma.hu
                     90:           (p7) cmp.ltu         p6, p7 =
                     91:                ;;
                     92: } { .mib       getf.sig
                     93:           (p6) add 1
                     94:                nop.b
                     95: } { .mib       ldfp8            = [rp], 16
                     96:           (p7) add
                     97:                br.cloop
                     98:                ;;
                     99: }
                    100:
                    101: 2 limbs/20 instructions
                    102:           20 insn/max 6 insn/cycle:            3.3 cycles/2limb
                    103:           8 memops/max 2 memops/cycle:         4.0 cycles/2limb
                    104:           8 intops/max 2 intops/cycle:         4.0 cycles/2limb
                    105:           4 fpops/max 2 fpops/cycle:           2.0 cycles/2limb
                    106:
                    107: ================================================================
                    108: mpn_submul_1:
                    109:
                    110: The current code just calls mpn_mul_1 and mpn_sub_n and thus needs
                    111: about 7 cycles/limb.
                    112:
                    113: We could implement this much like mpn_addmul_1, if we first complement
                    114: v.  When v is complemented, the low product limb becomes complement of
                    115: true product.  This should allow us to use the accumulation of xma.
                    116: Here is how it works:
                    117:
                    118:
                    119:   #define umul_ppmma(ph, pl, m0, m1, a) \
                    120:     do {                                                               \
                    121:       UDItype __m0 = (m0), __m1 = (m1), __a = (a);                     \
                    122:       __asm__ ("xma.hu %0 = %1, %2, %3"                                        \
                    123:               : "=f" (ph)                                              \
                    124:               : "f" (m0), "f" (m1), "f" (__a));                        \
                    125:       (pl) = __m0 * __m1 + __a;                                                \
                    126:     } while (0)
                    127:
                    128:   mp_limb_t
                    129:   mpn_submul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
                    130:   {
                    131:     mp_limb_t cl, cy;
                    132:     mp_size_t i;
                    133:     mp_limb_t phi, plo;
                    134:     mp_limb_t x;
                    135:     mp_limb_t ul, vln;
                    136:
                    137:     vln = -vl;
                    138:
                    139:     cl = 0;
                    140:     for (i = n; i != 0; i--)
                    141:       {
                    142:        ul = *up++;             /* will need this in both fregs and gregs */
                    143:        x = *rp;
                    144:        umul_ppmma (phi, plo, ul, vln, x);
                    145:
                    146:        cy = plo < cl;
                    147:        plo -= cl;
                    148:
                    149:        cl = ul - phi;
                    150:        cl += cy;
                    151:
                    152:        *rp++ = plo;
                    153:       }
                    154:
                    155:     return cl;
                    156:   }
                    157:
                    158: ================================================================
                    159: mpn_mul_1:
                    160:
                    161: The current code runs at 3.7 cycles/limb.  The code is very similar to
                    162: the mpn_addmul_1 code.  See comments above.
                    163:
                    164: Faster code wouldn't be too hard to write.  This is one possible
                    165: pattern:
                    166:
                    167:   { .mfi       getf.sig
                    168:                xma.l
                    169:           (p6) cmp.leu         p6, p7 =
                    170: } { .mfi       stf8
                    171:                xma.hu
                    172:           (p7) cmp.ltu         p6, p7 =
                    173:                ;;
                    174: } { .mib       getf.sig
                    175:           (p6) add 1
                    176:                nop.b
                    177: } { .mib       ldf8             = [up], 8
                    178:           (p7) add
                    179:                br.cloop
                    180:                ;;
                    181: }
                    182:
                    183: 1 limb/12 instructions
                    184:           12 insn/max 6 insn/cycle:            2.0 cycles/limb
                    185:           4 memops/max 2 memops/cycle:         2.0 cycles/limb
                    186:           4 intops/max 2 intops/cycle:         2.0 cycles/limb
                    187:           2 fpops/max 2 fpops/cycle:           1.0 cycles/limb
                    188:
                    189: ================================================================
                    190: mpn_mul_8
                    191:
                    192: The add+cmp+add we use on the other codes is optimal for shortening
                    193: recurrencies (2 cycles) but the sequence takes up 4 execution slots.  When
                    194: recurrency depth is not critical, a more standard 3-cycle add+cmp+add is
                    195: better.
                    196:
                    197: /* First load the 8 values from v */
                    198:        ldfp8           v0, v1 = [r35], 16;;
                    199:        ldfp8           v2, v3 = [r35], 16;;
                    200:        ldfp8           v4, v5 = [r35], 16;;
                    201:        ldfp8           v6, v7 = [r35], 16;;
                    202:
                    203: /* In the inner loop, get a new U limb and store a result limb. */
                    204:        mov             lc = un
                    205: Loop:  ldf8            u0 = [r33], 8
                    206:        xma.l           lp0 = v0, u0, hp0
                    207:        xma.hu          hp0 = v0, u0, hp0
                    208:        xma.l           lp1 = v1, u0, hp1
                    209:        xma.hu          hp1 = v1, u0, hp1
                    210:        xma.l           lp2 = v2, u0, hp2
                    211:        xma.hu          hp2 = v2, u0, hp2
                    212:        xma.l           lp3 = v3, u0, hp3
                    213:        xma.hu          hp3 = v3, u0, hp3
                    214:        xma.l           lp4 = v4, u0, hp4
                    215:        xma.hu          hp4 = v4, u0, hp4
                    216:        xma.l           lp5 = v5, u0, hp5
                    217:        xma.hu          hp5 = v5, u0, hp5
                    218:        xma.l           lp6 = v6, u0, hp6
                    219:        xma.hu          hp6 = v6, u0, hp6
                    220:        xma.l           lp7 = v7, u0, hp7
                    221:        xma.hu          hp7 = v7, u0, hp7
                    222:        getf.sig        l0 = lp0
                    223:        getf.sig        l1 = lp1
                    224:        getf.sig        l2 = lp2
                    225:        getf.sig        l3 = lp3
                    226:        getf.sig        l4 = lp4
                    227:        getf.sig        l5 = lp5
                    228:        getf.sig        l6 = lp6
                    229:        getf.sig        l7 = lp7
                    230:        add+cmp+add     l0, l0, h0
                    231:        add+cmp+add     l1, l1, h1
                    232:        add+cmp+add     l2, l2, h2
                    233:        add+cmp+add     l3, l3, h3
                    234:        add+cmp+add     l4, l4, h4
                    235:        add+cmp+add     l5, l5, h5
                    236:        add+cmp+add     l6, l6, h6
                    237:        add+cmp+add     l7, l7, h7
                    238:        st8             [r32] = xx, 8
                    239:        br.cloop Loop
                    240:
                    241:        50 insn at max 6 insn/cycle:            8.33 cycles/limb8
                    242:        10 memops at max 2 memops/cycle:        5 cycles/limb8
                    243:        16 fpops at max 2 fpops/cycle:          8 cycles/limb8
                    244:        24 intops at max 4 intops/cycle:        6 cycles/limb8
                    245:        10+24 memops+intops at max 4/cycle      8.5 cycles/limb8
                    246:                                                1.0625 cycles/limb
                    247:
                    248: ================================================================
                    249: mpn_lshift, mpn_rshift
                    250:
                    251: The current code runs at 2 cycles/limb, but has a too deep software
                    252: pipeline.  The code suffers badly from the 4 cycle latency of the
                    253: variable shift instructions.
                    254:
                    255: Using 63 separate loops, we could use the double-word SHRP
                    256: instruction.  That instruction has a plain single-cycle latency.  We
                    257: need 63 loops since this instruction only accept immediate count.

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>