README revision 1.1 1 1.1 mrg Copyright 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
2 1.1 mrg
3 1.1 mrg This file is part of the GNU MP Library.
4 1.1 mrg
5 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
6 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
7 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
8 1.1 mrg option) any later version.
9 1.1 mrg
10 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
11 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 1.1 mrg License for more details.
14 1.1 mrg
15 1.1 mrg You should have received a copy of the GNU Lesser General Public License
16 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/.
17 1.1 mrg
18 1.1 mrg
19 1.1 mrg
20 1.1 mrg IA-64 MPN SUBROUTINES
21 1.1 mrg
22 1.1 mrg
23 1.1 mrg This directory contains mpn functions for the IA-64 architecture.
24 1.1 mrg
25 1.1 mrg
26 1.1 mrg CODE ORGANIZATION
27 1.1 mrg
28 1.1 mrg mpn/ia64 itanium-2, and generic ia64
29 1.1 mrg
30 1.1 mrg The code here has been optimized primarily for Itanium 2. Very few Itanium 1
31 1.1 mrg chips were ever sold, and Itanium 2 is more powerful, so the latter is what
32 1.1 mrg we concentrate on.
33 1.1 mrg
34 1.1 mrg
35 1.1 mrg
36 1.1 mrg CHIP NOTES
37 1.1 mrg
38 1.1 mrg The IA-64 ISA keeps instructions three and three in 128 bit bundles.
39 1.1 mrg Programmers/compilers need to put explicit breaks `;;' when there are WAW or
40 1.1 mrg RAW dependencies, with some notable exceptions. Such "breaks" are typically
41 1.1 mrg at the end of a bundle, but can be put between operations within some bundle
42 1.1 mrg types too.
43 1.1 mrg
44 1.1 mrg The Itanium 1 and Itanium 2 implementations can under ideal conditions
45 1.1 mrg execute two bundles per cycle. The Itanium 1 allows 4 of these instructions
46 1.1 mrg to do integer operations, while the Itanium 2 allows all 6 to be integer
47 1.1 mrg operations.
48 1.1 mrg
49 1.1 mrg Taken cloop branches seem to insert a bubble into the pipeline most of the
50 1.1 mrg time on Itanium 1.
51 1.1 mrg
52 1.1 mrg Loads to the fp registers bypass the L1 cache and thus get extremely long
53 1.1 mrg latencies, 9 cycles on the Itanium 1 and 6 cycles on the Itanium 2.
54 1.1 mrg
55 1.1 mrg The software pipeline stuff using br.ctop instruction causes delays, since
56 1.1 mrg many issue slots are taken up by instructions with zero predicates, and
57 1.1 mrg since many extra instructions are needed to set things up. These features
58 1.1 mrg are clearly designed for code density, not speed.
59 1.1 mrg
60 1.1 mrg Misc pipeline limitations (Itanium 1):
61 1.1 mrg * The getf.sig instruction can only execute in M0.
62 1.1 mrg * At most four integer instructions/cycle.
63 1.1 mrg * Nops take up resources like any plain instructions.
64 1.1 mrg
65 1.1 mrg Misc pipeline limitations (Itanium 2):
66 1.1 mrg * The getf.sig instruction can only execute in M0.
67 1.1 mrg * Nops take up resources like any plain instructions.
68 1.1 mrg
69 1.1 mrg
70 1.1 mrg ASSEMBLY SYNTAX
71 1.1 mrg
72 1.1 mrg .align pads with nops in a text segment, but gas 2.14 and earlier
73 1.1 mrg incorrectly byte-swaps its nop bundle in big endian mode (eg. hpux), making
74 1.1 mrg it come out as break instructions. We use the ALIGN() macro in
75 1.1 mrg mpn/ia64/ia64-defs.m4 when it might be executed across. That macro
76 1.1 mrg suppresses any .align if the problem is detected by configure. Lack of
77 1.1 mrg alignment might hurt performance but will at least be correct.
78 1.1 mrg
79 1.1 mrg foo:: to create a global symbol is not accepted by gas. Use separate
80 1.1 mrg ".global foo" and "foo:" instead.
81 1.1 mrg
82 1.1 mrg .global is the standard global directive. gas accepts .globl, but hpux "as"
83 1.1 mrg doesn't.
84 1.1 mrg
85 1.1 mrg .proc / .endp generates the appropriate .type and .size information for ELF,
86 1.1 mrg so the latter directives don't need to be given explicitly.
87 1.1 mrg
88 1.1 mrg .pred.rel "mutex"... is standard for annotating predicate register
89 1.1 mrg relationships. gas also accepts .pred.rel.mutex, but hpux "as" doesn't.
90 1.1 mrg
91 1.1 mrg .pred directives can't be put on a line with a label, like
92 1.1 mrg ".Lfoo: .pred ...", the HP assembler on HP-UX 11.23 rejects that.
93 1.1 mrg gas is happy with it, and past versions of HP had seemed ok.
94 1.1 mrg
95 1.1 mrg // is the standard comment sequence, but we prefer "C" since it inhibits m4
96 1.1 mrg macro expansion. See comments in ia64-defs.m4.
97 1.1 mrg
98 1.1 mrg
99 1.1 mrg REGISTER USAGE
100 1.1 mrg
101 1.1 mrg Special:
102 1.1 mrg r0: constant 0
103 1.1 mrg r1: global pointer (gp)
104 1.1 mrg r8: return value
105 1.1 mrg r12: stack pointer (sp)
106 1.1 mrg r13: thread pointer (tp)
107 1.1 mrg Caller-saves: r8-r11 r14-r31 f6-f15 f32-f127
108 1.1 mrg Caller-saves but rotating: r32-
109 1.1 mrg
110 1.1 mrg
111 1.1 mrg ================================================================
112 1.1 mrg mpn_add_n, mpn_sub_n:
113 1.1 mrg
114 1.1 mrg The current code runs at 1.25 c/l on Itanium 2.
115 1.1 mrg
116 1.1 mrg ================================================================
117 1.1 mrg mpn_mul_1:
118 1.1 mrg
119 1.1 mrg The current code runs at 2 c/l on Itanium 2.
120 1.1 mrg
121 1.1 mrg Using a blocked approach, working off of 4 separate places in the operands,
122 1.1 mrg one could make use of the xma accumulation, and approach 1 c/l.
123 1.1 mrg
124 1.1 mrg ldf8 [up]
125 1.1 mrg xma.l
126 1.1 mrg xma.hu
127 1.1 mrg stf8 [wrp]
128 1.1 mrg
129 1.1 mrg ================================================================
130 1.1 mrg mpn_addmul_1:
131 1.1 mrg
132 1.1 mrg The current code runs at 2 c/l on Itanium 2.
133 1.1 mrg
134 1.1 mrg It seems possible to use a blocked approach, as with mpn_mul_1. We should
135 1.1 mrg read rp[] to integer registers, allowing for just one getf.sig per cycle.
136 1.1 mrg
137 1.1 mrg ld8 [rp]
138 1.1 mrg ldf8 [up]
139 1.1 mrg xma.l
140 1.1 mrg xma.hu
141 1.1 mrg getf.sig
142 1.1 mrg add+add+cmp+cmp
143 1.1 mrg st8 [wrp]
144 1.1 mrg
145 1.1 mrg These 10 instructions can be scheduled to approach 1.667 cycles, and with
146 1.1 mrg the 4 cycle latency of xma, this means we need at least 3 blocks. Using
147 1.1 mrg ldfp8 we could approach 1.583 c/l.
148 1.1 mrg
149 1.1 mrg ================================================================
150 1.1 mrg mpn_submul_1:
151 1.1 mrg
152 1.1 mrg The current code runs at 2.25 c/l on Itanium 2. Getting to 2 c/l requires
153 1.1 mrg ldfp8 with all alignment headache that implies.
154 1.1 mrg
155 1.1 mrg ================================================================
156 1.1 mrg mpn_addmul_N
157 1.1 mrg
158 1.1 mrg For best speed, we need to give up using mpn_addmul_1 as the main multiply
159 1.1 mrg building block, and instead take multiple v limbs per loop. For the Itanium
160 1.1 mrg 1, we need to take about 8 limbs at a time for full speed. For the Itanium
161 1.1 mrg 2, something like mpn_addmul_4 should be enough.
162 1.1 mrg
163 1.1 mrg The add+cmp+cmp+add we use on the other codes is optimal for shortening
164 1.1 mrg recurrencies (1 cycle) but the sequence takes up 4 execution slots. When
165 1.1 mrg recurrency depth is not critical, a more standard 3-cycle add+cmp+add is
166 1.1 mrg better.
167 1.1 mrg
168 1.1 mrg /* First load the 8 values from v */
169 1.1 mrg ldfp8 v0, v1 = [r35], 16;;
170 1.1 mrg ldfp8 v2, v3 = [r35], 16;;
171 1.1 mrg ldfp8 v4, v5 = [r35], 16;;
172 1.1 mrg ldfp8 v6, v7 = [r35], 16;;
173 1.1 mrg
174 1.1 mrg /* In the inner loop, get a new U limb and store a result limb. */
175 1.1 mrg mov lc = un
176 1.1 mrg Loop: ldf8 u0 = [r33], 8
177 1.1 mrg ld8 r0 = [r32]
178 1.1 mrg xma.l lp0 = v0, u0, hp0
179 1.1 mrg xma.hu hp0 = v0, u0, hp0
180 1.1 mrg xma.l lp1 = v1, u0, hp1
181 1.1 mrg xma.hu hp1 = v1, u0, hp1
182 1.1 mrg xma.l lp2 = v2, u0, hp2
183 1.1 mrg xma.hu hp2 = v2, u0, hp2
184 1.1 mrg xma.l lp3 = v3, u0, hp3
185 1.1 mrg xma.hu hp3 = v3, u0, hp3
186 1.1 mrg xma.l lp4 = v4, u0, hp4
187 1.1 mrg xma.hu hp4 = v4, u0, hp4
188 1.1 mrg xma.l lp5 = v5, u0, hp5
189 1.1 mrg xma.hu hp5 = v5, u0, hp5
190 1.1 mrg xma.l lp6 = v6, u0, hp6
191 1.1 mrg xma.hu hp6 = v6, u0, hp6
192 1.1 mrg xma.l lp7 = v7, u0, hp7
193 1.1 mrg xma.hu hp7 = v7, u0, hp7
194 1.1 mrg getf.sig l0 = lp0
195 1.1 mrg getf.sig l1 = lp1
196 1.1 mrg getf.sig l2 = lp2
197 1.1 mrg getf.sig l3 = lp3
198 1.1 mrg getf.sig l4 = lp4
199 1.1 mrg getf.sig l5 = lp5
200 1.1 mrg getf.sig l6 = lp6
201 1.1 mrg add+cmp+add xx, l0, r0
202 1.1 mrg add+cmp+add acc0, acc1, l1
203 1.1 mrg add+cmp+add acc1, acc2, l2
204 1.1 mrg add+cmp+add acc2, acc3, l3
205 1.1 mrg add+cmp+add acc3, acc4, l4
206 1.1 mrg add+cmp+add acc4, acc5, l5
207 1.1 mrg add+cmp+add acc5, acc6, l6
208 1.1 mrg getf.sig acc6 = lp7
209 1.1 mrg st8 [r32] = xx, 8
210 1.1 mrg br.cloop Loop
211 1.1 mrg
212 1.1 mrg 49 insn at max 6 insn/cycle: 8.167 cycles/limb8
213 1.1 mrg 11 memops at max 2 memops/cycle: 5.5 cycles/limb8
214 1.1 mrg 16 fpops at max 2 fpops/cycle: 8 cycles/limb8
215 1.1 mrg 21 intops at max 4 intops/cycle: 5.25 cycles/limb8
216 1.1 mrg 11+21 memops+intops at max 4/cycle 8 cycles/limb8
217 1.1 mrg
218 1.1 mrg ================================================================
219 1.1 mrg mpn_lshift, mpn_rshift
220 1.1 mrg
221 1.1 mrg The current code runs at 1 cycle/limb on Itanium 2.
222 1.1 mrg
223 1.1 mrg Using 63 separate loops, we could use the double-word shrp instruction.
224 1.1 mrg That instruction has a plain single-cycle latency. We need 63 loops since
225 1.1 mrg this instruction only accept immediate count. That would lead to a somewhat
226 1.1 mrg silly code size, but the speed would be 0.75 c/l on Itanium 2 (by using shrp
227 1.1 mrg each cycle plus shl/shr going down I1 for a further limb every second
228 1.1 mrg cycle).
229 1.1 mrg
230 1.1 mrg ================================================================
231 1.1 mrg mpn_copyi, mpn_copyd
232 1.1 mrg
233 1.1 mrg The current code runs at 0.5 c/l on Itanium 2. But that is just for L1
234 1.1 mrg cache hit. The 4-way unrolled loop takes just 2 cycles, and thus load-use
235 1.1 mrg scheduling isn't great. It might be best to actually use modulo scheduled
236 1.1 mrg loops, since that will allow us to do better load-use scheduling without too
237 1.1 mrg much unrolling.
238 1.1 mrg
239 1.1 mrg Depending on size or operand alignment, we get 1 c/l or 0.5 c/l on Itanium
240 1.1 mrg 2, according to tune/speed. Cache bank conflicts?
241 1.1 mrg
242 1.1 mrg
243 1.1 mrg
244 1.1 mrg REFERENCES
245 1.1 mrg
246 1.1 mrg Intel Itanium Architecture Software Developer's Manual, volumes 1 to 3,
247 1.1 mrg Intel document 245317-004, 245318-004, 245319-004 October 2002. Volume 1
248 1.1 mrg includes an Itanium optimization guide.
249 1.1 mrg
250 1.1 mrg Intel Itanium Processor-specific Application Binary Interface (ABI), Intel
251 1.1 mrg document 245370-003, May 2001. Describes C type sizes, dynamic linking,
252 1.1 mrg etc.
253 1.1 mrg
254 1.1 mrg Intel Itanium Architecture Assembly Language Reference Guide, Intel document
255 1.1 mrg 248801-004, 2000-2002. Describes assembly instruction syntax and other
256 1.1 mrg directives.
257 1.1 mrg
258 1.1 mrg Itanium Software Conventions and Runtime Architecture Guide, Intel document
259 1.1 mrg 245358-003, May 2001. Describes calling conventions, including stack
260 1.1 mrg unwinding requirements.
261 1.1 mrg
262 1.1 mrg Intel Itanium Processor Reference Manual for Software Optimization, Intel
263 1.1 mrg document 245473-003, November 2001.
264 1.1 mrg
265 1.1 mrg Intel Itanium-2 Processor Reference Manual for Software Development and
266 1.1 mrg Optimization, Intel document 251110-003, May 2004.
267 1.1 mrg
268 1.1 mrg All the above documents can be found online at
269 1.1 mrg
270 1.1 mrg http://developer.intel.com/design/itanium/manuals.htm
271