(no commit message)
[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 In SVP64 Horizontal-First Mode, the first failure in ALL mode (Great Big
49 AND) results in early exit: no more updates to CTR occur (if requested);
50 no branch occurs, and LR is not updated (if requested). Likewise for
51 non-ALL mode (Great Big Or) on first success early exit also occurs,
52 however this time with the Branch proceeding. In both cases the testing
53 of the Vector of CRs should be done in linear sequential order (or in
54 REMAP re-sequenced order): such that tests that are sequentially beyond
55 the exit point are *not* carried out. (*Note: it is standard practice in
56 Programming languages to exit early from conditional tests, however
57 a little unusual to consider in an ISA that is designed for Parallel
58 Vector Processing. The reason is to have strictly-defined guaranteed
59 behaviour*)
60
61 In Vertical-First Mode, the `ALL` bit should not be used. If set,
62 behaviour is `UNDEFINED`. (*The reason is that Vertical-First hints may
63 permit multiple elements up to hint length to be executed in parallel,
64 however the number is entirely up to implementors. Attempting to test
65 an arbitrary indeterminate number of Conditional tests is impossible
66 to define, and efforts to enforce such defined behaviour interfere with
67 Vertical-First mode parallel opportunistic behaviour.*)
68
69 In `svstep` mode, srcstep and dststep are incremented, and then
70 tested exactly as in [[sv/svstep]]. When Rc=1 the test results
71 are wtitten into the whole CR Field (the exact same one
72 about to be tested by the Branch Condition). Following the svstep
73 update, the
74 Branch Conditional instruction proceeds as normal (reading and testing
75 the CR bit just updated, if the relevant `BO` bit is set). Note that
76 the SVSTATE srcstep and dststep fields are still updated
77 and the CR field still updated, even if `BO[0]` is set.
78
79 Predication in both INT and CR modes may be applied to `sv.bc` and other
80 SVP64 Branch Conditional operations, exactly as they may be applied to
81 other SVP64 operations. When `sz` is zero, any masked-out Branch-element
82 operations are not executed, exactly like all other SVP64 operations.
83
84 However when `sz` is non-zero, this normally requests insertion of a zero
85 in place of the input data, when the relevant predicate mask bit is zero.
86 This would mean that a zero is inserted in place of `CR[BI+32]` for
87 testing against `BO`, which may not be desirable in all circumstances.
88 Therefore, an extra field is provided `SNZ`, which, if set, will insert
89 a **one** in place of a masked-out element instead of a zero.
90
91 (*Note: Both options are provided because it is useful to deliberately
92 cause the Branch-Conditional Vector testing to fail at a specific point,
93 controlled by the Predicate mask. This is particularly useful in `VLSET`
94 mode, which will truncate SVSTATE.VL at the point of the first failed
95 test.*)
96
97 SVP64 RM `MODE` (includes `ELWIDTH` and `ELWIDTH_SRC` bits) for Branch Conditional:
98
99 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 23 | description |
100 | - | - | - | - | -- | -- | --- |---------|-------------------------- |
101 |ALL|LRu| / | / | 0 | 0 | / | SNZ sz | normal mode |
102 |ALL|LRu| / | / | 0 | 1 | VLI | SNZ sz | VLSET mode |
103 |ALL|LRu|BRc| / | 1 | 0 | / | SNZ sz | svstep mode |
104 |ALL|LRu|BRc| / | 1 | 1 | VLI | SNZ sz | svstep+VLSET mode |
105
106 Fields:
107
108 * **sz** if predication is enabled will put 4 copies of `SNZ` in place of
109 the src CR Field when the predicate bit is zero. otherwise the element
110 is ignored or skipped, depending on context.
111 * **ALL** when set, all branch conditional tests must pass in order for
112 the branch to succeed.
113 * **VLI** In VLSET mode, VL is set equal (truncated) to the first
114 branch which succeeds. If VLI (Vector Length Inclusive) is clear,
115 VL is truncated to *exclude* the current element, otherwise it is
116 included. SVSTATE.MVL is not changed.
117 * **LRu**: Link Register Update. When set, Link Register will
118 only be updated if the Branch Condition succeeds. This avoids
119 destruction of LR during loops.
120 * **BRc** Branch variant of Rc. Instructs svstep testing to overwrite
121 the CR Field about to be tested
122
123 svstep mode will run an increment of SVSTATE srcstep and dststep
124 (which is still useful in Horizontal First Mode). Unlike `svstep.`
125 however which updates only CR0 with the testing of REMAP loop progress,
126 the CR Field is taken from the branch `BI` field, and updated prior to
127 proceeding to each element branch conditional testing.
128
129 Note that, interestingly, due to the useful side-effects of `VLSET` mode
130 and `svstep` mode it is actually useful to use Branch Conditional even
131 to perform no actual branch operation, i.e to point to the instruction
132 after the branch.
133
134 In particular, svstep mode is still useful for Horizontal-First Mode
135 particularly in combination with REMAP. All "loop end" conditions
136 will be tested on a per-element basis and placed into a Vector of CRs
137 starting from the point specified by the Branch `BI` field. This Vector
138 of CR Fields may then be subsequently used as a Predicate Mask, and,
139 furthermore, if VLSET mode was requested, VL will have been set to the
140 length of one of the loop endpoints, again as specified by the bit from
141 the Branch `BI` field.
142
143 Also, the unconditional bit `BO[0]` is still relevant when Predication
144 is applied to the Branch because in `ALL` mode all nonmasked bits have
145 to be tested. Even when svstep mode or VLSET mode are not used, CTR
146 may still be decremented by the total number of nonmasked elements.
147 In short, Vectorised Branch becomes an extremely powerful tool.
148
149 Available options to combine:
150
151 * `BO[0]` to make an unconditional branch would seem irrelevant if
152 it were not for predication and for side-effects.
153 * `BO[1]` to select whether the CR bit being tested is zero or nonzero
154 * `R30` and `~R30` and other predicate mask options including CR and
155 inverted CR bit testing
156 * `sz` and `SNZ` to insert either zeros or ones in place of masked-out
157 predicate bits
158 * `ALL` or `ANY` behaviour corresponding to `AND` of all tests and
159 `OR` of all tests, respectively.
160
161 In addition to the above, it is necessary to select whether, in `svstep`
162 mode, the Vector CR Field is to be overwritten or not: in some cases
163 it is useful to know but in others all that is needed is the branch itself.
164 In the case of `sv.bc` there is no additional bitspace, so on the
165 basis that it is rarely used, the `AA`
166 field is re-interpreted instead to be `Rc`. For `sv.bclr`, there is free
167 bitspace and so bit 16 has been chosen as `Rc`.
168
169 **These interpretations are only available for sv.bc, they are NOT
170 available for Power ISA v3.0B** i.e. only when embedded in an SVP64
171 Prefix Context do these and all other parts of this specification
172 apply.
173
174 Form: B-Form (see [[isatables/fields.text]])
175
176 | 0.5|6.10|11.15|16..29| 30 |31| name |
177 | -- | -- | --- | ---- | -- |--| ------- |
178 |16 | BO | BI | BD | Rc |LK| sv.bc |
179
180 Form: XL-Form (see [[isatables/fields.text]])
181
182 | 0.5|6.10|11.15|16|17.18|19.20|21..30|31| name |
183 | -- | -- | --- |--|---- |-----|------|--| ------- |
184 |19 | BO | BI |Rc| // | BH | 19 |LK| sv.bclr |
185
186 Pseudocode for Rc in sv.bc
187
188 ```
189 # Use bit 30 as Rc, disable AA
190 Rc = AA
191 AA = 0
192 ```
193
194 Pseudocode for Rc in sv.bclr
195
196 ```
197 # use bit 16 of opcode as Rc
198 Rc = instr[16]
199 ```
200
201 Pseudocode for Horizontal-First Mode:
202
203 ```
204 cond_ok = not SVRMmode.ALL
205 for srcstep in range(VL):
206 # select predicate bit or zero/one
207 if predicate[srcstep]:
208 # get SVP64 extended CR field 0..127
209 SVCRf = SVP64EXTRA(BI>>2)
210 if svstep_mode then
211 new_srcstep, CRbits = SVSTATE_NEXT(srcstep)
212 else
213 CRbits = CR{SVCRf}
214 if Rc = 1 then # CR0 Vectorised
215 CR{0+srcstep} = CRbits
216 testbit = CRbits[BI & 0b11]
217 # testbit = CR[BI+32+srcstep*4]
218 else if not SVRMmode.sz:
219 continue
220 else
221 testbit = SVRMmode.SNZ
222 # actual element test here
223 el_cond_ok <- BO[0] | ¬(testbit ^ BO[1])
224 # merge in the test
225 if SVRMmode.ALL:
226 cond_ok &= el_cond_ok
227 else
228 cond_ok |= el_cond_ok
229 # test for VL to be set (and exit)
230 if ~el_cond_ok and VLSET
231 if SVRMmode.VLI
232 SVSTATE.VL = srcstep+1
233 else
234 SVSTATE.VL = srcstep
235 break
236 # early exit?
237 if SVRMmode.ALL:
238 if ~el_cond_ok:
239 break
240 else
241 if el_cond_ok:
242 break
243 if svstep_mode then
244 SVSTATE.srcstep = new_srcstep
245 ```
246
247 Pseudocode for Vertical-First Mode:
248
249 ```
250 # get SVP64 extended CR field 0..127
251 SVCRf = SVP64EXTRA(BI>>2)
252 if svstep_mode then
253 new_srcstep, CRbits = SVSTATE_NEXT(srcstep)
254 else
255 CRbits = CR{SVCRf}
256 # select predicate bit or zero/one
257 if predicate[srcstep]:
258 if Rc = 1 then # CR0 vectorised
259 CR{0+srcstep} = CRbits
260 testbit = CRbits[BI & 0b11]
261 else if not SVRMmode.sz:
262 SVSTATE.srcstep = new_srcstep
263 exit # no branch testing
264 else
265 testbit = SVRMmode.SNZ
266 # actual element test here
267 cond_ok <- BO[0] | ¬(testbit ^ BO[1])
268 # test for VL to be set (and exit)
269 if ~cond_ok and VLSET
270 if SVRMmode.VLI
271 SVSTATE.VL = new_srcstep+1
272 else
273 SVSTATE.VL = new_srcstep
274 if svstep_mode then
275 SVSTATE.srcstep = new_srcstep
276 ```
277
278 # Example Shader code
279
280 ```
281 while(a > 2) {
282 if(b < 5)
283 f();
284 else
285 g();
286 h();
287 }
288 ```
289
290 which compiles to something like:
291
292 ```
293 vec<i32> a, b;
294 // ...
295 pred loop_pred = a > 2;
296 while(loop_pred.any()) {
297 pred if_pred = loop_pred & (b < 5);
298 if(if_pred.any()) {
299 f(if_pred);
300 }
301 label1:
302 pred else_pred = loop_pred & ~if_pred;
303 if(else_pred.any()) {
304 g(else_pred);
305 }
306 h(loop_pred);
307 }
308 ```
309
310 which will end up as:
311
312 ```
313 sv.cmpi CR60.v a.v, 2 # vector compare a into CR60 vector
314 sv.crweird r30, CR60.GT # transfer GT vector to r30
315 while_loop:
316 sv.cmpi CR80.v, b.v, 5 # vector compare b into CR64 Vector
317 sv.bc/m=r30/~ALL/sz CR80.v.LT skip_f # skip when none
318 # only calculate loop_pred & pred_b because needed in f()
319 sv.crand CR80.v.SO, CR60.v.GT, CR80.V.LT # if = loop & pred_b
320 f(CR80.v.SO)
321 skip_f:
322 # illustrate inversion of pred_b. invert r30, test ALL
323 # rather than SOME, but masked-out zero test would FAIL,
324 # therefore masked-out instead is tested against 1 not 0
325 sv.bc/m=~r30/ALL/SNZ CR80.v.LT skip_g
326 # else = loop & ~pred_b, need this because used in g()
327 sv.crternari(A&~B) CR80.v.SO, CR60.v.GT, CR80.V.LT
328 g(CR80.v.SO)
329 skip_g:
330 # conditionally call h(r30) if any loop pred set
331 sv.bclr/m=r30/~ALL/sz BO[1]=1 h()
332 sv.bc/m=r30/~ALL/sz BO[1]=1 while_loop
333 ```