From: Andreas Arnez Date: Mon, 9 Mar 2020 14:14:16 +0000 (+0100) Subject: s390x: Enable 1- and 2-byte operands for v-test X-Git-Tag: VALGRIND_3_16_0~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ea91ebf5dec2a8e469b5cabdb9ff11bc2f3b27b6;p=thirdparty%2Fvalgrind.git s390x: Enable 1- and 2-byte operands for v-test The v-test operation tests its operand against zero and sets the condition code accordingly. So far the operation was only supported for 4- and 8-byte operands. Lift this restriction and enable 1- and 2-byte operands for v-test, using the z/Architecture "test under mask" instructions TM, TMY, and TMLL. Exploit this in the instruction selector, getting rid of the conversion to a 4-byte operand. This slightly reduces the generated code on s390x. --- diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c index 1cd469637e..04da842ee2 100644 --- a/VEX/priv/host_s390_defs.c +++ b/VEX/priv/host_s390_defs.c @@ -2081,6 +2081,36 @@ s390_emit_NILL(UChar *p, UChar r1, UShort i2) } +static UChar * +s390_emit_TM(UChar *p, UChar i2, UChar b1, UShort d1) +{ + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + s390_disasm(ENC3(MNM, UDXB, INT), "tm", d1, 0, b1, i2); + + return emit_SI(p, 0x91000000, i2, b1, d1); +} + + +static UChar * +s390_emit_TMY(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1) +{ + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + s390_disasm(ENC3(MNM, SDXB, INT), "tmy", dh1, dl1, 0, b1, (Int)(Char)i2); + + return emit_SIY(p, 0xeb0000000051ULL, i2, b1, dl1, dh1); +} + + +static UChar * +s390_emit_TMLL(UChar *p, UChar r1, UShort i2) +{ + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + s390_disasm(ENC3(MNM, GPR, UINT), "tmll", r1, i2); + + return emit_RI(p, 0xa7010000, r1, i2); +} + + static UChar * s390_emit_BASR(UChar *p, UChar r1, UChar r2) { @@ -6490,7 +6520,7 @@ s390_insn_test(UChar size, s390_opnd_RMI src) { s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn)); - vassert(size == 4 || size == 8); + vassert(size == 1 || size == 2 || size == 4 || size == 8); insn->tag = S390_INSN_TEST; insn->size = size; @@ -9300,9 +9330,7 @@ s390_insn_unop_emit(UChar *buf, const s390_insn *insn) } -/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte - comparisons will have been converted to 4-byte comparisons in - s390_isel_cc and should not occur here. */ +/* Test operand for zero. */ static UChar * s390_insn_test_emit(UChar *buf, const s390_insn *insn) { @@ -9315,6 +9343,12 @@ s390_insn_test_emit(UChar *buf, const s390_insn *insn) UInt reg = hregNumber(opnd.variant.reg); switch (insn->size) { + case 1: + return s390_emit_TMLL(buf, reg, 0xff); + + case 2: + return s390_emit_TMLL(buf, reg, 0xffff); + case 4: return s390_emit_LTR(buf, reg, reg); @@ -9333,6 +9367,27 @@ s390_insn_test_emit(UChar *buf, const s390_insn *insn) Int d = am->d; switch (insn->size) { + case 1: + switch (am->tag) { + case S390_AMODE_B12: + return s390_emit_TM(buf, 0xff, b, d); + case S390_AMODE_B20: + return s390_emit_TMY(buf, 0xff, b, DISP20(d)); + default: + buf = s390_emit_LB(buf, R0, x, b, DISP20(d)); + return s390_emit_TMLL(buf, R0, 0xff); + } + + case 2: + switch (am->tag) { + case S390_AMODE_B12: + buf = s390_emit_LH(buf, R0, x, b, d); + return s390_emit_TMLL(buf, R0, 0xffff); + default: + buf = s390_emit_LHY(buf, R0, x, b, DISP20(d)); + return s390_emit_TMLL(buf, R0, 0xffff); + } + case 4: return s390_emit_LTw(buf, R0, x, b, DISP20(d)); @@ -9345,20 +9400,10 @@ s390_insn_test_emit(UChar *buf, const s390_insn *insn) } case S390_OPND_IMMEDIATE: { - ULong value = opnd.variant.imm; - - switch (insn->size) { - case 4: - buf = s390_emit_load_32imm(buf, R0, value); - return s390_emit_LTR(buf, R0, R0); - - case 8: - buf = s390_emit_load_64imm(buf, R0, value); - return s390_emit_LTGR(buf, R0, R0); - - default: - goto fail; - } + if (opnd.variant.imm == 0) + return s390_emit_CR(buf, R0, R0); + else + return s390_emit_OILL(buf, R0, 1); } default: diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c index 4d0cf1721b..b374024c8c 100644 --- a/VEX/priv/host_s390_isel.c +++ b/VEX/priv/host_s390_isel.c @@ -3514,20 +3514,7 @@ s390_isel_cc(ISelEnv *env, IRExpr *cond) } case Iop_CmpNEZ8: - case Iop_CmpNEZ16: { - s390_opnd_RMI src; - s390_unop_t op; - HReg dst; - - op = (cond->Iex.Unop.op == Iop_CmpNEZ8) ? S390_ZERO_EXTEND_8 - : S390_ZERO_EXTEND_16; - dst = newVRegI(env); - src = s390_isel_int_expr_RMI(env, arg); - addInstr(env, s390_insn_unop(4, op, dst, src)); - addInstr(env, s390_insn_test(4, s390_opnd_reg(dst))); - return S390_CC_NE; - } - + case Iop_CmpNEZ16: case Iop_CmpNEZ32: case Iop_CmpNEZ64: { s390_opnd_RMI src;