All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] tcg: Add min/max opcodes
@ 2026-08-12  0:31 Richard Henderson
  2026-08-12  0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Richard Henderson @ 2026-08-12  0:31 UTC (permalink / raw)
  To: qemu-devel

Since two hosts now have (optional) support for min/max,
I thought it might be worth implementing natively.

While I was there, use some more of the FEAT_CSSC extension.


r~


Richard Henderson (7):
  tcg: Add integer min/max opcodes
  tcg/optimize: Handle min/max opcodes
  util/cpuinfo-aarch64: Detect FEAT_CSSC
  tcg/aarch64: Implement min/max with FEAT_CSSC
  target/riscv64: Implement min/max with Zbb
  tcg/aarch64: Implement ctpop with FEAT_CSSC
  tcg/aarch64: Use CTZ from FEAT_CSSC

 host/include/aarch64/host/cpuinfo.h |   1 +
 include/tcg/tcg-opc.h               |   4 +
 tcg/aarch64/tcg-target-con-set.h    |   2 +
 tcg/aarch64/tcg-target-con-str.h    |   2 +
 tcg/optimize.c                      |  52 +++++++++
 tcg/tcg-op.c                        |  48 ++++++--
 tcg/tcg.c                           |   4 +
 util/cpuinfo-aarch64.c              |  13 ++-
 docs/devel/tcg-ops.rst              |  14 ++-
 tcg/aarch64/tcg-target.c.inc        | 169 ++++++++++++++++++++++++++--
 tcg/loongarch64/tcg-target.c.inc    |  16 +++
 tcg/ppc64/tcg-target.c.inc          |  16 +++
 tcg/riscv64/tcg-target.c.inc        |  52 +++++++++
 tcg/s390x/tcg-target.c.inc          |  16 +++
 tcg/sparc64/tcg-target.c.inc        |  16 +++
 tcg/tci/tcg-target.c.inc            |  16 +++
 tcg/x86_64/tcg-target.c.inc         |  16 +++
 17 files changed, 435 insertions(+), 22 deletions(-)

-- 
2.43.0



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/7] tcg: Add integer min/max opcodes
  2026-08-12  0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
@ 2026-08-12  0:31 ` Richard Henderson
  2026-08-12  8:42   ` Alex Bennée
  2026-08-12  0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12  0:31 UTC (permalink / raw)
  To: qemu-devel

We already have these for vectors; replicate for integers.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/tcg/tcg-opc.h            |  4 +++
 tcg/tcg-op.c                     | 48 ++++++++++++++++++++++++++------
 tcg/tcg.c                        |  4 +++
 docs/devel/tcg-ops.rst           | 14 +++++++++-
 tcg/aarch64/tcg-target.c.inc     | 16 +++++++++++
 tcg/loongarch64/tcg-target.c.inc | 16 +++++++++++
 tcg/ppc64/tcg-target.c.inc       | 16 +++++++++++
 tcg/riscv64/tcg-target.c.inc     | 16 +++++++++++
 tcg/s390x/tcg-target.c.inc       | 16 +++++++++++
 tcg/sparc64/tcg-target.c.inc     | 16 +++++++++++
 tcg/tci/tcg-target.c.inc         | 16 +++++++++++
 tcg/x86_64/tcg-target.c.inc      | 16 +++++++++++
 12 files changed, 189 insertions(+), 9 deletions(-)

diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index 13c7f17f76..f3a81d5d7f 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -89,11 +89,15 @@ DEF(setcond, 1, 2, 1, TCG_OPF_INT)
 DEF(sextract, 1, 1, 2, TCG_OPF_INT)
 DEF(shl, 1, 2, 0, TCG_OPF_INT)
 DEF(shr, 1, 2, 0, TCG_OPF_INT)
+DEF(smax, 1, 2, 0, TCG_OPF_INT)
+DEF(smin, 1, 2, 0, TCG_OPF_INT)
 DEF(st8, 0, 2, 1, TCG_OPF_INT)
 DEF(st16, 0, 2, 1, TCG_OPF_INT)
 DEF(st32, 0, 2, 1, TCG_OPF_INT)
 DEF(st, 0, 2, 1, TCG_OPF_INT)
 DEF(sub, 1, 2, 0, TCG_OPF_INT)
+DEF(umax, 1, 2, 0, TCG_OPF_INT)
+DEF(umin, 1, 2, 0, TCG_OPF_INT)
 DEF(xor, 1, 2, 0, TCG_OPF_INT)
 
 DEF(addco, 1, 2, 0, TCG_OPF_INT | TCG_OPF_CARRY_OUT)
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index c302a484cd..e28944cf72 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -1294,22 +1294,38 @@ void tcg_gen_revbit32_i32(TCGv_i32 ret, TCGv_i32 arg)
 
 void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
 {
-    tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
+    if (tcg_op_supported(INDEX_op_smin, TCG_TYPE_I32, 0)) {
+        tcg_gen_op3_i32(INDEX_op_smin, ret, a, b);
+    } else {
+        tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
+    }
 }
 
 void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
 {
-    tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
+    if (tcg_op_supported(INDEX_op_umin, TCG_TYPE_I32, 0)) {
+        tcg_gen_op3_i32(INDEX_op_umin, ret, a, b);
+    } else {
+        tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
+    }
 }
 
 void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
 {
-    tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
+    if (tcg_op_supported(INDEX_op_smax, TCG_TYPE_I32, 0)) {
+        tcg_gen_op3_i32(INDEX_op_smax, ret, a, b);
+    } else {
+        tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
+    }
 }
 
 void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
 {
-    tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
+    if (tcg_op_supported(INDEX_op_umax, TCG_TYPE_I32, 0)) {
+        tcg_gen_op3_i32(INDEX_op_umax, ret, a, b);
+    } else {
+        tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
+    }
 }
 
 void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a)
@@ -2473,22 +2489,38 @@ void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
 
 void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
 {
-    tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
+    if (tcg_op_supported(INDEX_op_smin, TCG_TYPE_I64, 0)) {
+        tcg_gen_op3_i64(INDEX_op_smin, ret, a, b);
+    } else {
+        tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
+    }
 }
 
 void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
 {
-    tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
+    if (tcg_op_supported(INDEX_op_umin, TCG_TYPE_I64, 0)) {
+        tcg_gen_op3_i64(INDEX_op_umin, ret, a, b);
+    } else {
+        tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
+    }
 }
 
 void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
 {
-    tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
+    if (tcg_op_supported(INDEX_op_smax, TCG_TYPE_I64, 0)) {
+        tcg_gen_op3_i64(INDEX_op_smax, ret, a, b);
+    } else {
+        tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
+    }
 }
 
 void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
 {
-    tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
+    if (tcg_op_supported(INDEX_op_umax, TCG_TYPE_I64, 0)) {
+        tcg_gen_op3_i64(INDEX_op_umax, ret, a, b);
+    } else {
+        tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
+    }
 }
 
 void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 4c2207c6af..54f7906cb7 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -5512,6 +5512,10 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
     case INDEX_op_sar:
     case INDEX_op_shl:
     case INDEX_op_shr:
+    case INDEX_op_smax:
+    case INDEX_op_smin:
+    case INDEX_op_umax:
+    case INDEX_op_umin:
     case INDEX_op_xor:
         {
             const TCGOutOpBinary *out =
diff --git a/docs/devel/tcg-ops.rst b/docs/devel/tcg-ops.rst
index f2e9255dd9..d30db9ea65 100644
--- a/docs/devel/tcg-ops.rst
+++ b/docs/devel/tcg-ops.rst
@@ -317,6 +317,18 @@ Arithmetic
          pass 0 to *nh* to make a simple zero-extension of *nl*,
          so overflow should never occur.
 
+   * - smax *t0*, *t1*, *t2*
+
+       umax *t0*, *t1*, *t2*
+
+     - | *t0* = MAX(*t1*, *t2*), for signed and unsigned integers.
+
+   * - smin *t0*, *t1*, *t2*
+
+       umin *t0*, *t1*, *t2*
+
+     - | *t0* = MIN(*t1*, *t2*), for signed and unsigned integers.
+
 Logical
 -------
 
@@ -512,7 +524,7 @@ Misc
 
      - | Reverse the 64 bits of input *t1* with output in *dest*.
 
-Conditional moves
+Conditional motes
 -----------------
 
 .. list-table::
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 80995403e4..f5c185bbf4 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -2592,6 +2592,22 @@ static void tcg_out_set_borrow(TCGContext *s)
                  TCG_REG_XZR, TCG_REG_XZR, TCG_REG_XZR);
 }
 
+static const TCGOutOpBinary outop_smax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_smin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
 static void tgen_xor(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 7d89e80886..f65496a040 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1804,6 +1804,22 @@ static void tcg_out_set_borrow(TCGContext *s)
     g_assert_not_reached();
 }
 
+static const TCGOutOpBinary outop_smax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_smin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
 static void tgen_xor(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
diff --git a/tcg/ppc64/tcg-target.c.inc b/tcg/ppc64/tcg-target.c.inc
index 07dff67e84..cd1c234367 100644
--- a/tcg/ppc64/tcg-target.c.inc
+++ b/tcg/ppc64/tcg-target.c.inc
@@ -3281,6 +3281,22 @@ static void tcg_out_set_borrow(TCGContext *s)
     tcg_out32(s, ADDIC | TAI(TCG_REG_R0, TCG_REG_R0, 0));
 }
 
+static const TCGOutOpBinary outop_smax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_smin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
 static void tgen_xor(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc
index 8fd32644fe..723c21b3da 100644
--- a/tcg/riscv64/tcg-target.c.inc
+++ b/tcg/riscv64/tcg-target.c.inc
@@ -2404,6 +2404,22 @@ static void tcg_out_set_borrow(TCGContext *s)
     g_assert_not_reached();
 }
 
+static const TCGOutOpBinary outop_smax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_smin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
 static void tgen_xor(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index c481745c3f..4d1a779c47 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -2950,6 +2950,22 @@ static void tcg_out_set_borrow(TCGContext *s)
     tcg_out_insn(s, RR, CLR, TCG_REG_R0, TCG_REG_R0); /* cc = 0 */
 }
 
+static const TCGOutOpBinary outop_smax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_smin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
 static void tgen_xor(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index d6ed9d3362..35cd14a5b6 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -1917,6 +1917,22 @@ static void tcg_out_set_borrow(TCGContext *s)
     tcg_out_set_carry(s);  /* borrow == carry */
 }
 
+static const TCGOutOpBinary outop_smax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_smin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
 static void tgen_xor(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
index 1b61668517..4cd1c1431c 100644
--- a/tcg/tci/tcg-target.c.inc
+++ b/tcg/tci/tcg-target.c.inc
@@ -894,6 +894,22 @@ static void tcg_out_set_borrow(TCGContext *s)
     tcg_out_op_v(s, INDEX_op_tci_setcarry);  /* borrow == carry */
 }
 
+static const TCGOutOpBinary outop_smax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_smin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
 static void tgen_xor(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
diff --git a/tcg/x86_64/tcg-target.c.inc b/tcg/x86_64/tcg-target.c.inc
index 37acba9045..2c8f1f3e58 100644
--- a/tcg/x86_64/tcg-target.c.inc
+++ b/tcg/x86_64/tcg-target.c.inc
@@ -2977,6 +2977,22 @@ static void tcg_out_set_borrow(TCGContext *s)
     tcg_out8(s, OPC_STC);
 }
 
+static const TCGOutOpBinary outop_smax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_smin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umax = {
+    .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBinary outop_umin = {
+    .base.static_constraint = C_NotImplemented,
+};
+
 static void tgen_xor(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/7] tcg/optimize: Handle min/max opcodes
  2026-08-12  0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
  2026-08-12  0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
@ 2026-08-12  0:31 ` Richard Henderson
  2026-08-12  7:17   ` Philippe Mathieu-Daudé
  2026-08-12  8:46   ` Alex Bennée
  2026-08-12  0:31 ` [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC Richard Henderson
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 16+ messages in thread
From: Richard Henderson @ 2026-08-12  0:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/optimize.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index facf4c1e0f..d291c844ca 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -597,6 +597,30 @@ static uint64_t do_constant_folding_2(TCGOpcode op, TCGType type,
         }
         return (uint64_t)x % ((uint64_t)y ? : 1);
 
+    case INDEX_op_smax:
+        if (type == TCG_TYPE_I32) {
+            return MAX((int32_t)x, (int32_t)y);
+        }
+        return MAX((int64_t)x, (int64_t)y);
+
+    case INDEX_op_smin:
+        if (type == TCG_TYPE_I32) {
+            return MIN((int32_t)x, (int32_t)y);
+        }
+        return MIN((int64_t)x, (int64_t)y);
+
+    case INDEX_op_umax:
+        if (type == TCG_TYPE_I32) {
+            return MAX((uint32_t)x, (uint32_t)y);
+        }
+        return MAX((uint64_t)x, (uint64_t)y);
+
+    case INDEX_op_umin:
+        if (type == TCG_TYPE_I32) {
+            return MIN((uint32_t)x, (uint32_t)y);
+        }
+        return MIN((uint64_t)x, (uint64_t)y);
+
     default:
         g_assert_not_reached();
     }
@@ -2101,6 +2125,16 @@ static bool fold_mb(OptContext *ctx, TCGOp *op)
     return true;
 }
 
+static bool fold_minmax(OptContext *ctx, TCGOp *op, uint64_t bound)
+{
+    if (fold_const2_commutative(ctx, op) ||
+        fold_xi_to_i(ctx, op, bound) ||
+        fold_xx_to_x(ctx, op)) {
+        return true;
+    }
+    return finish_folding(ctx, op);
+}
+
 static bool fold_mov(OptContext *ctx, TCGOp *op)
 {
     return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]);
@@ -3258,6 +3292,14 @@ void tcg_optimize(TCGContext *s)
         case INDEX_op_sextract:
             done = fold_sextract(&ctx, op);
             break;
+        case INDEX_op_smax:
+            done = fold_minmax(&ctx, op, (ctx.type == TCG_TYPE_I32
+                                          ? INT32_MAX : INT64_MAX));
+            break;
+        case INDEX_op_smin:
+            done = fold_minmax(&ctx, op, (ctx.type == TCG_TYPE_I32
+                                          ? INT32_MIN : INT64_MIN));
+            break;
         case INDEX_op_sub:
             done = fold_sub(&ctx, op);
             break;
@@ -3273,6 +3315,16 @@ void tcg_optimize(TCGContext *s)
         case INDEX_op_sub_vec:
             done = fold_sub_vec(&ctx, op);
             break;
+        case INDEX_op_umax:
+            /*
+             * Note that 32-bit constants are stored sign extended,
+             * so (int32_t)UINT32_MAX == -1.
+             */
+            done = fold_minmax(&ctx, op, -1);
+            break;
+        case INDEX_op_umin:
+            done = fold_minmax(&ctx, op, 0);
+            break;
         case INDEX_op_xor:
         case INDEX_op_xor_vec:
             done = fold_xor(&ctx, op);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC
  2026-08-12  0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
  2026-08-12  0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
  2026-08-12  0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
@ 2026-08-12  0:31 ` Richard Henderson
  2026-08-12  3:35   ` Brad Smith
  2026-08-12  0:31 ` [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC Richard Henderson
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12  0:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 host/include/aarch64/host/cpuinfo.h |  1 +
 util/cpuinfo-aarch64.c              | 13 ++++++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/host/include/aarch64/host/cpuinfo.h b/host/include/aarch64/host/cpuinfo.h
index fe671534e4..c32c04dade 100644
--- a/host/include/aarch64/host/cpuinfo.h
+++ b/host/include/aarch64/host/cpuinfo.h
@@ -12,6 +12,7 @@
 #define CPUINFO_AES             (1u << 3)
 #define CPUINFO_PMULL           (1u << 4)
 #define CPUINFO_BTI             (1u << 5)
+#define CPUINFO_CSSC            (1u << 6)
 
 /* Initialized with a constructor. */
 extern unsigned cpuinfo;
diff --git a/util/cpuinfo-aarch64.c b/util/cpuinfo-aarch64.c
index 288074c08f..0b4f8a747d 100644
--- a/util/cpuinfo-aarch64.c
+++ b/util/cpuinfo-aarch64.c
@@ -72,6 +72,7 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
 
     unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2);
     info |= (hwcap2 & HWCAP2_BTI ? CPUINFO_BTI : 0);
+    info |= (hwcap2 & HWCAP2_CSSC ? CPUINFO_CSSC : 0);
 #endif
 #ifdef CONFIG_DARWIN
     info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
@@ -79,10 +80,11 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
     info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES;
     info |= sysctl_for_bool("hw.optional.arm.FEAT_PMULL") * CPUINFO_PMULL;
     info |= sysctl_for_bool("hw.optional.arm.FEAT_BTI") * CPUINFO_BTI;
+    info |= sysctl_for_bool("hw.optional.arm.FEAT_CSSC") * CPUINFO_CSSC;
 #endif
 #if defined(__OpenBSD__) && !defined(CONFIG_ELF_AUX_INFO)
     int mib[2];
-    uint64_t isar0;
+    uint64_t isar0, isar2;
     uint64_t pfr1;
     size_t len;
 
@@ -101,6 +103,15 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
         }
     }
 
+    mib[0] = CTL_MACHDEP;
+    mib[1] = CPU_ID_AA64ISAR2;
+    len = sizeof(isar2);
+    if (sysctl(mib, 2, &isar2, &len, NULL, 0) != -1) {
+        if (ID_AA64ISAR2_CSSC(isar2) >= ID_AA64ISAR2_CSSC_IMPL) {
+            info |= CPUINFO_CSSC;
+        }
+    }
+
     mib[0] = CTL_MACHDEP;
     mib[1] = CPU_ID_AA64PFR1;
     len = sizeof(pfr1);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC
  2026-08-12  0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
                   ` (2 preceding siblings ...)
  2026-08-12  0:31 ` [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC Richard Henderson
@ 2026-08-12  0:31 ` Richard Henderson
  2026-08-12  7:15   ` Philippe Mathieu-Daudé
  2026-08-12  0:31 ` [PATCH 5/7] target/riscv64: Implement min/max with Zbb Richard Henderson
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12  0:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/aarch64/tcg-target-con-set.h |   2 +
 tcg/aarch64/tcg-target-con-str.h |   2 +
 tcg/aarch64/tcg-target.c.inc     | 103 +++++++++++++++++++++++++++++--
 3 files changed, 103 insertions(+), 4 deletions(-)

diff --git a/tcg/aarch64/tcg-target-con-set.h b/tcg/aarch64/tcg-target-con-set.h
index d0622e65fb..dd84a9af58 100644
--- a/tcg/aarch64/tcg-target-con-set.h
+++ b/tcg/aarch64/tcg-target-con-set.h
@@ -24,6 +24,8 @@ C_O1_I2(r, r, rAL)
 C_O1_I2(r, r, rC)
 C_O1_I2(r, r, ri)
 C_O1_I2(r, r, rL)
+C_O1_I2(r, r, rS)
+C_O1_I2(r, r, rU)
 C_O1_I2(r, rZ, rA)
 C_O1_I2(r, rz, rMZ)
 C_O1_I2(r, rz, rz)
diff --git a/tcg/aarch64/tcg-target-con-str.h b/tcg/aarch64/tcg-target-con-str.h
index 48e1722c68..fef75e8a76 100644
--- a/tcg/aarch64/tcg-target-con-str.h
+++ b/tcg/aarch64/tcg-target-con-str.h
@@ -21,4 +21,6 @@ CONST('L', TCG_CT_CONST_LIMM)
 CONST('M', TCG_CT_CONST_MONE)
 CONST('O', TCG_CT_CONST_ORRI)
 CONST('N', TCG_CT_CONST_ANDI)
+CONST('S', TCG_CT_CONST_S8)
+CONST('U', TCG_CT_CONST_U8)
 CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index f5c185bbf4..55b3be0b96 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -152,6 +152,8 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
 #define TCG_CT_CONST_ORRI 0x1000
 #define TCG_CT_CONST_ANDI 0x2000
 #define TCG_CT_CONST_CMP  0x4000
+#define TCG_CT_CONST_S8   0x8000
+#define TCG_CT_CONST_U8   0x10000
 
 #define ALL_GENERAL_REGS  0xffffffffu
 #define ALL_VECTOR_REGS   0xffffffff00000000ull
@@ -320,6 +322,12 @@ static bool tcg_target_const_match(int64_t val, int ct,
     if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
         return 1;
     }
+    if ((ct & TCG_CT_CONST_S8) && val == (int8_t)val) {
+        return 1;
+    }
+    if ((ct & TCG_CT_CONST_U8) && val == (uint8_t)val) {
+        return 1;
+    }
     if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
         return 1;
     }
@@ -472,6 +480,12 @@ typedef enum {
     Iaddsub_imm_SUBI  = 0x51000000,
     Iaddsub_imm_SUBSI = 0x71000000,
 
+    /* Min/max immediate instructions. */
+    Iminmax_imm_SMAXI = 0x11c00000,
+    Iminmax_imm_UMAXI = 0x11c40000,
+    Iminmax_imm_SMINI = 0x11c80000,
+    Iminmax_imm_UMINI = 0x11cc0000,
+
     /* Bitfield instructions.  */
     Ibitfield_BFM     = 0x33000000,
     Ibitfield_SBFM    = 0x13000000,
@@ -533,6 +547,10 @@ typedef enum {
     Irrr_UMULH         = 0x9bc07c00,
     Irrr_UDIV          = 0x1ac00800,
     Irrr_SDIV          = 0x1ac00c00,
+    Irrr_SMAX          = 0x1ac00600,
+    Irrr_UMAX          = 0x1ac00640,
+    Irrr_SMIN          = 0x1ac00680,
+    Irrr_UMIN          = 0x1ac006c0,
 
     /* Data-processing (3 source) instructions.  */
     Irrrr_MADD         = 0x1b000000,
@@ -737,6 +755,13 @@ static void tcg_out_insn_addsub_imm(TCGContext *s, AArch64Insn insn,
     tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
 }
 
+static void tcg_out_insn_minmax_imm(TCGContext *s, AArch64Insn insn,
+                                    TCGType ext, TCGReg rd, TCGReg rn,
+                                    uint8_t imm)
+{
+    tcg_out32(s, insn | ext << 31 | imm << 10 | rn << 5 | rd);
+}
+
 /* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
    (Logical immediate).  Both insn groups have N, IMMR and IMMS fields
    that feed the DecodeBitMasks pseudo function.  */
@@ -2592,20 +2617,90 @@ static void tcg_out_set_borrow(TCGContext *s)
                  TCG_REG_XZR, TCG_REG_XZR, TCG_REG_XZR);
 }
 
+static TCGConstraintSetIndex cset_sminmax(TCGType type, unsigned flags)
+{
+    return cpuinfo & CPUINFO_CSSC ? C_O1_I2(r, r, rS) : C_NotImplemented;
+}
+
+static void tgen_smax(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_out_insn(s, rrr, SMAX, type, a0, a1, a2);
+}
+
+static void tgen_smaxi(TCGContext *s, TCGType type,
+                       TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+    tcg_out_insn(s, minmax_imm, SMAXI, type, a0, a1, a2);
+}
+
 static const TCGOutOpBinary outop_smax = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_sminmax,
+    .out_rrr = tgen_smax,
+    .out_rri = tgen_smaxi,
 };
 
+static void tgen_smin(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_out_insn(s, rrr, SMIN, type, a0, a1, a2);
+}
+
+static void tgen_smini(TCGContext *s, TCGType type,
+                       TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+    tcg_out_insn(s, minmax_imm, SMINI, type, a0, a1, a2);
+}
+
 static const TCGOutOpBinary outop_smin = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_sminmax,
+    .out_rrr = tgen_smin,
+    .out_rri = tgen_smini,
 };
 
+static TCGConstraintSetIndex cset_uminmax(TCGType type, unsigned flags)
+{
+    return cpuinfo & CPUINFO_CSSC ? C_O1_I2(r, r, rU) : C_NotImplemented;
+}
+
+static void tgen_umax(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_out_insn(s, rrr, UMAX, type, a0, a1, a2);
+}
+
+static void tgen_umaxi(TCGContext *s, TCGType type,
+                       TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+    tcg_out_insn(s, minmax_imm, UMAXI, type, a0, a1, a2);
+}
+
 static const TCGOutOpBinary outop_umax = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_uminmax,
+    .out_rrr = tgen_umax,
+    .out_rri = tgen_umaxi,
 };
 
+static void tgen_umin(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_out_insn(s, rrr, UMIN, type, a0, a1, a2);
+}
+
+static void tgen_umini(TCGContext *s, TCGType type,
+                       TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+    tcg_out_insn(s, minmax_imm, UMINI, type, a0, a1, a2);
+}
+
 static const TCGOutOpBinary outop_umin = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_uminmax,
+    .out_rrr = tgen_umin,
+    .out_rri = tgen_umini,
 };
 
 static void tgen_xor(TCGContext *s, TCGType type,
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 5/7] target/riscv64: Implement min/max with Zbb
  2026-08-12  0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
                   ` (3 preceding siblings ...)
  2026-08-12  0:31 ` [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC Richard Henderson
@ 2026-08-12  0:31 ` Richard Henderson
  2026-08-12  0:31 ` [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC Richard Henderson
  2026-08-12  0:31 ` [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC Richard Henderson
  6 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2026-08-12  0:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/riscv64/tcg-target.c.inc | 44 ++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc
index 723c21b3da..2ce9d47a63 100644
--- a/tcg/riscv64/tcg-target.c.inc
+++ b/tcg/riscv64/tcg-target.c.inc
@@ -233,6 +233,10 @@ typedef enum {
     OPC_CPOPW  = 0x6020101b,
     OPC_CTZ    = 0x60101013,
     OPC_CTZW   = 0x6010101b,
+    OPC_MAX    = 0x0a006033,
+    OPC_MAXU   = 0x0a007033,
+    OPC_MIN    = 0x0a004033,
+    OPC_MINU   = 0x0a005033,
     OPC_ORN    = 0x40006033,
     OPC_REV8   = 0x6b805013,
     OPC_ROL    = 0x60001033,
@@ -2404,20 +2408,52 @@ static void tcg_out_set_borrow(TCGContext *s)
     g_assert_not_reached();
 }
 
+static void tgen_smax(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_out_opc_reg(s, OPC_MAX, a0, a1, a2);
+}
+
 static const TCGOutOpBinary outop_smax = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_zbb_rrr,
+    .out_rrr = tgen_smax,
 };
 
+static void tgen_smin(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_out_opc_reg(s, OPC_MIN, a0, a1, a2);
+}
+
 static const TCGOutOpBinary outop_smin = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_zbb_rrr,
+    .out_rrr = tgen_smin,
 };
 
+static void tgen_umax(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_out_opc_reg(s, OPC_MAXU, a0, a1, a2);
+}
+
 static const TCGOutOpBinary outop_umax = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_zbb_rrr,
+    .out_rrr = tgen_umax,
 };
 
+static void tgen_umin(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_out_opc_reg(s, OPC_MINU, a0, a1, a2);
+}
+
 static const TCGOutOpBinary outop_umin = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_zbb_rrr,
+    .out_rrr = tgen_umin,
 };
 
 static void tgen_xor(TCGContext *s, TCGType type,
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC
  2026-08-12  0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
                   ` (4 preceding siblings ...)
  2026-08-12  0:31 ` [PATCH 5/7] target/riscv64: Implement min/max with Zbb Richard Henderson
@ 2026-08-12  0:31 ` Richard Henderson
  2026-08-12  6:59   ` Philippe Mathieu-Daudé
  2026-08-12  0:31 ` [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC Richard Henderson
  6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12  0:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/aarch64/tcg-target.c.inc | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 55b3be0b96..1f784e8d46 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -535,6 +535,7 @@ typedef enum {
 
     /* Data-processing (1 source) instructions.  */
     Irr_sf_CLZ         = 0x5ac01000,
+    Irr_sf_CNT         = 0x5ac01c00,
     Irr_sf_RBIT        = 0x5ac00000,
     Irr_sf_REV         = 0x5ac00000, /* + size << 10 */
 
@@ -2251,8 +2252,20 @@ static const TCGOutOpBinary outop_clz = {
     .out_rri = tgen_clzi,
 };
 
+static TCGConstraintSetIndex cset_ctpop(TCGType type, unsigned flags)
+{
+    return cpuinfo & CPUINFO_CSSC ? C_O1_I1(r, r) : C_NotImplemented;
+}
+
+static void tgen_ctpop(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
+{
+    tcg_out_insn(s, rr_sf, CNT, type, a0, a1);
+}
+
 static const TCGOutOpUnary outop_ctpop = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_ctpop,
+    .out_rr = tgen_ctpop,
 };
 
 static void tgen_ctz(TCGContext *s, TCGType type,
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC
  2026-08-12  0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
                   ` (5 preceding siblings ...)
  2026-08-12  0:31 ` [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC Richard Henderson
@ 2026-08-12  0:31 ` Richard Henderson
  2026-08-12  7:06   ` Philippe Mathieu-Daudé
  6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12  0:31 UTC (permalink / raw)
  To: qemu-devel

We already have an expansion of CTZ using RBIT+CLZ,
but use the new insn with FEAT_CSSC is present.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/aarch64/tcg-target.c.inc | 43 +++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 1f784e8d46..ce5c039557 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -535,6 +535,7 @@ typedef enum {
 
     /* Data-processing (1 source) instructions.  */
     Irr_sf_CLZ         = 0x5ac01000,
+    Irr_sf_CTZ         = 0x5ac01800,
     Irr_sf_CNT         = 0x5ac01c00,
     Irr_sf_RBIT        = 0x5ac00000,
     Irr_sf_REV         = 0x5ac00000, /* + size << 10 */
@@ -2213,24 +2214,30 @@ static const TCGOutOpBinary outop_andc = {
     .out_rrr = tgen_andc,
 };
 
-static void tgen_clz(TCGContext *s, TCGType type,
-                     TCGReg a0, TCGReg a1, TCGReg a2)
+static void tgen_clzctz(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
+                        TCGReg a2, AArch64Insn insn)
 {
     tcg_out_cmp(s, type, TCG_COND_NE, a1, 0, true);
-    tcg_out_insn(s, rr_sf, CLZ, type, TCG_REG_TMP0, a1);
+    tcg_out_insn_rr_sf(s, insn, type, TCG_REG_TMP0, a1);
     tcg_out_insn(s, csel, CSEL, type, a0, TCG_REG_TMP0, a2, TCG_COND_NE);
 }
 
-static void tgen_clzi(TCGContext *s, TCGType type,
-                      TCGReg a0, TCGReg a1, tcg_target_long a2)
+static void tgen_clz(TCGContext *s, TCGType type,
+                     TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tgen_clzctz(s, type, a0, a1, a2, Irr_sf_CLZ);
+}
+
+static void tgen_clzctzi(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
+                         tcg_target_long a2, AArch64Insn insn)
 {
     if (a2 == (type == TCG_TYPE_I32 ? 32 : 64)) {
-        tcg_out_insn(s, rr_sf, CLZ, type, a0, a1);
+        tcg_out_insn_rr_sf(s, insn, type, a0, a1);
         return;
     }
 
     tcg_out_cmp(s, type, TCG_COND_NE, a1, 0, true);
-    tcg_out_insn(s, rr_sf, CLZ, type, a0, a1);
+    tcg_out_insn_rr_sf(s, insn, type, a0, a1);
 
     switch (a2) {
     case -1:
@@ -2246,6 +2253,12 @@ static void tgen_clzi(TCGContext *s, TCGType type,
     }
 }
 
+static void tgen_clzi(TCGContext *s, TCGType type,
+                      TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+    tgen_clzctzi(s, type, a0, a1, a2, Irr_sf_CLZ);
+}
+
 static const TCGOutOpBinary outop_clz = {
     .base.static_constraint = C_O1_I2(r, r, rAL),
     .out_rrr = tgen_clz,
@@ -2271,15 +2284,23 @@ static const TCGOutOpUnary outop_ctpop = {
 static void tgen_ctz(TCGContext *s, TCGType type,
                      TCGReg a0, TCGReg a1, TCGReg a2)
 {
-    tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
-    tgen_clz(s, type, a0, TCG_REG_TMP0, a2);
+    if (cpuinfo & CPUINFO_CSSC) {
+        tgen_clzctz(s, type, a0, a1, a2, Irr_sf_CTZ);
+    } else {
+        tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
+        tgen_clzctz(s, type, a0, TCG_REG_TMP0, a2, Irr_sf_CLZ);
+    }
 }
 
 static void tgen_ctzi(TCGContext *s, TCGType type,
                       TCGReg a0, TCGReg a1, tcg_target_long a2)
 {
-    tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
-    tgen_clzi(s, type, a0, TCG_REG_TMP0, a2);
+    if (cpuinfo & CPUINFO_CSSC) {
+        tgen_clzctzi(s, type, a0, a1, a2, Irr_sf_CTZ);
+    } else {
+        tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
+        tgen_clzctzi(s, type, a0, a1, a2, Irr_sf_CLZ);
+    }
 }
 
 static const TCGOutOpBinary outop_ctz = {
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC
  2026-08-12  0:31 ` [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC Richard Henderson
@ 2026-08-12  3:35   ` Brad Smith
  2026-08-12 13:56     ` Richard Henderson
  0 siblings, 1 reply; 16+ messages in thread
From: Brad Smith @ 2026-08-12  3:35 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

On 2026-08-11 8:31 p.m., Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   host/include/aarch64/host/cpuinfo.h |  1 +
>   util/cpuinfo-aarch64.c              | 13 ++++++++++++-
>   2 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/host/include/aarch64/host/cpuinfo.h b/host/include/aarch64/host/cpuinfo.h
> index fe671534e4..c32c04dade 100644
> --- a/host/include/aarch64/host/cpuinfo.h
> +++ b/host/include/aarch64/host/cpuinfo.h
> @@ -12,6 +12,7 @@
>   #define CPUINFO_AES             (1u << 3)
>   #define CPUINFO_PMULL           (1u << 4)
>   #define CPUINFO_BTI             (1u << 5)
> +#define CPUINFO_CSSC            (1u << 6)
>   
>   /* Initialized with a constructor. */
>   extern unsigned cpuinfo;
> diff --git a/util/cpuinfo-aarch64.c b/util/cpuinfo-aarch64.c
> index 288074c08f..0b4f8a747d 100644
> --- a/util/cpuinfo-aarch64.c
> +++ b/util/cpuinfo-aarch64.c
> @@ -72,6 +72,7 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
>   
>       unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2);
>       info |= (hwcap2 & HWCAP2_BTI ? CPUINFO_BTI : 0);
> +    info |= (hwcap2 & HWCAP2_CSSC ? CPUINFO_CSSC : 0);
>   #endif
>   #ifdef CONFIG_DARWIN
>       info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
> @@ -79,10 +80,11 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
>       info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES;
>       info |= sysctl_for_bool("hw.optional.arm.FEAT_PMULL") * CPUINFO_PMULL;
>       info |= sysctl_for_bool("hw.optional.arm.FEAT_BTI") * CPUINFO_BTI;
> +    info |= sysctl_for_bool("hw.optional.arm.FEAT_CSSC") * CPUINFO_CSSC;
>   #endif
>   #if defined(__OpenBSD__) && !defined(CONFIG_ELF_AUX_INFO)
>       int mib[2];
> -    uint64_t isar0;
> +    uint64_t isar0, isar2;
>       uint64_t pfr1;
>       size_t len;
>   
> @@ -101,6 +103,15 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
>           }
>       }
>   
> +    mib[0] = CTL_MACHDEP;
> +    mib[1] = CPU_ID_AA64ISAR2;
> +    len = sizeof(isar2);
> +    if (sysctl(mib, 2, &isar2, &len, NULL, 0) != -1) {
> +        if (ID_AA64ISAR2_CSSC(isar2) >= ID_AA64ISAR2_CSSC_IMPL) {
> +            info |= CPUINFO_CSSC;
> +        }
> +    }
> +
>       mib[0] = CTL_MACHDEP;
>       mib[1] = CPU_ID_AA64PFR1;
>       len = sizeof(pfr1);

You can remove the bottom chunk. Any OpenBSD release that has the 
ID_AA64ISAR2_CSSC
and ID_AA64ISAR2_CSSC_IMPL constants is also covered by elf_aux_info() 
which is the
first chunk.

ID_AA64ISAR2_CSSC_IMPL



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC
  2026-08-12  0:31 ` [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC Richard Henderson
@ 2026-08-12  6:59   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 16+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-12  6:59 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

On 12/8/26 02:31, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   tcg/aarch64/tcg-target.c.inc | 15 ++++++++++++++-
>   1 file changed, 14 insertions(+), 1 deletion(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC
  2026-08-12  0:31 ` [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC Richard Henderson
@ 2026-08-12  7:06   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 16+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-12  7:06 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

On 12/8/26 02:31, Richard Henderson wrote:
> We already have an expansion of CTZ using RBIT+CLZ,
> but use the new insn with FEAT_CSSC is present.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   tcg/aarch64/tcg-target.c.inc | 43 +++++++++++++++++++++++++++---------
>   1 file changed, 32 insertions(+), 11 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC
  2026-08-12  0:31 ` [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC Richard Henderson
@ 2026-08-12  7:15   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 16+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-12  7:15 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

On 12/8/26 02:31, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   tcg/aarch64/tcg-target-con-set.h |   2 +
>   tcg/aarch64/tcg-target-con-str.h |   2 +
>   tcg/aarch64/tcg-target.c.inc     | 103 +++++++++++++++++++++++++++++--
>   3 files changed, 103 insertions(+), 4 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/7] tcg/optimize: Handle min/max opcodes
  2026-08-12  0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
@ 2026-08-12  7:17   ` Philippe Mathieu-Daudé
  2026-08-12  8:46   ` Alex Bennée
  1 sibling, 0 replies; 16+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-12  7:17 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

On 12/8/26 02:31, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   tcg/optimize.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 52 insertions(+)

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/7] tcg: Add integer min/max opcodes
  2026-08-12  0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
@ 2026-08-12  8:42   ` Alex Bennée
  0 siblings, 0 replies; 16+ messages in thread
From: Alex Bennée @ 2026-08-12  8:42 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

Richard Henderson <richard.henderson@linaro.org> writes:

> We already have these for vectors; replicate for integers.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/tcg/tcg-opc.h            |  4 +++
>  tcg/tcg-op.c                     | 48 ++++++++++++++++++++++++++------
>  tcg/tcg.c                        |  4 +++
>  docs/devel/tcg-ops.rst           | 14 +++++++++-
>  tcg/aarch64/tcg-target.c.inc     | 16 +++++++++++
>  tcg/loongarch64/tcg-target.c.inc | 16 +++++++++++
>  tcg/ppc64/tcg-target.c.inc       | 16 +++++++++++
>  tcg/riscv64/tcg-target.c.inc     | 16 +++++++++++
>  tcg/s390x/tcg-target.c.inc       | 16 +++++++++++
>  tcg/sparc64/tcg-target.c.inc     | 16 +++++++++++
>  tcg/tci/tcg-target.c.inc         | 16 +++++++++++
>  tcg/x86_64/tcg-target.c.inc      | 16 +++++++++++
>  12 files changed, 189 insertions(+), 9 deletions(-)
>
> diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
> index 13c7f17f76..f3a81d5d7f 100644
> --- a/include/tcg/tcg-opc.h
> +++ b/include/tcg/tcg-opc.h
> @@ -89,11 +89,15 @@ DEF(setcond, 1, 2, 1, TCG_OPF_INT)
>  DEF(sextract, 1, 1, 2, TCG_OPF_INT)
>  DEF(shl, 1, 2, 0, TCG_OPF_INT)
>  DEF(shr, 1, 2, 0, TCG_OPF_INT)
> +DEF(smax, 1, 2, 0, TCG_OPF_INT)
> +DEF(smin, 1, 2, 0, TCG_OPF_INT)
>  DEF(st8, 0, 2, 1, TCG_OPF_INT)
>  DEF(st16, 0, 2, 1, TCG_OPF_INT)
>  DEF(st32, 0, 2, 1, TCG_OPF_INT)
>  DEF(st, 0, 2, 1, TCG_OPF_INT)
>  DEF(sub, 1, 2, 0, TCG_OPF_INT)
> +DEF(umax, 1, 2, 0, TCG_OPF_INT)
> +DEF(umin, 1, 2, 0, TCG_OPF_INT)
>  DEF(xor, 1, 2, 0, TCG_OPF_INT)
>  
>  DEF(addco, 1, 2, 0, TCG_OPF_INT | TCG_OPF_CARRY_OUT)
> diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
> index c302a484cd..e28944cf72 100644
> --- a/tcg/tcg-op.c
> +++ b/tcg/tcg-op.c
> @@ -1294,22 +1294,38 @@ void tcg_gen_revbit32_i32(TCGv_i32 ret, TCGv_i32 arg)
>  
>  void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
>  {
> -    tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
> +    if (tcg_op_supported(INDEX_op_smin, TCG_TYPE_I32, 0)) {
> +        tcg_gen_op3_i32(INDEX_op_smin, ret, a, b);
> +    } else {
> +        tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
> +    }
>  }
>  
>  void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
>  {
> -    tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
> +    if (tcg_op_supported(INDEX_op_umin, TCG_TYPE_I32, 0)) {
> +        tcg_gen_op3_i32(INDEX_op_umin, ret, a, b);
> +    } else {
> +        tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
> +    }
>  }
>  
>  void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
>  {
> -    tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
> +    if (tcg_op_supported(INDEX_op_smax, TCG_TYPE_I32, 0)) {
> +        tcg_gen_op3_i32(INDEX_op_smax, ret, a, b);
> +    } else {
> +        tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
> +    }
>  }
>  
>  void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
>  {
> -    tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
> +    if (tcg_op_supported(INDEX_op_umax, TCG_TYPE_I32, 0)) {
> +        tcg_gen_op3_i32(INDEX_op_umax, ret, a, b);
> +    } else {
> +        tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
> +    }
>  }
>  
>  void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a)
> @@ -2473,22 +2489,38 @@ void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
>  
>  void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
>  {
> -    tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
> +    if (tcg_op_supported(INDEX_op_smin, TCG_TYPE_I64, 0)) {
> +        tcg_gen_op3_i64(INDEX_op_smin, ret, a, b);
> +    } else {
> +        tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
> +    }
>  }
>  
>  void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
>  {
> -    tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
> +    if (tcg_op_supported(INDEX_op_umin, TCG_TYPE_I64, 0)) {
> +        tcg_gen_op3_i64(INDEX_op_umin, ret, a, b);
> +    } else {
> +        tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
> +    }
>  }
>  
>  void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
>  {
> -    tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
> +    if (tcg_op_supported(INDEX_op_smax, TCG_TYPE_I64, 0)) {
> +        tcg_gen_op3_i64(INDEX_op_smax, ret, a, b);
> +    } else {
> +        tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
> +    }
>  }
>  
>  void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
>  {
> -    tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
> +    if (tcg_op_supported(INDEX_op_umax, TCG_TYPE_I64, 0)) {
> +        tcg_gen_op3_i64(INDEX_op_umax, ret, a, b);
> +    } else {
> +        tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
> +    }
>  }
>  
>  void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a)
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index 4c2207c6af..54f7906cb7 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -5512,6 +5512,10 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
>      case INDEX_op_sar:
>      case INDEX_op_shl:
>      case INDEX_op_shr:
> +    case INDEX_op_smax:
> +    case INDEX_op_smin:
> +    case INDEX_op_umax:
> +    case INDEX_op_umin:
>      case INDEX_op_xor:
>          {
>              const TCGOutOpBinary *out =
> diff --git a/docs/devel/tcg-ops.rst b/docs/devel/tcg-ops.rst
> index f2e9255dd9..d30db9ea65 100644
> --- a/docs/devel/tcg-ops.rst
> +++ b/docs/devel/tcg-ops.rst
> @@ -317,6 +317,18 @@ Arithmetic
>           pass 0 to *nh* to make a simple zero-extension of *nl*,
>           so overflow should never occur.
>  
> +   * - smax *t0*, *t1*, *t2*
> +
> +       umax *t0*, *t1*, *t2*
> +
> +     - | *t0* = MAX(*t1*, *t2*), for signed and unsigned integers.
> +
> +   * - smin *t0*, *t1*, *t2*
> +
> +       umin *t0*, *t1*, *t2*
> +
> +     - | *t0* = MIN(*t1*, *t2*), for signed and unsigned integers.
> +
>  Logical
>  -------
>  
> @@ -512,7 +524,7 @@ Misc
>  
>       - | Reverse the 64 bits of input *t1* with output in *dest*.
>  
> -Conditional moves
> +Conditional motes
>  -----------------

A typo snuck in....


Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/7] tcg/optimize: Handle min/max opcodes
  2026-08-12  0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
  2026-08-12  7:17   ` Philippe Mathieu-Daudé
@ 2026-08-12  8:46   ` Alex Bennée
  1 sibling, 0 replies; 16+ messages in thread
From: Alex Bennée @ 2026-08-12  8:46 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

Richard Henderson <richard.henderson@linaro.org> writes:

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC
  2026-08-12  3:35   ` Brad Smith
@ 2026-08-12 13:56     ` Richard Henderson
  0 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 13:56 UTC (permalink / raw)
  To: Brad Smith, qemu-devel

On 8/11/26 20:35, Brad Smith wrote:
>> @@ -101,6 +103,15 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
>>           }
>>       }
>> +    mib[0] = CTL_MACHDEP;
>> +    mib[1] = CPU_ID_AA64ISAR2;
>> +    len = sizeof(isar2);
>> +    if (sysctl(mib, 2, &isar2, &len, NULL, 0) != -1) {
>> +        if (ID_AA64ISAR2_CSSC(isar2) >= ID_AA64ISAR2_CSSC_IMPL) {
>> +            info |= CPUINFO_CSSC;
>> +        }
>> +    }
>> +
>>       mib[0] = CTL_MACHDEP;
>>       mib[1] = CPU_ID_AA64PFR1;
>>       len = sizeof(pfr1);
> 
> You can remove the bottom chunk. Any OpenBSD release that has the ID_AA64ISAR2_CSSC
> and ID_AA64ISAR2_CSSC_IMPL constants is also covered by elf_aux_info() which is the
> first chunk.

Right-o.  Thanks!

r~


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-08-12 13:56 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12  0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
2026-08-12  0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
2026-08-12  8:42   ` Alex Bennée
2026-08-12  0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
2026-08-12  7:17   ` Philippe Mathieu-Daudé
2026-08-12  8:46   ` Alex Bennée
2026-08-12  0:31 ` [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC Richard Henderson
2026-08-12  3:35   ` Brad Smith
2026-08-12 13:56     ` Richard Henderson
2026-08-12  0:31 ` [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC Richard Henderson
2026-08-12  7:15   ` Philippe Mathieu-Daudé
2026-08-12  0:31 ` [PATCH 5/7] target/riscv64: Implement min/max with Zbb Richard Henderson
2026-08-12  0:31 ` [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC Richard Henderson
2026-08-12  6:59   ` Philippe Mathieu-Daudé
2026-08-12  0:31 ` [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC Richard Henderson
2026-08-12  7:06   ` Philippe Mathieu-Daudé

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.