tcg/sparc64: Hoist read of tcg_cond_to_rcond

Use a non-zero value here (an illegal encoding) as a better
condition than is_unsigned_cond for when MOVR/BPR is usable.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-10-24 14:19:08 -07:00
parent be1335dba1
commit 6bc74a5387

View File

@ -620,7 +620,7 @@ static const uint8_t tcg_cond_to_bcond[] = {
[TCG_COND_GTU] = COND_GU, [TCG_COND_GTU] = COND_GU,
}; };
static const uint8_t tcg_cond_to_rcond[] = { static const uint8_t tcg_cond_to_rcond[16] = {
[TCG_COND_EQ] = RCOND_Z, [TCG_COND_EQ] = RCOND_Z,
[TCG_COND_NE] = RCOND_NZ, [TCG_COND_NE] = RCOND_NZ,
[TCG_COND_LT] = RCOND_LZ, [TCG_COND_LT] = RCOND_LZ,
@ -679,7 +679,8 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
int32_t arg2, int const_arg2, TCGLabel *l) int32_t arg2, int const_arg2, TCGLabel *l)
{ {
/* For 64-bit signed comparisons vs zero, we can avoid the compare. */ /* For 64-bit signed comparisons vs zero, we can avoid the compare. */
if (arg2 == 0 && !is_unsigned_cond(cond)) { int rcond = tcg_cond_to_rcond[cond];
if (arg2 == 0 && rcond) {
int off16 = 0; int off16 = 0;
if (l->has_value) { if (l->has_value) {
@ -688,7 +689,7 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, l, 0); tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, l, 0);
} }
tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1) tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1)
| INSN_COND(tcg_cond_to_rcond[cond]) | off16); | INSN_COND(rcond) | off16);
} else { } else {
tcg_out_cmp(s, arg1, arg2, const_arg2); tcg_out_cmp(s, arg1, arg2, const_arg2);
tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, l); tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, l);
@ -696,11 +697,10 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
tcg_out_nop(s); tcg_out_nop(s);
} }
static void tcg_out_movr(TCGContext *s, TCGCond cond, TCGReg ret, TCGReg c1, static void tcg_out_movr(TCGContext *s, int rcond, TCGReg ret, TCGReg c1,
int32_t v1, int v1const) int32_t v1, int v1const)
{ {
tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1) tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1) | (rcond << 10)
| (tcg_cond_to_rcond[cond] << 10)
| (v1const ? INSN_IMM10(v1) : INSN_RS2(v1))); | (v1const ? INSN_IMM10(v1) : INSN_RS2(v1)));
} }
@ -711,9 +711,9 @@ static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
/* For 64-bit signed comparisons vs zero, we can avoid the compare. /* For 64-bit signed comparisons vs zero, we can avoid the compare.
Note that the immediate range is one bit smaller, so we must check Note that the immediate range is one bit smaller, so we must check
for that as well. */ for that as well. */
if (c2 == 0 && !is_unsigned_cond(cond) int rcond = tcg_cond_to_rcond[cond];
&& (!v1const || check_fit_i32(v1, 10))) { if (c2 == 0 && rcond && (!v1const || check_fit_i32(v1, 10))) {
tcg_out_movr(s, cond, ret, c1, v1, v1const); tcg_out_movr(s, rcond, ret, c1, v1, v1const);
} else { } else {
tcg_out_cmp(s, c1, c2, c2const); tcg_out_cmp(s, c1, c2, c2const);
tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const); tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const);
@ -788,6 +788,8 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret, static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg c1, int32_t c2, int c2const, bool neg) TCGReg c1, int32_t c2, int c2const, bool neg)
{ {
int rcond;
if (use_vis3_instructions && !neg) { if (use_vis3_instructions && !neg) {
switch (cond) { switch (cond) {
case TCG_COND_NE: case TCG_COND_NE:
@ -807,9 +809,10 @@ static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
/* For 64-bit signed comparisons vs zero, we can avoid the compare /* For 64-bit signed comparisons vs zero, we can avoid the compare
if the input does not overlap the output. */ if the input does not overlap the output. */
if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) { rcond = tcg_cond_to_rcond[cond];
if (c2 == 0 && rcond && c1 != ret) {
tcg_out_movi_s13(s, ret, 0); tcg_out_movi_s13(s, ret, 0);
tcg_out_movr(s, cond, ret, c1, neg ? -1 : 1, 1); tcg_out_movr(s, rcond, ret, c1, neg ? -1 : 1, 1);
} else { } else {
tcg_out_cmp(s, c1, c2, c2const); tcg_out_cmp(s, c1, c2, c2const);
tcg_out_movi_s13(s, ret, 0); tcg_out_movi_s13(s, ret, 0);