2536558bbe99975da80f6329e60efebf7fb4fe4d
[libreriscv.git] / openpower / sv / branches.mdwn
1 # SVP64 Branch Conditional behaviour
2
3 **DRAFT STATUS**
4
5 Please note: SVP64 Branch instructions should be
6 considered completely separate and distinct from
7 standard scalar OpenPOWER-approved v3.0B branches.
8 **v3.0B branches are in no way impacted, altered,
9 changed or modified in any way, shape or form by
10 the SVP64 Vectorised Variants**.
11
12 Links
13
14 * <https://bugs.libre-soc.org/show_bug.cgi?id=664>
15 * <http://lists.libre-soc.org/pipermail/libre-soc-dev/2021-August/003416.html>
16 * [[openpower/isa/branch]]
17
18 Scalar 3.0B Branch Conditional operations, `bc`, `bctar` etc. test a
19 Condition Register. When doing so in a Vector Context, it is quite
20 reasonable and logical to test and Branch on a *Vector* of CR Fields
21 which have just been calculated from a *Vector* of results. In 3D Shader
22 binaries, which are inherently parallelised and predicated, testing all or
23 some results and branching based on multiple tests is extremely common,
24 and a fundamental part of Shader Compilers. Therefore, `sv.bc` and
25 other Vector-aware Branch Conditional instructions are a high priority
26 for 3D GPUs.
27
28 The `BI` field of Branch Conditional operations is five bits, in scalar
29 v3.0B this would select one bit of the 32 bit CR. In SVP64 there are
30 16 32 bit CRs, containing 128 4-bit CR Fields. Therefore, the 2 LSBs of
31 `BI` select the bit from the CR Field (EQ LT GT SO), and the top 3 bits
32 are extended to either scalar or vector and to select CR Fields 0..127
33 as specified in SVP64 [[sv/svp64/appendix]].
34
35 When considering an "array" of branches, there are four useful modes:
36 AND, OR, NAND and NOR of all Conditions.
37 NAND and NOR may be synthesised by
38 inverting `BO[2]` which just leaves two modes:
39
40 * Branch takes place on the first CR test to succeed
41 (a Great Big OR of all condition tests)
42 * Branch takes place only if **all** CR tests succeed:
43 a Great Big AND of all condition tests
44 (including those where the predicate is masked out
45 and the corresponding CR Field is considered to be
46 set to `SNZ`)
47
48 When the CR Fields selected by SVP64 Augmented `BI` is marked as scalar,
49 then as usual the loop ends at the first element tested, after taking
50 predication into consideration. Thus, as usual, when `sz` is zero, srcstep
51 skips forward to the first non-zero predicated element, and only that
52 one element is tested.
53
54 In SVP64 Horizontal-First Mode, the first failure in ALL mode (Great Big
55 AND) results in early exit: no more updates to CTR occur (if requested);
56 no branch occurs, and LR is not updated (if requested). Likewise for
57 non-ALL mode (Great Big Or) on first success early exit also occurs,
58 however this time with the Branch proceeding. In both cases the testing
59 of the Vector of CRs should be done in linear sequential order (or in
60 REMAP re-sequenced order): such that tests that are sequentially beyond
61 the exit point are *not* carried out. (*Note: it is standard practice in
62 Programming languages to exit early from conditional tests, however
63 a little unusual to consider in an ISA that is designed for Parallel
64 Vector Processing. The reason is to have strictly-defined guaranteed
65 behaviour*)
66
67 In Vertical-First Mode, the `ALL` bit still applies, but to the elements
68 that are executed up to the Hint length, in parallel batches. See
69 [[sv/setvl]] for the definition of Vertical-First Hint.
70
71 In `svstep` mode, srcstep and dststep are incremented, and then
72 tested exactly as in [[sv/svstep]]. When Rc=1 the test results
73 are wtitten into the whole CR Field (the exact same one
74 about to be tested by the Branch Condition). Following the svstep
75 update, the
76 Branch Conditional instruction proceeds as normal (reading and testing
77 the CR bit just updated, if the relevant `BO` bit is set). Note that
78 the SVSTATE srcstep and dststep fields are still updated
79 and the CR field still updated, even if `BO[0]` is set.
80
81 Predication in both INT and CR modes may be applied to `sv.bc` and other
82 SVP64 Branch Conditional operations, exactly as they may be applied to
83 other SVP64 operations. When `sz` is zero, any masked-out Branch-element
84 operations are not included in condition testing, exactly like all other SVP64 operations. This *includes* side-effects such as decrementing
85 of CTR, which is also skipped on masked-out CR Field elements,
86 when `sz` is zero.
87
88 However when `sz` is non-zero, this normally requests insertion of a zero
89 in place of the input data, when the relevant predicate mask bit is zero.
90 This would mean that a zero is inserted in place of `CR[BI+32]` for
91 testing against `BO`, which may not be desirable in all circumstances.
92 Therefore, an extra field is provided `SNZ`, which, if set, will insert
93 a **one** in place of a masked-out element, instead of a zero.
94
95 (*Note: Both options are provided because it is useful to deliberately
96 cause the Branch-Conditional Vector testing to fail at a specific point,
97 controlled by the Predicate mask. This is particularly useful in `VLSET`
98 mode, which will truncate SVSTATE.VL at the point of the first failed
99 test.*)
100
101 SVP64 RM `MODE` (includes `ELWIDTH` and `ELWIDTH_SRC` bits) for Branch Conditional:
102
103 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 23 | description |
104 | - | - | - | - | -- | -- | --- |---------|-------------------- |
105 |ALL|LRu| / | / | 0 | 0 | / | SNZ sz | normal mode |
106 |ALL|LRu| / |VSb| 0 | 1 | VLI | SNZ sz | VLSET mode |
107 |ALL|LRu|BRc| / | 1 | 0 | / | SNZ sz | svstep mode |
108 |ALL|LRu|BRc|VSb| 1 | 1 | VLI | SNZ sz | svstep+VLSET mode |
109
110 Fields:
111
112 * **sz** if predication is enabled will put 4 copies of `SNZ` in place of
113 the src CR Field when the predicate bit is zero. otherwise the element
114 is ignored or skipped, depending on context.
115 * **ALL** when set, all branch conditional tests must pass in order for
116 the branch to succeed. When clear, it is the first sequentially
117 encountered successful test that causes the branch to succeed.
118 * **VLI** VLSET is identical to Data-dependent Fail-First mode.
119 In VLSET mode, VL is set equal (truncated) to the first point
120 where, assuming Conditions are tested sequentially, the branch succeeds
121 *or fails* depending if VSb is set.
122 If VLI (Vector Length Inclusive) is clear,
123 VL is truncated to *exclude* the current element, otherwise it is
124 included. SVSTATE.MVL is not changed: only VL.
125 * **LRu**: Link Register Update. When set, Link Register will
126 only be updated if the Branch Condition succeeds. This avoids
127 destruction of LR during loops (particularly Vertical-First
128 ones).
129 * **BRc** Branch variant of Rc. Instructs svstep testing to overwrite
130 the CR Field about to be tested. Only takes effect in svstep mode
131 * **VSb** is most relevant for Vertical-First VLSET Mode. After testing,
132 if VSb is set, VL is truncated if the branch succeeds. If VSb is clear,
133 VL is truncated if the branch did **not** take place.
134
135 svstep mode will run an increment of SVSTATE srcstep and dststep
136 (which is still useful in Horizontal First Mode). Unlike `svstep.`
137 however which updates only CR0 with the testing of REMAP loop progress,
138 the CR Field is taken from the branch `BI` field, and, if `BRc`
139 is set, updated prior to
140 proceeding to each element branch conditional testing.
141 This implies that the *prior contents of the CR Vector are entirely ignored*
142 when `BRc` is set, which implies an opportunity to save on CR file
143 reads.
144
145 Note that, interestingly, due to the useful side-effects of `VLSET` mode
146 and `svstep` mode it is actually useful to use Branch Conditional even
147 to perform no actual branch operation, i.e to point to the instruction
148 after the branch.
149
150 In particular, svstep mode is still useful for Horizontal-First Mode
151 particularly in combination with REMAP. All "loop end" conditions
152 will be tested on a per-element basis and placed into a Vector of CRs
153 starting from the point specified by the Branch `BI` field. This Vector
154 of CR Fields may then be subsequently used as a Predicate Mask, and,
155 furthermore, if VLSET mode was requested, VL will have been set to the
156 length of one of the loop endpoints, again as specified by the bit from
157 the Branch `BI` field.
158
159 Also, the unconditional bit `BO[0]` is still relevant when Predication
160 is applied to the Branch because in `ALL` mode all nonmasked bits have
161 to be tested. Even when svstep mode or VLSET mode are not used, CTR
162 may still be decremented by the total number of nonmasked elements.
163 In short, Vectorised Branch becomes an extremely powerful tool.
164
165 `VLSET` mode with Vertical-First is particularly unusual. Vertical-First
166 is used for explicit looping, where the looping is to terminate if
167 the end of the Vector, VL, is reached. If however that loop is terminated
168 early because VL is truncated, VLSET with Vertical-First becomes
169 meaningless. Therefore, the option to decide whether truncation should
170 occur if the branch succeeds *or* if the branch condition fails allows
171 for flexibility required.
172
173 `VLSET` mode with Horizontal-First when `VSb` is clear is still useful,
174 because it can be used to truncate VL to the first predicated (non-masked-out)
175 element.
176
177 Available options to combine:
178
179 * `BO[0]` to make an unconditional branch would seem irrelevant if
180 it were not for predication and for side-effects.
181 * `BO[1]` to select whether the CR bit being tested is zero or nonzero
182 * `R30` and `~R30` and other predicate mask options including CR and
183 inverted CR bit testing
184 * `sz` and `SNZ` to insert either zeros or ones in place of masked-out
185 predicate bits
186 * `ALL` or `ANY` behaviour corresponding to `AND` of all tests and
187 `OR` of all tests, respectively.
188
189 In addition to the above, it is necessary to select whether, in `svstep`
190 mode, the Vector CR Field is to be overwritten or not: in some cases
191 it is useful to know but in others all that is needed is the branch itself.
192
193 Pseudocode for Horizontal-First Mode:
194
195 ```
196 cond_ok = not SVRMmode.ALL
197 for srcstep in range(VL):
198 # select predicate bit or zero/one
199 if predicate[srcstep]:
200 # get SVP64 extended CR field 0..127
201 SVCRf = SVP64EXTRA(BI>>2)
202 if svstep_mode then
203 new_srcstep, CRbits = SVSTATE_NEXT(srcstep)
204 if BRc = 1 then # CR Vectorised overwritr
205 CR{SVCRf+srcstep} = CRbits
206 else
207 CRbits = CR{SVCRf}
208 testbit = CRbits[BI & 0b11]
209 # testbit = CR[BI+32+srcstep*4]
210 else if not SVRMmode.sz:
211 continue
212 else
213 testbit = SVRMmode.SNZ
214 # actual element test here
215 el_cond_ok <- BO[0] | ¬(testbit ^ BO[1])
216 # merge in the test
217 if SVRMmode.ALL:
218 cond_ok &= el_cond_ok
219 else
220 cond_ok |= el_cond_ok
221 # test for VL to be set (and exit)
222 if VLSET and VSb = el_cond_ok then
223 if SVRMmode.VLI
224 SVSTATE.VL = srcstep+1
225 else
226 SVSTATE.VL = srcstep
227 break
228 # early exit?
229 if SVRMmode.ALL:
230 if ~el_cond_ok:
231 break
232 else
233 if el_cond_ok:
234 break
235 if svstep_mode then
236 SVSTATE.srcstep = new_srcstep
237 if SVCRf.scalar:
238 break
239 ```
240
241 Pseudocode for Vertical-First Mode:
242
243 ```
244 # get SVP64 extended CR field 0..127
245 SVCRf = SVP64EXTRA(BI>>2)
246 if svstep_mode then
247 new_srcstep, CRbits = SVSTATE_NEXT(srcstep)
248 else
249 CRbits = CR{SVCRf}
250 # select predicate bit or zero/one
251 if predicate[srcstep]:
252 if BRc = 1 then # CR0 vectorised
253 CR{SVCRf+srcstep} = CRbits
254 testbit = CRbits[BI & 0b11]
255 else if not SVRMmode.sz:
256 SVSTATE.srcstep = new_srcstep
257 exit # no branch testing
258 else
259 testbit = SVRMmode.SNZ
260 # actual element test here
261 cond_ok <- BO[0] | ¬(testbit ^ BO[1])
262 # test for VL to be set (and exit)
263 if VLSET and cond_ok = VSb then
264 if SVRMmode.VLI
265 SVSTATE.VL = new_srcstep+1
266 else
267 SVSTATE.VL = new_srcstep
268 if svstep_mode then
269 SVSTATE.srcstep = new_srcstep
270 ```
271
272 v3.0B branch pseudocode including LRu
273
274 ```
275 if (mode_is_64bit) then M <- 0
276 else M <- 32
277 if ¬BO[2] then CTR <- CTR - 1
278 ctr_ok <- BO[2] | ((CTR[M:63] != 0) ^ BO[3])
279 cond_ok <- BO[0] | ¬(CR[BI+32] ^ BO[1])
280 lr_ok <- SVRMmode.LRu
281 if ctr_ok & cond_ok then
282 if AA then NIA <-iea EXTS(BD || 0b00)
283 else NIA <-iea CIA + EXTS(BD || 0b00)
284 lr_ok <- 0b1
285 if LK & lr_ok then LR <-iea CIA + 4
286 ```
287
288 # Example Shader code
289
290 ```
291 while(a > 2) {
292 if(b < 5)
293 f();
294 else
295 g();
296 h();
297 }
298 ```
299
300 which compiles to something like:
301
302 ```
303 vec<i32> a, b;
304 // ...
305 pred loop_pred = a > 2;
306 while(loop_pred.any()) {
307 pred if_pred = loop_pred & (b < 5);
308 if(if_pred.any()) {
309 f(if_pred);
310 }
311 label1:
312 pred else_pred = loop_pred & ~if_pred;
313 if(else_pred.any()) {
314 g(else_pred);
315 }
316 h(loop_pred);
317 }
318 ```
319
320 which will end up as:
321
322 ```
323 sv.cmpi CR60.v a.v, 2 # vector compare a into CR60 vector
324 sv.crweird r30, CR60.GT # transfer GT vector to r30
325 while_loop:
326 sv.cmpi CR80.v, b.v, 5 # vector compare b into CR64 Vector
327 sv.bc/m=r30/~ALL/sz CR80.v.LT skip_f # skip when none
328 # only calculate loop_pred & pred_b because needed in f()
329 sv.crand CR80.v.SO, CR60.v.GT, CR80.V.LT # if = loop & pred_b
330 f(CR80.v.SO)
331 skip_f:
332 # illustrate inversion of pred_b. invert r30, test ALL
333 # rather than SOME, but masked-out zero test would FAIL,
334 # therefore masked-out instead is tested against 1 not 0
335 sv.bc/m=~r30/ALL/SNZ CR80.v.LT skip_g
336 # else = loop & ~pred_b, need this because used in g()
337 sv.crternari(A&~B) CR80.v.SO, CR60.v.GT, CR80.V.LT
338 g(CR80.v.SO)
339 skip_g:
340 # conditionally call h(r30) if any loop pred set
341 sv.bclr/m=r30/~ALL/sz BO[1]=1 h()
342 sv.bc/m=r30/~ALL/sz BO[1]=1 while_loop
343 ```