tcg/mips: optimize brcond arg, 0

MIPS has some conditional branch instructions when comparing with zero.
Use them.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Aurelien Jarno 2012-09-21 18:20:26 +02:00
parent 0d0b53a670
commit 0f46c064ee
1 changed files with 30 additions and 8 deletions

View File

@ -278,6 +278,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
enum { enum {
OPC_BEQ = 0x04 << 26, OPC_BEQ = 0x04 << 26,
OPC_BNE = 0x05 << 26, OPC_BNE = 0x05 << 26,
OPC_BLEZ = 0x06 << 26,
OPC_BGTZ = 0x07 << 26,
OPC_ADDIU = 0x09 << 26, OPC_ADDIU = 0x09 << 26,
OPC_SLTI = 0x0A << 26, OPC_SLTI = 0x0A << 26,
OPC_SLTIU = 0x0B << 26, OPC_SLTIU = 0x0B << 26,
@ -319,6 +321,10 @@ enum {
OPC_SLT = OPC_SPECIAL | 0x2A, OPC_SLT = OPC_SPECIAL | 0x2A,
OPC_SLTU = OPC_SPECIAL | 0x2B, OPC_SLTU = OPC_SPECIAL | 0x2B,
OPC_REGIMM = 0x01 << 26,
OPC_BLTZ = OPC_REGIMM | (0x00 << 16),
OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
OPC_SPECIAL3 = 0x1f << 26, OPC_SPECIAL3 = 0x1f << 26,
OPC_SEB = OPC_SPECIAL3 | 0x420, OPC_SEB = OPC_SPECIAL3 | 0x420,
OPC_SEH = OPC_SPECIAL3 | 0x620, OPC_SEH = OPC_SPECIAL3 | 0x620,
@ -590,32 +596,48 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
tcg_out_opc_br(s, OPC_BNE, arg1, arg2); tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
break; break;
case TCG_COND_LT: case TCG_COND_LT:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); if (arg2 == 0) {
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); tcg_out_opc_br(s, OPC_BLTZ, 0, arg1);
} else {
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
}
break; break;
case TCG_COND_LTU: case TCG_COND_LTU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2); tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_GE: case TCG_COND_GE:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); if (arg2 == 0) {
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); tcg_out_opc_br(s, OPC_BGEZ, 0, arg1);
} else {
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
}
break; break;
case TCG_COND_GEU: case TCG_COND_GEU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2); tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_LE: case TCG_COND_LE:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); if (arg2 == 0) {
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); tcg_out_opc_br(s, OPC_BLEZ, 0, arg1);
} else {
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
}
break; break;
case TCG_COND_LEU: case TCG_COND_LEU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1); tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break; break;
case TCG_COND_GT: case TCG_COND_GT:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); if (arg2 == 0) {
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); tcg_out_opc_br(s, OPC_BGTZ, 0, arg1);
} else {
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
}
break; break;
case TCG_COND_GTU: case TCG_COND_GTU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1); tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);