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