From: Andreas Arnez Date: Fri, 5 Dec 2025 17:01:22 +0000 (+0100) Subject: s390x: Simplify single multiplications X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b811351450b3b4637457849b720cc922e503a5bf;p=thirdparty%2Fvalgrind.git s390x: Simplify single multiplications So far the single-multiplication instructions are implemented by taking the low half of a widening multiply. This pattern is then recognized by the instruction selector, which combines it to a single multiplication again. This is unnecessarily complicated, since single-multiply operations can be expressed directly by Iop_Mul32 and Iop_Mul64 instead. So do this, simplifying the code generation. Also, since Iop_Mul32 and Iop_Mul64 haven't really been used before, the instruction selector generates sub-optimal code for them. Fix that. --- diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 8f42c844d..9e850b78f 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -9015,14 +9015,7 @@ s390_irgen_MLG(UChar r1, IRTemp op2addr) static const HChar * s390_irgen_MSR(UChar r1, UChar r2) { - IRTemp op1 = newTemp(Ity_I32); - IRTemp op2 = newTemp(Ity_I32); - IRTemp result = newTemp(Ity_I64); - - assign(op1, get_gpr_w1(r1)); - assign(op2, get_gpr_w1(r2)); - assign(result, binop(Iop_MullS32, mkexpr(op1), mkexpr(op2))); - put_gpr_w1(r1, unop(Iop_64to32, mkexpr(result))); + put_gpr_w1(r1, binop(Iop_Mul32, get_gpr_w1(r1), get_gpr_w1(r2))); return "msr"; } @@ -9030,14 +9023,7 @@ s390_irgen_MSR(UChar r1, UChar r2) static const HChar * s390_irgen_MSGR(UChar r1, UChar r2) { - IRTemp op1 = newTemp(Ity_I64); - IRTemp op2 = newTemp(Ity_I64); - IRTemp result = newTemp(Ity_I128); - - assign(op1, get_gpr_dw0(r1)); - assign(op2, get_gpr_dw0(r2)); - assign(result, binop(Iop_MullS64, mkexpr(op1), mkexpr(op2))); - put_gpr_dw0(r1, unop(Iop_128to64, mkexpr(result))); + put_gpr_dw0(r1, binop(Iop_Mul64, get_gpr_dw0(r1), get_gpr_dw0(r2))); return "msgr"; } @@ -9045,15 +9031,8 @@ s390_irgen_MSGR(UChar r1, UChar r2) static const HChar * s390_irgen_MSGFR(UChar r1, UChar r2) { - IRTemp op1 = newTemp(Ity_I64); - IRTemp op2 = newTemp(Ity_I32); - IRTemp result = newTemp(Ity_I128); - - assign(op1, get_gpr_dw0(r1)); - assign(op2, get_gpr_w1(r2)); - assign(result, binop(Iop_MullS64, mkexpr(op1), unop(Iop_32Sto64, mkexpr(op2)) - )); - put_gpr_dw0(r1, unop(Iop_128to64, mkexpr(result))); + put_gpr_dw0( + r1, binop(Iop_Mul64, get_gpr_dw0(r1), unop(Iop_32Sto64, get_gpr_w1(r2)))); return "msgfr"; } @@ -9061,14 +9040,8 @@ s390_irgen_MSGFR(UChar r1, UChar r2) static const HChar * s390_irgen_MS(UChar r1, IRTemp op2addr) { - IRTemp op1 = newTemp(Ity_I32); - IRTemp op2 = newTemp(Ity_I32); - IRTemp result = newTemp(Ity_I64); - - assign(op1, get_gpr_w1(r1)); - assign(op2, load(Ity_I32, mkexpr(op2addr))); - assign(result, binop(Iop_MullS32, mkexpr(op1), mkexpr(op2))); - put_gpr_w1(r1, unop(Iop_64to32, mkexpr(result))); + put_gpr_w1(r1, + binop(Iop_Mul32, get_gpr_w1(r1), load(Ity_I32, mkexpr(op2addr)))); return "ms"; } @@ -9078,13 +9051,11 @@ s390_irgen_MSC(UChar r1, IRTemp op2addr) { IRTemp op1 = newTemp(Ity_I32); IRTemp op2 = newTemp(Ity_I32); - IRTemp result = newTemp(Ity_I64); assign(op1, get_gpr_w1(r1)); assign(op2, load(Ity_I32, mkexpr(op2addr))); - assign(result, binop(Iop_MullS32, mkexpr(op1), mkexpr(op2))); s390_cc_thunk_putSS(S390_CC_OP_MUL_32, op1, op2); - put_gpr_w1(r1, unop(Iop_64to32, mkexpr(result))); + put_gpr_w1(r1, binop(Iop_Mul32, mkexpr(op1), mkexpr(op2))); return "msc"; } @@ -9094,13 +9065,11 @@ s390_irgen_MSRKC(UChar r3, UChar r1, UChar r2) { IRTemp op2 = newTemp(Ity_I32); IRTemp op3 = newTemp(Ity_I32); - IRTemp result = newTemp(Ity_I64); assign(op2, get_gpr_w1(r2)); assign(op3, get_gpr_w1(r3)); - assign(result, binop(Iop_MullS32, mkexpr(op2), mkexpr(op3))); s390_cc_thunk_putSS(S390_CC_OP_MUL_32, op2, op3); - put_gpr_w1(r1, unop(Iop_64to32, mkexpr(result))); + put_gpr_w1(r1, binop(Iop_Mul32, mkexpr(op2), mkexpr(op3))); return "msrkc"; } @@ -9108,14 +9077,8 @@ s390_irgen_MSRKC(UChar r3, UChar r1, UChar r2) static const HChar * s390_irgen_MSY(UChar r1, IRTemp op2addr) { - IRTemp op1 = newTemp(Ity_I32); - IRTemp op2 = newTemp(Ity_I32); - IRTemp result = newTemp(Ity_I64); - - assign(op1, get_gpr_w1(r1)); - assign(op2, load(Ity_I32, mkexpr(op2addr))); - assign(result, binop(Iop_MullS32, mkexpr(op1), mkexpr(op2))); - put_gpr_w1(r1, unop(Iop_64to32, mkexpr(result))); + put_gpr_w1(r1, + binop(Iop_Mul32, get_gpr_w1(r1), load(Ity_I32, mkexpr(op2addr)))); return "msy"; } @@ -9123,14 +9086,8 @@ s390_irgen_MSY(UChar r1, IRTemp op2addr) static const HChar * s390_irgen_MSG(UChar r1, IRTemp op2addr) { - IRTemp op1 = newTemp(Ity_I64); - IRTemp op2 = newTemp(Ity_I64); - IRTemp result = newTemp(Ity_I128); - - assign(op1, get_gpr_dw0(r1)); - assign(op2, load(Ity_I64, mkexpr(op2addr))); - assign(result, binop(Iop_MullS64, mkexpr(op1), mkexpr(op2))); - put_gpr_dw0(r1, unop(Iop_128to64, mkexpr(result))); + put_gpr_dw0(r1, + binop(Iop_Mul64, get_gpr_dw0(r1), load(Ity_I64, mkexpr(op2addr)))); return "msg"; } @@ -9140,13 +9097,11 @@ s390_irgen_MSGC(UChar r1, IRTemp op2addr) { IRTemp op1 = newTemp(Ity_I64); IRTemp op2 = newTemp(Ity_I64); - IRTemp result = newTemp(Ity_I128); assign(op1, get_gpr_dw0(r1)); assign(op2, load(Ity_I64, mkexpr(op2addr))); - assign(result, binop(Iop_MullS64, mkexpr(op1), mkexpr(op2))); s390_cc_thunk_putSS(S390_CC_OP_MUL_64, op1, op2); - put_gpr_dw0(r1, unop(Iop_128to64, mkexpr(result))); + put_gpr_dw0(r1, binop(Iop_Mul64, mkexpr(op1), mkexpr(op2))); return "msgc"; } @@ -9154,15 +9109,8 @@ s390_irgen_MSGC(UChar r1, IRTemp op2addr) static const HChar * s390_irgen_MSGF(UChar r1, IRTemp op2addr) { - IRTemp op1 = newTemp(Ity_I64); - IRTemp op2 = newTemp(Ity_I32); - IRTemp result = newTemp(Ity_I128); - - assign(op1, get_gpr_dw0(r1)); - assign(op2, load(Ity_I32, mkexpr(op2addr))); - assign(result, binop(Iop_MullS64, mkexpr(op1), unop(Iop_32Sto64, mkexpr(op2)) - )); - put_gpr_dw0(r1, unop(Iop_128to64, mkexpr(result))); + put_gpr_dw0(r1, binop(Iop_Mul64, get_gpr_dw0(r1), + unop(Iop_32Sto64, load(Ity_I32, mkexpr(op2addr))))); return "msgf"; } @@ -9170,14 +9118,7 @@ s390_irgen_MSGF(UChar r1, IRTemp op2addr) static const HChar * s390_irgen_MSFI(UChar r1, UInt i2) { - IRTemp op1 = newTemp(Ity_I32); - Int op2; - IRTemp result = newTemp(Ity_I64); - - assign(op1, get_gpr_w1(r1)); - op2 = (Int)i2; - assign(result, binop(Iop_MullS32, mkexpr(op1), mkU32((UInt)op2))); - put_gpr_w1(r1, unop(Iop_64to32, mkexpr(result))); + put_gpr_w1(r1, binop(Iop_Mul32, get_gpr_w1(r1), mkU32(i2))); return "msfi"; } @@ -9185,15 +9126,8 @@ s390_irgen_MSFI(UChar r1, UInt i2) static const HChar * s390_irgen_MSGFI(UChar r1, UInt i2) { - IRTemp op1 = newTemp(Ity_I64); - Int op2; - IRTemp result = newTemp(Ity_I128); - - assign(op1, get_gpr_dw0(r1)); - op2 = (Int)i2; - assign(result, binop(Iop_MullS64, mkexpr(op1), unop(Iop_32Sto64, mkU32((UInt) - op2)))); - put_gpr_dw0(r1, unop(Iop_128to64, mkexpr(result))); + ULong op2 = (ULong)i2 - (((ULong)i2 & (1 << 31)) << 1); + put_gpr_dw0(r1, binop(Iop_Mul64, get_gpr_dw0(r1), mkU64(op2))); return "msgfi"; } @@ -9203,13 +9137,11 @@ s390_irgen_MSGRKC(UChar r3, UChar r1, UChar r2) { IRTemp op2 = newTemp(Ity_I64); IRTemp op3 = newTemp(Ity_I64); - IRTemp result = newTemp(Ity_I128); assign(op2, get_gpr_dw0(r2)); assign(op3, get_gpr_dw0(r3)); - assign(result, binop(Iop_MullS64, mkexpr(op2), mkexpr(op3))); s390_cc_thunk_putSS(S390_CC_OP_MUL_64, op2, op3); - put_gpr_dw0(r1, unop(Iop_128to64, mkexpr(result))); + put_gpr_dw0(r1, binop(Iop_Mul64, mkexpr(op2), mkexpr(op3))); return "msgrkc"; } diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c index 9cb9b65d3..ffe8a82a2 100644 --- a/VEX/priv/host_s390_isel.c +++ b/VEX/priv/host_s390_isel.c @@ -1277,13 +1277,21 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr) goto do_multiply; do_multiply: { - HReg r10, r11; - UInt arg_size = is_single_multiply ? size : size / 2; - order_commutative_operands(arg1, arg2); h1 = s390_isel_int_expr(env, arg1); /* Process 1st operand */ op2 = s390_isel_int_expr_RMI(env, arg2); /* Process 2nd operand */ + res = newVRegI(env); + + if (is_single_multiply) { + /* No register pair needed */ + addInstr(env, s390_insn_move(size, res, h1)); + addInstr(env, s390_insn_alu(size, S390_ALU_MUL, res, op2)); + return res; + } + + HReg r10, r11; + UInt arg_size = size / 2; /* We use non-virtual registers r10 and r11 as pair */ r10 = make_gpr(10); @@ -1295,7 +1303,6 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr) /* Multiply */ addInstr(env, s390_insn_mul(arg_size, r10, r11, op2, is_signed_multiply)); - res = newVRegI(env); if (arg_size == 1 || arg_size == 2) { /* For 8-bit and 16-bit multiplication the result is in r11[32:63] */ @@ -1303,12 +1310,6 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr) return res; } - /* For Iop_Mul64 the result is in r11[0:63] */ - if (expr->Iex.Binop.op == Iop_Mul64) { - addInstr(env, s390_insn_move(size, res, r11)); - return res; - } - /* The result is in registers r10 and r11. Combine them into a SIZE-bit value into the destination register. */ addInstr(env, s390_insn_move(arg_size, res, r10));