tcg: Convert setcond2_i32 to TCGOutOpSetcond2

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-01-10 16:57:07 -08:00
parent f408df587a
commit e579c717cb
7 changed files with 110 additions and 76 deletions

View file

@ -2266,13 +2266,25 @@ static const TCGOutOpBrcond2 outop_brcond2 = {
.out = tgen_brcond2,
};
static void tgen_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg al, TCGReg ah,
TCGArg bl, bool const_bl,
TCGArg bh, bool const_bh)
{
cond = tcg_out_cmp2(s, cond, al, ah, bl, const_bl, bh, const_bh);
finish_setcond(s, cond, ret, false);
}
static const TCGOutOpSetcond2 outop_setcond2 = {
.base.static_constraint = C_O1_I4(r, r, r, rI, rI),
.out = tgen_setcond2,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
{
TCGArg a0, a1, a2, a3, a4, a5;
int c;
switch (opc) {
case INDEX_op_goto_ptr:
@ -2348,14 +2360,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_mov_reg(s, COND_AL, args[0], a0);
break;
case INDEX_op_setcond2_i32:
c = tcg_out_cmp2(s, args[5], args[1], args[2], args[3], const_args[3],
args[4], const_args[4]);
tcg_out_dat_imm(s, tcg_cond_to_arm_cond[c], ARITH_MOV, args[0], 0, 1);
tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(c)],
ARITH_MOV, args[0], 0, 0);
break;
case INDEX_op_qemu_ld_i32:
tcg_out_qemu_ld(s, args[0], -1, args[1], args[2], TCG_TYPE_I32);
break;
@ -2452,9 +2456,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
return C_O2_I4(r, r, r, r, rIN, rIK);
case INDEX_op_sub2_i32:
return C_O2_I4(r, r, rI, rI, rIN, rIK);
case INDEX_op_setcond2_i32:
return C_O1_I4(r, r, r, rI, rI);
case INDEX_op_qemu_ld_i32:
return C_O1_I1(r, q);
case INDEX_op_qemu_ld_i64:

View file

@ -1860,47 +1860,53 @@ static const TCGOutOpSetcond outop_negsetcond = {
.out_rri = tgen_negsetcondi,
};
#if TCG_TARGET_REG_BITS == 32
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
const int *const_args)
static void tgen_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg al, TCGReg ah,
TCGArg bl, bool const_bl,
TCGArg bh, bool const_bh)
{
TCGLabel *label_true, *label_over;
TCGLabel *label_over = gen_new_label();
if (args[0] == args[1] || args[0] == args[2]
|| (!const_args[3] && args[0] == args[3])
|| (!const_args[4] && args[0] == args[4])) {
/* When the destination overlaps with one of the argument
registers, don't do anything tricky. */
label_true = gen_new_label();
label_over = gen_new_label();
if (ret == al || ret == ah
|| (!const_bl && ret == bl)
|| (!const_bh && ret == bh)) {
/*
* When the destination overlaps with one of the argument
* registers, don't do anything tricky.
*/
TCGLabel *label_true = gen_new_label();
tcg_out_brcond2(s, args[5], args[1], args[2], args[3], const_args[3],
args[4], const_args[4], label_true, true);
tcg_out_brcond2(s, cond, al, ah, bl, const_bl,
bh, const_bh, label_true, true);
tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
tcg_out_movi(s, TCG_TYPE_I32, ret, 0);
tcg_out_jxx(s, JCC_JMP, label_over, 1);
tcg_out_label(s, label_true);
tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
tcg_out_label(s, label_over);
tcg_out_movi(s, TCG_TYPE_I32, ret, 1);
} else {
/* When the destination does not overlap one of the arguments,
clear the destination first, jump if cond false, and emit an
increment in the true case. This results in smaller code. */
/*
* When the destination does not overlap one of the arguments,
* clear the destination first, jump if cond false, and emit an
* increment in the true case. This results in smaller code.
*/
tcg_out_movi(s, TCG_TYPE_I32, ret, 0);
tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
tcg_out_brcond2(s, tcg_invert_cond(cond), al, ah, bl, const_bl,
bh, const_bh, label_over, true);
label_over = gen_new_label();
tcg_out_brcond2(s, tcg_invert_cond(args[5]), args[1], args[2],
args[3], const_args[3],
args[4], const_args[4], label_over, true);
tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
tcg_out_label(s, label_over);
tgen_arithi(s, ARITH_ADD, ret, 1, 0);
}
tcg_out_label(s, label_over);
}
#if TCG_TARGET_REG_BITS != 32
__attribute__((unused))
#endif
static const TCGOutOpSetcond2 outop_setcond2 = {
.base.static_constraint = C_O1_I4(r, r, r, ri, ri),
.out = tgen_setcond2,
};
static void tcg_out_cmov(TCGContext *s, int jcc, int rexw,
TCGReg dest, TCGReg v1)
@ -3240,11 +3246,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
}
break;
#if TCG_TARGET_REG_BITS == 32
case INDEX_op_setcond2_i32:
tcg_out_setcond2(s, args, const_args);
break;
#else /* TCG_TARGET_REG_BITS == 64 */
#if TCG_TARGET_REG_BITS == 64
case INDEX_op_ld32s_i64:
tcg_out_modrm_offset(s, OPC_MOVSLQ, a0, a1, a2);
break;
@ -4012,9 +4014,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
return C_O0_I3(L, L, L);
case INDEX_op_setcond2_i32:
return C_O1_I4(r, r, r, ri, ri);
case INDEX_op_ld_vec:
case INDEX_op_dupm_vec:
return C_O1_I1(x, r);

View file

@ -25,7 +25,7 @@ C_O1_I2(r, r, rz)
C_O1_I2(r, r, rzW)
C_O1_I4(r, r, rz, rz, 0)
C_O1_I4(r, r, rz, rz, rz)
C_O1_I4(r, rz, rz, rz, rz)
C_O1_I4(r, r, r, rz, rz)
C_O2_I1(r, r, r)
C_O2_I2(r, r, r, r)
C_O2_I4(r, r, rz, rz, rN, rN)

View file

@ -1067,13 +1067,23 @@ static int tcg_out_setcond2_int(TCGContext *s, TCGCond cond, TCGReg ret,
return ret | flags;
}
static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
static void tgen_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg al, TCGReg ah,
TCGArg bl, bool const_bl,
TCGArg bh, bool const_bh)
{
int tmpflags = tcg_out_setcond2_int(s, cond, ret, al, ah, bl, bh);
tcg_out_setcond_end(s, ret, tmpflags);
}
#if TCG_TARGET_REG_BITS != 32
__attribute__((unused))
#endif
static const TCGOutOpSetcond2 outop_setcond2 = {
.base.static_constraint = C_O1_I4(r, r, r, rz, rz),
.out = tgen_setcond2,
};
static void tgen_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
TCGArg bl, bool const_bl,
TCGArg bh, bool const_bh, TCGLabel *l)
@ -2306,10 +2316,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
}
break;
case INDEX_op_setcond2_i32:
tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
break;
case INDEX_op_qemu_ld_i32:
tcg_out_qemu_ld(s, a0, 0, a1, a2, TCG_TYPE_I32);
break;
@ -2404,8 +2410,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_add2_i32:
case INDEX_op_sub2_i32:
return C_O2_I4(r, r, rz, rz, rN, rN);
case INDEX_op_setcond2_i32:
return C_O1_I4(r, rz, rz, rz, rz);
case INDEX_op_qemu_ld_i32:
return C_O1_I1(r, r);

View file

@ -2274,15 +2274,24 @@ static void tcg_out_cmp2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
}
}
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
const int *const_args)
static void tgen_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg al, TCGReg ah,
TCGArg bl, bool const_bl,
TCGArg bh, bool const_bh)
{
tcg_out_cmp2(s, args[5], args[1], args[2], args[3], const_args[3],
args[4], const_args[4]);
tcg_out_cmp2(s, cond, al, ah, bl, const_bl, bh, const_bh);
tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(0));
tcg_out_rlw(s, RLWINM, args[0], TCG_REG_R0, CR_EQ + 0*4 + 1, 31, 31);
tcg_out_rlw(s, RLWINM, ret, TCG_REG_R0, CR_EQ + 0*4 + 1, 31, 31);
}
#if TCG_TARGET_REG_BITS != 32
__attribute__((unused))
#endif
static const TCGOutOpSetcond2 outop_setcond2 = {
.base.static_constraint = C_O1_I4(r, r, r, rU, rC),
.out = tgen_setcond2,
};
static void tgen_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
TCGArg bl, bool const_bl,
TCGArg bh, bool const_bh, TCGLabel *l)
@ -3491,10 +3500,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_qemu_ldst_i128(s, args[0], args[1], args[2], args[3], false);
break;
case INDEX_op_setcond2_i32:
tcg_out_setcond2(s, args, const_args);
break;
case INDEX_op_bswap16_i32:
case INDEX_op_bswap16_i64:
tcg_out_bswap16(s, args[0], args[1], args[2]);
@ -4277,8 +4282,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64:
return C_O1_I2(r, 0, rZ);
case INDEX_op_setcond2_i32:
return C_O1_I4(r, r, r, rU, rC);
case INDEX_op_add2_i64:
case INDEX_op_add2_i32:
return C_O2_I4(r, r, r, r, rI, rZM);

View file

@ -1033,6 +1033,12 @@ typedef struct TCGOutOpSetcond {
TCGReg ret, TCGReg a1, tcg_target_long a2);
} TCGOutOpSetcond;
typedef struct TCGOutOpSetcond2 {
TCGOutOp base;
void (*out)(TCGContext *s, TCGCond cond, TCGReg ret, TCGReg al, TCGReg ah,
TCGArg bl, bool const_bl, TCGArg bh, bool const_bh);
} TCGOutOpSetcond2;
typedef struct TCGOutOpSubtract {
TCGOutOp base;
void (*out_rrr)(TCGContext *s, TCGType type,
@ -1097,6 +1103,7 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
#if TCG_TARGET_REG_BITS == 32
OUTOP(INDEX_op_brcond2_i32, TCGOutOpBrcond2, outop_brcond2),
OUTOP(INDEX_op_setcond2_i32, TCGOutOpSetcond2, outop_setcond2),
#endif
};
@ -5565,8 +5572,20 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
new_args[3], const_args[3], label);
}
break;
case INDEX_op_setcond2_i32:
{
const TCGOutOpSetcond2 *out = &outop_setcond2;
TCGCond cond = new_args[5];
tcg_debug_assert(!const_args[1]);
tcg_debug_assert(!const_args[2]);
out->out(s, cond, new_args[0], new_args[1], new_args[2],
new_args[3], const_args[3], new_args[4], const_args[4]);
}
break;
#else
case INDEX_op_brcond2_i32:
case INDEX_op_setcond2_i32:
g_assert_not_reached();
#endif

View file

@ -87,9 +87,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_sub2_i64:
return C_O2_I4(r, r, r, r, r, r);
case INDEX_op_setcond2_i32:
return C_O1_I4(r, r, r, r, r);
case INDEX_op_qemu_ld_i32:
return C_O1_I1(r, r);
case INDEX_op_qemu_ld_i64:
@ -997,6 +994,22 @@ static const TCGOutOpBrcond2 outop_brcond2 = {
.out = tgen_brcond2,
};
static void tgen_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg al, TCGReg ah,
TCGArg bl, bool const_bl,
TCGArg bh, bool const_bh)
{
tcg_out_op_rrrrrc(s, INDEX_op_setcond2_i32, ret, al, ah, bl, bh, cond);
}
#if TCG_TARGET_REG_BITS != 32
__attribute__((unused))
#endif
static const TCGOutOpSetcond2 outop_setcond2 = {
.base.static_constraint = C_O1_I4(r, r, r, r, r),
.out = tgen_setcond2,
};
static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@ -1012,11 +1025,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type,
tcg_out_op_l(s, opc, arg_label(args[0]));
break;
case INDEX_op_setcond2_i32:
tcg_out_op_rrrrrc(s, opc, args[0], args[1], args[2],
args[3], args[4], args[5]);
break;
CASE_32_64(ld8u)
CASE_32_64(ld8s)
CASE_32_64(ld16u)