diff mbox series

[v2,070/101] target/arm: Introduce pred_count_test

Message ID 20250621235037.74091-71-richard.henderson@linaro.org
State New
Headers show
Series target/arm: Implement FEAT_SME2p1 | expand

Commit Message

Richard Henderson June 21, 2025, 11:50 p.m. UTC
For WHILE, we have the count of enabled predicates, so we don't
need to search to compute the PredTest result.  Reuse the logic
that will shortly be required for counted predicates.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/tcg/sve_helper.c | 62 +++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c
index e78d807ce1..df2cbf9b6e 100644
--- a/target/arm/tcg/sve_helper.c
+++ b/target/arm/tcg/sve_helper.c
@@ -4102,20 +4102,50 @@  uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
     return sum;
 }
 
+/* C.f. Arm pseudocode PredCountTest */
+static uint32_t pred_count_test(uint32_t elements, uint32_t count, bool invert)
+{
+    uint32_t flags;
+
+    if (count == 0) {
+        /*
+         * N = 0  !(first active)
+         * Z = 1  (none active)
+         * C = 1  !(not last active)
+         */
+        flags = 1;
+    } else if (!invert) {
+        /*
+         * N = 1  (first active)
+         * Z = 0  !(none active)
+         * C = ?  (not last active)
+         */
+        flags = (1u << 31) | 2;      /* N, Z */
+        flags |= count == elements;  /* C */
+    } else {
+        /*
+         * N = ?  (first active)
+         * Z = 0  !(none active)
+         * C = 0  !(not last active)
+         */
+        flags = 2;  /* Z, C */
+        flags |= (count == elements) << 31;  /* N */
+    }
+    return flags;
+}
+
 uint32_t HELPER(sve_whilel)(void *vd, uint32_t count, uint32_t pred_desc)
 {
     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
     intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
     uint64_t esz_mask = pred_esz_masks[esz];
     ARMPredicateReg *d = vd;
-    uint32_t flags;
-    intptr_t i;
+    intptr_t i, oprbits = oprsz * 8;
+
+    tcg_debug_assert(count <= oprbits);
 
     /* Begin with a zero predicate register.  */
-    flags = do_zero(d, oprsz);
-    if (count == 0) {
-        return flags;
-    }
+    do_zero(d, oprsz);
 
     /* Set all of the requested bits.  */
     for (i = 0; i < count / 64; ++i) {
@@ -4125,7 +4155,7 @@  uint32_t HELPER(sve_whilel)(void *vd, uint32_t count, uint32_t pred_desc)
         d->p[i] = MAKE_64BIT_MASK(0, count & 63) & esz_mask;
     }
 
-    return predtest_ones(d, oprsz, esz_mask);
+    return pred_count_test(oprbits, count, false);
 }
 
 uint32_t HELPER(sve_whileg)(void *vd, uint32_t count, uint32_t pred_desc)
@@ -4134,16 +4164,15 @@  uint32_t HELPER(sve_whileg)(void *vd, uint32_t count, uint32_t pred_desc)
     intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
     uint64_t esz_mask = pred_esz_masks[esz];
     ARMPredicateReg *d = vd;
-    intptr_t i, invcount, oprbits;
+    intptr_t i, invcount, oprbits = oprsz * 8;
     uint64_t bits;
 
-    if (count == 0) {
-        return do_zero(d, oprsz);
-    }
-
-    oprbits = oprsz * 8;
     tcg_debug_assert(count <= oprbits);
 
+    /* Begin with a zero predicate register.  */
+    do_zero(d, oprsz);
+
+    /* Set all of the requested bits.  */
     bits = esz_mask;
     if (oprbits & 63) {
         bits &= MAKE_64BIT_MASK(0, oprbits & 63);
@@ -4154,14 +4183,9 @@  uint32_t HELPER(sve_whileg)(void *vd, uint32_t count, uint32_t pred_desc)
         d->p[i] = bits;
         bits = esz_mask;
     }
-
     d->p[i] = bits & MAKE_64BIT_MASK(invcount & 63, 64);
 
-    while (--i >= 0) {
-        d->p[i] = 0;
-    }
-
-    return predtest_ones(d, oprsz, esz_mask);
+    return pred_count_test(oprbits, count, true);
 }
 
 /* Recursive reduction on a function;