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 = {