@samitouri / QOSamiQemu / commits / 8ad4e32be0

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>

Richard Henderson committed Aug 11, 2026 at 17:19 UTC 8ad4e32be0dd281bf4f1b849be588fee7058de67
1 file changed +32 -11
tcg/aarch64/tcg-target.c.inc
+32 -11
@@ -535,6 +535,7 @@ typedef enum {
535
536 /* Data-processing (1 source) instructions. */
537 Irr_sf_CLZ = 0x5ac01000,
538 + Irr_sf_CTZ = 0x5ac01800,
539 Irr_sf_CNT = 0x5ac01c00,
540 Irr_sf_RBIT = 0x5ac00000,
541 Irr_sf_REV = 0x5ac00000, /* + size << 10 */
@@ -2213,24 +2214,30 @@ static const TCGOutOpBinary outop_andc = {
2214 .out_rrr = tgen_andc,
2215 };
2216
2216 -static void tgen_clz(TCGContext *s, TCGType type,
2217 - TCGReg a0, TCGReg a1, TCGReg a2)
2217 +static void tgen_clzctz(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
2218 + TCGReg a2, AArch64Insn insn)
2219 {
2220 tcg_out_cmp(s, type, TCG_COND_NE, a1, 0, true);
2220 - tcg_out_insn(s, rr_sf, CLZ, type, TCG_REG_TMP0, a1);
2221 + tcg_out_insn_rr_sf(s, insn, type, TCG_REG_TMP0, a1);
2222 tcg_out_insn(s, csel, CSEL, type, a0, TCG_REG_TMP0, a2, TCG_COND_NE);
2223 }
2224
2224 -static void tgen_clzi(TCGContext *s, TCGType type,
2225 - TCGReg a0, TCGReg a1, tcg_target_long a2)
2225 +static void tgen_clz(TCGContext *s, TCGType type,
2226 + TCGReg a0, TCGReg a1, TCGReg a2)
2227 +{
2228 + tgen_clzctz(s, type, a0, a1, a2, Irr_sf_CLZ);
2229 +}
2230 +
2231 +static void tgen_clzctzi(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
2232 + tcg_target_long a2, AArch64Insn insn)
2233 {
2234 if (a2 == (type == TCG_TYPE_I32 ? 32 : 64)) {
2228 - tcg_out_insn(s, rr_sf, CLZ, type, a0, a1);
2235 + tcg_out_insn_rr_sf(s, insn, type, a0, a1);
2236 return;
2237 }
2238
2239 tcg_out_cmp(s, type, TCG_COND_NE, a1, 0, true);
2233 - tcg_out_insn(s, rr_sf, CLZ, type, a0, a1);
2240 + tcg_out_insn_rr_sf(s, insn, type, a0, a1);
2241
2242 switch (a2) {
2243 case -1:
@@ -2246,6 +2253,12 @@ static void tgen_clzi(TCGContext *s, TCGType type,
2253 }
2254 }
2255
2256 +static void tgen_clzi(TCGContext *s, TCGType type,
2257 + TCGReg a0, TCGReg a1, tcg_target_long a2)
2258 +{
2259 + tgen_clzctzi(s, type, a0, a1, a2, Irr_sf_CLZ);
2260 +}
2261 +
2262 static const TCGOutOpBinary outop_clz = {
2263 .base.static_constraint = C_O1_I2(r, r, rAL),
2264 .out_rrr = tgen_clz,
@@ -2271,15 +2284,23 @@ static const TCGOutOpUnary outop_ctpop = {
2284 static void tgen_ctz(TCGContext *s, TCGType type,
2285 TCGReg a0, TCGReg a1, TCGReg a2)
2286 {
2274 - tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
2275 - tgen_clz(s, type, a0, TCG_REG_TMP0, a2);
2287 + if (cpuinfo & CPUINFO_CSSC) {
2288 + tgen_clzctz(s, type, a0, a1, a2, Irr_sf_CTZ);
2289 + } else {
2290 + tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
2291 + tgen_clzctz(s, type, a0, TCG_REG_TMP0, a2, Irr_sf_CLZ);
2292 + }
2293 }
2294
2295 static void tgen_ctzi(TCGContext *s, TCGType type,
2296 TCGReg a0, TCGReg a1, tcg_target_long a2)
2297 {
2281 - tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
2282 - tgen_clzi(s, type, a0, TCG_REG_TMP0, a2);
2298 + if (cpuinfo & CPUINFO_CSSC) {
2299 + tgen_clzctzi(s, type, a0, a1, a2, Irr_sf_CTZ);
2300 + } else {
2301 + tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
2302 + tgen_clzctzi(s, type, a0, TCG_REG_TMP0, a2, Irr_sf_CLZ);
2303 + }
2304 }
2305
2306 static const TCGOutOpBinary outop_ctz = {