Commit 8ad4e32be0 for qemu.org
commit 8ad4e32be0dd281bf4f1b849be588fee7058de67
Author: Richard Henderson <richard.henderson@linaro.org>
Date: Tue Aug 11 17:19:20 2026 -0700
tcg/aarch64: Use CTZ from FEAT_CSSC
We already have an expansion of CTZ using RBIT+CLZ,
but use the new insn with FEAT_CSSC is present.
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 1f784e8d46..1e64c5994e 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, TCG_REG_TMP0, a2, Irr_sf_CLZ);
+ }
}
static const TCGOutOpBinary outop_ctz = {