(no commit message)
[libreriscv.git] / openpower / sv / branches.mdwn
index 471ac3d2f8a918104cd837209fa213b3057795c7..d4487dba9b0d077ee128e2883df3301dcc3316be 100644 (file)
@@ -16,38 +16,56 @@ Links
 * [[openpower/isa/branch]]
 
 Scalar 3.0B Branch Conditional operations, `bc`, `bctar` etc. test a
-Condition Register.  When doing so in a Vector Context, it is quite
-reasonable and logical to test and Branch on a *Vector* of CR Fields
-which have just been calculated from a *Vector* of results. In 3D Shader
+Condition Register.  However for parallel processing it is simply impossible
+to perform multiple independent branches: the Program Counter simply
+cannot branch to multiple destinations based on multiple conditions.
+The best that can be done is
+to test multiple Conditions and make a decision of a *single* branch,
+based on analysis of a *Vector* of CR Fields
+which have just been calculated from a *Vector* of results.
+
+In 3D Shader
 binaries, which are inherently parallelised and predicated, testing all or
 some results and branching based on multiple tests is extremely common,
-and a fundamental part of Shader Compilers.  Therefore, `sv.bc` and
+and a fundamental part of Shader Compilers.  Example:
+without such multi-condition
+test-and-branch, if a predicate mask is all zeros a large batch of
+instructions may be masked out to `nop`, and it would waste
+CPU cycles not only to run them but also to load the predicate
+mask repeatedly for each one.  3D GPU ISAs can test for this scenario
+and jump over the fully-masked-out operations, by spotting that
+*all* Conditions are false. Or, conversely, they only call the function if at least
+one Condition) is set.
+Therefore, in order to be commercially competitive, `sv.bc` and
 other Vector-aware Branch Conditional instructions are a high priority
-for 3D GPUs.
+for 3D GPU workloads.
 
 The `BI` field of Branch Conditional operations is five bits, in scalar
-v3.0B this would select one bit of the 32 bit CR.  In SVP64 there are
+v3.0B this would select one bit of the 32 bit CR,
+comprising eight CR Fields of 4 bits each.  In SVP64 there are
 16 32 bit CRs, containing 128 4-bit CR Fields.  Therefore, the 2 LSBs of
 `BI` select the bit from the CR Field (EQ LT GT SO), and the top 3 bits
 are extended to either scalar or vector and to select CR Fields 0..127
 as specified in SVP64 [[sv/svp64/appendix]].
 
-When considering an "array" of branches, there are four useful modes:
+When considering an "array" of branch-tests, there are four useful modes:
 AND, OR, NAND and NOR of all Conditions.
 NAND and NOR may be synthesised by
 inverting `BO[2]` which just leaves two modes:
 
-* Branch takes place on the first CR test to succeed
+* Branch takes place on the first CR Field test to succeed
   (a Great Big OR of all condition tests)
-* Branch takes place only if **all** CR tests succeed:
+* Branch takes place only if **all** CR field tests succeed:
   a Great Big AND of all condition tests
   (including those where the predicate is masked out
    and the corresponding CR Field is considered to be
    set to `SNZ`)
 
-When the CR Fields selected by SVP64 Augmented `BI` is marked as scalar,
-then as usual the loop ends at the first element tested, after taking
-predication into consideration. Thus, as usual, when `sz` is zero, srcstep
+When the CR Fields selected by SVP64-Augmented `BI` is marked as scalar,
+then as the usual SVP64 rules apply,
+the loop ends at the first element tested, after taking
+predication into consideration. Thus, also as usual, when a predicate mask is
+given, and `BI` marked as scalar, and `sz` is zero, srcstep
 skips forward to the first non-zero predicated element, and only that
 one element is tested.
 
@@ -64,29 +82,23 @@ a little unusual to consider in an ISA that is designed for Parallel
 Vector Processing. The reason is to have strictly-defined guaranteed
 behaviour*)
 
-In Vertical-First Mode, the `ALL` bit still applies, but to the elements
-that are executed up to the Hint length, in parallel batches. See
-[[sv/setvl]] for the definition of Vertical-First Hint.
-
-In `svstep` mode, srcstep and dststep are incremented, and then
-tested exactly as in  [[sv/svstep]]. When Rc=1 the test results
-are wtitten into the whole CR Field (the exact same one
-about to be tested by the Branch Condition). Following the svstep
-update, the
-Branch Conditional instruction proceeds as normal (reading and testing
-the CR bit just updated, if the relevant `BO` bit is set).  Note that
-the SVSTATE srcstep and dststep fields are still updated
-and the CR field still updated, even if `BO[0]` is set.
+In Vertical-First Mode, setting the `ALL` bit results in `UNDEFINED` 
+behaviour. Given that only one element is being tested at a time
+in Vertical-First Mode, a test designed to be done on multiple
+bits is meaningless.
 
 Predication in both INT and CR modes may be applied to `sv.bc` and other
 SVP64 Branch Conditional operations, exactly as they may be applied to
 other SVP64 operations.  When `sz` is zero, any masked-out Branch-element
 operations are not included in condition testing, exactly like all other
-SVP64 operations. This *includes* side-effects such as decrementing of
-CTR, which is also skipped on masked-out CR Field elements, when `sz`
-is zero.
-
-However when `sz` is non-zero, this normally requests insertion of a zero
+SVP64 operations, *including* side-effects such as potentially updating
+LR or CTR, which will also be skipped. There is *one* exception here,
+which is when
+`BO[2]=0, sz=0, CTR-test=0, CTi=1` and the relevant element
+predicate mask bit is also zero:
+under these special circumstances CTR will also decrement.
+
+When `sz` is non-zero, this normally requests insertion of a zero
 in place of the input data, when the relevant predicate mask bit is zero.
 This would mean that a zero is inserted in place of `CR[BI+32]` for
 testing against `BO`, which may not be desirable in all circumstances.
@@ -102,12 +114,12 @@ test.*)
 SVP64 RM `MODE` (includes `ELWIDTH` and `ELWIDTH_SRC` bits) for Branch
 Conditional:
 
-| 4 | 5 | 6 | 7 | 19 | 20 |  21 | 22   23 |  description        |
-| - | - | - | - | -- | -- | --- |---------|-------------------- |
-|ALL|LRu| / | / | 0  | 0  | /   |  SNZ sz | normal mode         |
-|ALL|LRu| / |VSb| 0  | 1  | VLI |  SNZ sz | VLSET mode          |
-|ALL|LRu|BRc| / | 1  | 0  | /   |  SNZ sz | svstep mode         |
-|ALL|LRu|BRc|VSb| 1  | 1  | VLI |  SNZ sz | svstep+VLSET mode   |
+| 4 | 5 | 6 | 7 | 19 | 20 |  21 | 22   23 |  description     |
+| - | - | - | - | -- | -- | --- |---------|----------------- |
+|ALL|LRu| / | / | 0  | 0  | /   |  SNZ sz | normal mode      |
+|ALL|LRu| / |VSb| 0  | 1  | VLI |  SNZ sz | VLSET mode       |
+|ALL|LRu|CTi| / | 1  | 0  | /   |  SNZ sz | CTR-test mode         |
+|ALL|LRu|CTi|VSb| 1  | 1  | VLI |  SNZ sz | CTR-test+VLSET mode   |
 
 Fields:
 
@@ -128,33 +140,57 @@ Fields:
   only be updated if the Branch Condition succeeds. This avoids
   destruction of LR during loops (particularly Vertical-First
   ones).
-* **BRc** Branch variant of Rc. Instructs svstep testing to overwrite
-  the CR Field about to be tested. Only takes effect in svstep mode
 * **VSb** is most relevant for Vertical-First VLSET Mode. After testing,
   if VSb is set, VL is truncated if the branch succeeds.  If VSb is clear,
   VL is truncated if the branch did **not** take place.
-
-svstep mode will run an increment of SVSTATE srcstep and dststep (which is
-still useful in Horizontal First Mode).  Unlike `svstep.` however which
-updates only CR0 with the testing of REMAP loop progress, the CR Field
-is taken from the branch `BI` field, and, if `BRc` is set, updated prior
-to proceeding to each element branch conditional testing.  This implies
-that the *prior contents of the CR Vector are entirely ignored* when
-`BRc` is set, which implies an opportunity to save on CR file reads.
-
-Note that, interestingly, due to the useful side-effects of `VLSET` mode
-and `svstep` mode it is actually useful to use Branch Conditional even
+* **CTi** CTR inversion. CTR Mode normally decrements per element
+  tested. CTR inversion decrements if a test *fails*.
+
+Normally, CTR mode will decrement once per Condition Test, resulting
+under normal circumstances that CTR reduces by up to VL in Horizontal-First
+Mode. Just as when v3.0B Branch-Conditional saves at
+least one instruction on tight inner loops through auto-decrementation
+of CTR, likewise it is also possible to save instruction count for
+SVP64 loops in both Vertical-First and Horizontal-First Mode, particularly
+in circumstances where there is conditional interaction between the
+element computation and testing, and the continuation (or otherwise)
+of a given loop. The potential combinations of interactions is why CTR
+testing options have been added.
+
+If both CTR-test and VLSET Modes are requested, then because the CTR decrement is on a per element basis, the total amount that CTR is decremented
+by will end up being VL *after* truncation (should that occur). In
+other words, the order is (as can be seen in pseudocode, below):
+
+1. compute the test
+2. (optionally) decrement CTR
+3. (optionally) truncate VL
+4. decide (based on step 1) whether to terminate looping
+   (including not executing step 5)
+5. decide whether to branch.
+
+CTR-test mode and CTi interaction is as follows: note that
+`BO[2]` is still required to be clear for decrements to be
+considered.
+
+* **CTR-test=0, CTi=0**: CTR decrements on a per-element basis
+  if `BO[2]` is zero. Masked-out elements when `sz=0` are
+  skipped.
+* **CTR-test=0, CTi=1**: CTR decrements on a per-element basis
+  if `BO[2]` is zero and a masked-out element is skipped
+  (`sz=0` and predicate bit is zero). This one special case is the
+  **opposite** of other combinations.
+* **CTR-test=1, CTi=0**: CTR decrements on a per-element basis
+  if `BO[2]` is zero and the Condition Test succeeds.
+  Masked-out elements when `sz=0` are skipped.
+* **CTR-test=1, CTi=1**: CTR decrements on a per-element basis
+  if `BO[2]` is zero and the Condition Test *fails*.
+  Masked-out elements when `sz=0` are skipped.
+
+Note that, interestingly, due to the side-effects of `VLSET` mode
+it is actually useful to use Branch Conditional even
 to perform no actual branch operation, i.e to point to the instruction
-after the branch.
-
-In particular, svstep mode is still useful for Horizontal-First Mode
-particularly in combination with REMAP. All "loop end" conditions
-will be tested on a per-element basis and placed into a Vector of CRs
-starting from the point specified by the Branch `BI` field.  This Vector
-of CR Fields may then be subsequently used as a Predicate Mask, and,
-furthermore, if VLSET mode was requested, VL will have been set to the
-length of one of the loop endpoints, again as specified by the bit from
-the Branch `BI` field.
+after the branch. Truncation of VL would thus conditionally occur yet control
+flow alteration would not.
 
 Also, the unconditional bit `BO[0]` is still relevant when Predication
 is applied to the Branch because in `ALL` mode all nonmasked bits have
@@ -166,7 +202,7 @@ In short, Vectorised Branch becomes an extremely powerful tool.
 is used for explicit looping, where the looping is to terminate if the end
 of the Vector, VL, is reached. If however that loop is terminated early
 because VL is truncated, VLSET with Vertical-First becomes meaningless.
-Therefore, the option to decide whether truncation should occur if the
+Therefore, with `VSb`, the option to decide whether truncation should occur if the
 branch succeeds *or* if the branch condition fails allows for flexibility
 required.
 
@@ -190,6 +226,11 @@ In addition to the above, it is necessary to select whether, in `svstep`
 mode, the Vector CR Field is to be overwritten or not: in some cases it
 is useful to know but in others all that is needed is the branch itself.
 
+*Programming note: One important point is that SVP64 instructions are 64 bit.
+(8 bytes not 4). This needs to be taken into consideration when computing
+branch offsets: the offset is relative to the start of the instruction,
+which includes the SVP64 Prefix*
+
 Pseudocode for Horizontal-First Mode:
 
 ```
@@ -199,15 +240,13 @@ for srcstep in range(VL):
     if predicate[srcstep]:
         # get SVP64 extended CR field 0..127
         SVCRf = SVP64EXTRA(BI>>2)
-        if svstep_mode then
-            new_srcstep, CRbits = SVSTATE_NEXT(srcstep)
-            if BRc = 1 then # CR Vectorised overwritr
-                CR{SVCRf+srcstep} = CRbits
-        else
-            CRbits = CR{SVCRf}
+        CRbits = CR{SVCRf}
         testbit = CRbits[BI & 0b11]
         # testbit = CR[BI+32+srcstep*4]
     else if not SVRMmode.sz:
+      # inverted CTR test skip mode
+      if ¬BO[2] & CTRtest & ¬CTI then
+         CTR = CTR - 1
         continue
     else
         testbit = SVRMmode.SNZ
@@ -232,8 +271,6 @@ for srcstep in range(VL):
     else
         if el_cond_ok:
             break
-    if svstep_mode then
-        SVSTATE.srcstep = new_srcstep
     if SVCRf.scalar:
        break
 ```
@@ -243,16 +280,16 @@ Pseudocode for Vertical-First Mode:
 ```
 # get SVP64 extended CR field 0..127
 SVCRf = SVP64EXTRA(BI>>2)
-if svstep_mode then
-    new_srcstep, CRbits = SVSTATE_NEXT(srcstep)
-else
-    CRbits = CR{SVCRf}
+CRbits = CR{SVCRf}
 # select predicate bit or zero/one
 if predicate[srcstep]:
     if BRc = 1 then # CR0 vectorised
         CR{SVCRf+srcstep} = CRbits
     testbit = CRbits[BI & 0b11]
 else if not SVRMmode.sz:
+    # inverted CTR test skip mode
+    if ¬BO[2] & CTRtest & ¬CTI then
+       CTR = CTR - 1
     SVSTATE.srcstep = new_srcstep
     exit # no branch testing
 else
@@ -265,18 +302,19 @@ if VLSET and cond_ok = VSb then
         SVSTATE.VL = new_srcstep+1
     else
         SVSTATE.VL = new_srcstep
-if svstep_mode then
-    SVSTATE.srcstep = new_srcstep
 ```
 
-v3.0B branch pseudocode including LRu
+v3.0B branch pseudocode including LRu and CTR skipping
 
 ```
 if (mode_is_64bit) then M <- 0
 else M <- 32
-if ¬BO[2] then CTR <- CTR - 1
-ctr_ok <- BO[2] | ((CTR[M:63] != 0) ^ BO[3])
 cond_ok <- BO[0] | ¬(CR[BI+32] ^ BO[1])
+ctrdec = ¬BO[2]
+if CTRtest & (cond_ok ^ CTi) then
+   ctrdec = 0b0
+if ctrdec then CTR <- CTR - 1
+ctr_ok <- BO[2] | ((CTR[M:63] != 0) ^ BO[3])
 lr_ok <- SVRMmode.LRu
 if ctr_ok & cond_ok then
   if AA then NIA <-iea EXTS(BD || 0b00)