|
From: Andreas A. <ar...@so...> - 2026-03-10 18:40:05
|
https://sourceware.org/cgit/valgrind/commit/?id=580baf807566236edbde5c7fbc960b51b0a7cbbc commit 580baf807566236edbde5c7fbc960b51b0a7cbbc Author: Andreas Arnez <ar...@li...> Date: Tue Mar 10 18:20:01 2026 +0100 s390x: Simplify POPCNT logic in host_s390_defs.c With the exploitation of the POPCNT instruction, the new s390_insn_tag S390_INSN_POPCNT was introduced. This requires handling the new tag in s390_get_reg_usage(), s390_insn_map_regs(), and s390_insn_as_string(), as well as providing the interface function s390_insn_popcnt(). All of this can go away when using the existing S390_INSN_UNOP instead and just adding a new unary operation type to s390_unop_t. So do this. Diff: --- VEX/priv/host_s390_defs.c | 119 ++++++++++++++++------------------------------ VEX/priv/host_s390_defs.h | 7 +-- VEX/priv/host_s390_isel.c | 2 +- 3 files changed, 44 insertions(+), 84 deletions(-) diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c index 58c891878b..28b66ef5c7 100644 --- a/VEX/priv/host_s390_defs.c +++ b/VEX/priv/host_s390_defs.c @@ -821,11 +821,6 @@ s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn) s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src); break; - case S390_INSN_POPCNT: - addHRegUse(u, HRmWrite, insn->variant.popcnt.dst); - s390_opnd_RMI_get_reg_usage(u, insn->variant.popcnt.src); - break; - case S390_INSN_UNOP: addHRegUse(u, HRmWrite, insn->variant.unop.dst); s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src); @@ -1182,11 +1177,6 @@ s390_insn_map_regs(HRegRemap *m, s390_insn *insn) s390_opnd_RMI_map_regs(m, &insn->variant.clz.src); break; - case S390_INSN_POPCNT: - insn->variant.popcnt.dst = lookupHRegRemap(m, insn->variant.popcnt.dst); - s390_opnd_RMI_map_regs(m, &insn->variant.popcnt.src); - break; - case S390_INSN_UNOP: insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst); s390_opnd_RMI_map_regs(m, &insn->variant.unop.src); @@ -4908,22 +4898,6 @@ s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src) } -s390_insn * -s390_insn_popcnt(UChar size, HReg dst, s390_opnd_RMI src) -{ - s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn)); - - vassert(size == 8); - - insn->tag = S390_INSN_POPCNT; - insn->size = size; - insn->variant.popcnt.dst = dst; - insn->variant.popcnt.src = src; - - return insn; -} - - s390_insn * s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd) { @@ -6261,10 +6235,6 @@ s390_insn_as_string(const s390_insn *insn) s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits, &insn->variant.clz.src); break; - - case S390_INSN_POPCNT: - s390_sprintf(buf, "%M %R,%O", "v-popcnt", insn->variant.popcnt.dst, - &insn->variant.popcnt.src); break; case S390_INSN_UNOP: @@ -6285,6 +6255,10 @@ s390_insn_as_string(const s390_insn *insn) op = "v-neg"; break; + case S390_POPCNT: + op = "v-popcnt"; + break; + case S390_VEC_FILL: op = "v-vfill"; break; @@ -7827,6 +7801,43 @@ s390_negate_emit(UChar *buf, const s390_insn *insn) } +static UChar * +s390_popcnt_emit(UChar *buf, const s390_insn *insn) +{ + s390_opnd_RMI src; + UChar r1, r2, *p; + + vassert(insn->size == 8); + p = buf; + r1 = hregNumber(insn->variant.unop.dst); + src = insn->variant.unop.src; + + /* Get operand and move it to r2 */ + switch (src.tag) { + case S390_OPND_REG: + r2 = hregNumber(src.variant.reg); + break; + + case S390_OPND_AMODE: { + p = s390_emit_load_mem(p, 8, R0, src.variant.am); + r2 = R0; + break; + } + + case S390_OPND_IMMEDIATE: { + p = s390_emit_load_64imm(p, R0, src.variant.imm); + r2 = R0; + break; + } + + default: + vpanic("s390_popcnt_emit"); + } + + return s390_emit_POPCNT(p, r1, r2); +} + + static UChar * s390_vec_duplicate_emit(UChar *buf, const s390_insn *insn) { @@ -7890,6 +7901,7 @@ s390_insn_unop_emit(UChar *buf, const s390_insn *insn) case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1); case S390_NEGATE: return s390_negate_emit(buf, insn); + case S390_POPCNT: return s390_popcnt_emit(buf, insn); case S390_VEC_FILL: { vassert(insn->variant.unop.src.tag == S390_OPND_IMMEDIATE); UChar v1 = hregNumber(insn->variant.unop.dst); @@ -8614,49 +8626,6 @@ s390_insn_clz_emit(UChar *buf, const s390_insn *insn) } -static UChar * -s390_insn_popcnt_emit(UChar *buf, const s390_insn *insn) -{ - s390_opnd_RMI src; - UChar r1, r2, *p; - - p = buf; - r1 = hregNumber(insn->variant.popcnt.dst); - src = insn->variant.clz.src; - - /* Get operand and move it to r2 */ - switch (src.tag) { - case S390_OPND_REG: - r2 = hregNumber(src.variant.reg); - break; - - case S390_OPND_AMODE: { - const s390_amode *am = src.variant.am; - UChar b = hregNumber(am->b); - UChar x = hregNumber(am->x); - Int d = am->d; - - p = s390_emit_LG(p, R0, x, b, DISP20(d)); - r2 = R0; - break; - } - - case S390_OPND_IMMEDIATE: { - ULong value = src.variant.imm; - - p = s390_emit_load_64imm(p, R0, value); - r2 = R0; - break; - } - - default: - vpanic("s390_insn_popcnt_emit"); - } - - return s390_emit_POPCNT(p, r1, r2); -} - - /* Returns a value == BUF to denote failure, != BUF to denote success. */ static UChar * s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn) @@ -10109,10 +10078,6 @@ emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn, end = s390_insn_clz_emit(buf, insn); break; - case S390_INSN_POPCNT: - end = s390_insn_popcnt_emit(buf, insn); - break; - case S390_INSN_UNOP: end = s390_insn_unop_emit(buf, insn); break; diff --git a/VEX/priv/host_s390_defs.h b/VEX/priv/host_s390_defs.h index 873e921290..f8bdaad093 100644 --- a/VEX/priv/host_s390_defs.h +++ b/VEX/priv/host_s390_defs.h @@ -129,7 +129,6 @@ typedef enum { S390_INSN_UDIV, /* unsigned division; 2n-bit / n-bit -> n-bit quot/rem */ S390_INSN_DIVS, /* n-bit dividend; n-bit divisor; n-bit quot/rem */ S390_INSN_CLZ, /* count left-most zeroes */ - S390_INSN_POPCNT, /* count bits whose value is 1 */ S390_INSN_UNOP, S390_INSN_TEST, /* test operand and set cc */ S390_INSN_CC2BOOL,/* convert condition code to 0/1 */ @@ -194,6 +193,7 @@ typedef enum { S390_SIGN_EXTEND_16, S390_SIGN_EXTEND_32, S390_NEGATE, + S390_POPCNT, S390_VEC_FILL, S390_VEC_DUPLICATE, S390_VEC_UNPACKLOWS, @@ -531,10 +531,6 @@ typedef struct { HReg clobber; /* unspecified r11 */ s390_opnd_RMI src; } clz; - struct { - HReg dst; /* number of '1' bits */ - s390_opnd_RMI src; - } popcnt; struct { s390_unop_t tag; HReg dst; @@ -781,7 +777,6 @@ s390_insn *s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_insn *s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2); s390_insn *s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI op); -s390_insn *s390_insn_popcnt(UChar size, HReg dst, s390_opnd_RMI op); s390_insn *s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old); s390_insn *s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c index 4f6c10fc38..5454f236ad 100644 --- a/VEX/priv/host_s390_isel.c +++ b/VEX/priv/host_s390_isel.c @@ -1985,7 +1985,7 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr) } case Iop_PopCount64: { - addInstr(env, s390_insn_popcnt(8, dst, opnd)); + addInstr(env, s390_insn_unop(8, S390_POPCNT, dst, opnd)); return dst; } |