tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS

There are several cases that can be handled easier inside both
translators and code generators if we have out-of-band values
for conditions.  It's easy enough to handle ALWAYS and NEVER in
the natural way inside the tcg middle-end.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Richard Henderson 2012-09-24 14:21:40 -07:00 committed by Aurelien Jarno
parent bcc66562ad
commit 0aed257f08
11 changed files with 102 additions and 41 deletions

View File

@ -335,7 +335,7 @@ enum arm_cond_code_e {
COND_AL = 0xe, COND_AL = 0xe,
}; };
static const uint8_t tcg_cond_to_arm_cond[10] = { static const uint8_t tcg_cond_to_arm_cond[] = {
[TCG_COND_EQ] = COND_EQ, [TCG_COND_EQ] = COND_EQ,
[TCG_COND_NE] = COND_NE, [TCG_COND_NE] = COND_NE,
[TCG_COND_LT] = COND_LT, [TCG_COND_LT] = COND_LT,

View File

@ -732,7 +732,7 @@ static void tcg_out_branch(TCGContext *s, int label_index, int nul)
} }
} }
static const uint8_t tcg_cond_to_cmp_cond[10] = static const uint8_t tcg_cond_to_cmp_cond[] =
{ {
[TCG_COND_EQ] = COND_EQ, [TCG_COND_EQ] = COND_EQ,
[TCG_COND_NE] = COND_EQ | COND_FALSE, [TCG_COND_NE] = COND_EQ | COND_FALSE,

View File

@ -338,7 +338,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define JCC_JLE 0xe #define JCC_JLE 0xe
#define JCC_JG 0xf #define JCC_JG 0xf
static const uint8_t tcg_cond_to_jcc[10] = { static const uint8_t tcg_cond_to_jcc[] = {
[TCG_COND_EQ] = JCC_JE, [TCG_COND_EQ] = JCC_JE,
[TCG_COND_NE] = JCC_JNE, [TCG_COND_NE] = JCC_JNE,
[TCG_COND_LT] = JCC_JL, [TCG_COND_LT] = JCC_JL,

View File

@ -321,6 +321,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
return (uint32_t)temps[x].val <= (uint32_t)temps[y].val; return (uint32_t)temps[x].val <= (uint32_t)temps[y].val;
case TCG_COND_GTU: case TCG_COND_GTU:
return (uint32_t)temps[x].val > (uint32_t)temps[y].val; return (uint32_t)temps[x].val > (uint32_t)temps[y].val;
default:
break;
} }
break; break;
case 64: case 64:
@ -345,6 +347,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
return (uint64_t)temps[x].val <= (uint64_t)temps[y].val; return (uint64_t)temps[x].val <= (uint64_t)temps[y].val;
case TCG_COND_GTU: case TCG_COND_GTU:
return (uint64_t)temps[x].val > (uint64_t)temps[y].val; return (uint64_t)temps[x].val > (uint64_t)temps[y].val;
default:
break;
} }
break; break;
} }
@ -362,6 +366,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
case TCG_COND_LEU: case TCG_COND_LEU:
case TCG_COND_EQ: case TCG_COND_EQ:
return 1; return 1;
default:
break;
} }
} else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) { } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) {
switch (c) { switch (c) {

View File

@ -437,7 +437,7 @@ enum {
CR_SO CR_SO
}; };
static const uint32_t tcg_to_bc[10] = { static const uint32_t tcg_to_bc[] = {
[TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE, [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,

View File

@ -418,7 +418,7 @@ enum {
CR_SO CR_SO
}; };
static const uint32_t tcg_to_bc[10] = { static const uint32_t tcg_to_bc[] = {
[TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE, [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,

View File

@ -268,7 +268,7 @@ static const int tcg_target_call_oarg_regs[] = {
#define S390_CC_ALWAYS 15 #define S390_CC_ALWAYS 15
/* Condition codes that result from a COMPARE and COMPARE LOGICAL. */ /* Condition codes that result from a COMPARE and COMPARE LOGICAL. */
static const uint8_t tcg_cond_to_s390_cond[10] = { static const uint8_t tcg_cond_to_s390_cond[] = {
[TCG_COND_EQ] = S390_CC_EQ, [TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE, [TCG_COND_NE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT, [TCG_COND_LT] = S390_CC_LT,
@ -284,7 +284,7 @@ static const uint8_t tcg_cond_to_s390_cond[10] = {
/* Condition codes that result from a LOAD AND TEST. Here, we have no /* Condition codes that result from a LOAD AND TEST. Here, we have no
unsigned instruction variation, however since the test is vs zero we unsigned instruction variation, however since the test is vs zero we
can re-map the outcomes appropriately. */ can re-map the outcomes appropriately. */
static const uint8_t tcg_cond_to_ltr_cond[10] = { static const uint8_t tcg_cond_to_ltr_cond[] = {
[TCG_COND_EQ] = S390_CC_EQ, [TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE, [TCG_COND_NE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT, [TCG_COND_LT] = S390_CC_LT,

View File

@ -512,7 +512,7 @@ static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
} }
#endif #endif
static const uint8_t tcg_cond_to_bcond[10] = { static const uint8_t tcg_cond_to_bcond[] = {
[TCG_COND_EQ] = COND_E, [TCG_COND_EQ] = COND_E,
[TCG_COND_NE] = COND_NE, [TCG_COND_NE] = COND_NE,
[TCG_COND_LT] = COND_L, [TCG_COND_LT] = COND_L,

View File

@ -646,29 +646,49 @@ static inline void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
static inline void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, static inline void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1,
TCGv_i32 arg2, int label_index) TCGv_i32 arg2, int label_index)
{ {
tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index); if (cond == TCG_COND_ALWAYS) {
tcg_gen_br(label_index);
} else if (cond != TCG_COND_NEVER) {
tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
}
} }
static inline void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1, static inline void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1,
int32_t arg2, int label_index) int32_t arg2, int label_index)
{ {
TCGv_i32 t0 = tcg_const_i32(arg2); if (cond == TCG_COND_ALWAYS) {
tcg_gen_brcond_i32(cond, arg1, t0, label_index); tcg_gen_br(label_index);
tcg_temp_free_i32(t0); } else if (cond != TCG_COND_NEVER) {
TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_brcond_i32(cond, arg1, t0, label_index);
tcg_temp_free_i32(t0);
}
} }
static inline void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret, static inline void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, TCGv_i32 arg2) TCGv_i32 arg1, TCGv_i32 arg2)
{ {
tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond); if (cond == TCG_COND_ALWAYS) {
tcg_gen_movi_i32(ret, 1);
} else if (cond == TCG_COND_NEVER) {
tcg_gen_movi_i32(ret, 0);
} else {
tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
}
} }
static inline void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret, static inline void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, int32_t arg2) TCGv_i32 arg1, int32_t arg2)
{ {
TCGv_i32 t0 = tcg_const_i32(arg2); if (cond == TCG_COND_ALWAYS) {
tcg_gen_setcond_i32(cond, ret, arg1, t0); tcg_gen_movi_i32(ret, 1);
tcg_temp_free_i32(t0); } else if (cond == TCG_COND_NEVER) {
tcg_gen_movi_i32(ret, 0);
} else {
TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_setcond_i32(cond, ret, arg1, t0);
tcg_temp_free_i32(t0);
}
} }
static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
@ -964,17 +984,27 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
TCGv_i64 arg2, int label_index) TCGv_i64 arg2, int label_index)
{ {
tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, if (cond == TCG_COND_ALWAYS) {
TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2), tcg_gen_br(label_index);
TCGV_HIGH(arg2), cond, label_index); } else if (cond != TCG_COND_NEVER) {
tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
TCGV_HIGH(arg2), cond, label_index);
}
} }
static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2) TCGv_i64 arg1, TCGv_i64 arg2)
{ {
tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), if (cond == TCG_COND_ALWAYS) {
TCGV_LOW(arg1), TCGV_HIGH(arg1), tcg_gen_movi_i32(TCGV_LOW(ret), 1);
TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); } else if (cond == TCG_COND_NEVER) {
tcg_gen_movi_i32(TCGV_LOW(ret), 0);
} else {
tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
TCGV_LOW(arg1), TCGV_HIGH(arg1),
TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
}
tcg_gen_movi_i32(TCGV_HIGH(ret), 0); tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
} }
@ -1273,13 +1303,23 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1, static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
TCGv_i64 arg2, int label_index) TCGv_i64 arg2, int label_index)
{ {
tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index); if (cond == TCG_COND_ALWAYS) {
tcg_gen_br(label_index);
} else if (cond != TCG_COND_NEVER) {
tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
}
} }
static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret, static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2) TCGv_i64 arg1, TCGv_i64 arg2)
{ {
tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond); if (cond == TCG_COND_ALWAYS) {
tcg_gen_movi_i64(ret, 1);
} else if (cond == TCG_COND_NEVER) {
tcg_gen_movi_i64(ret, 0);
} else {
tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
}
} }
static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
@ -1397,9 +1437,13 @@ static inline void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, static inline void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1,
int64_t arg2, int label_index) int64_t arg2, int label_index)
{ {
TCGv_i64 t0 = tcg_const_i64(arg2); if (cond == TCG_COND_ALWAYS) {
tcg_gen_brcond_i64(cond, arg1, t0, label_index); tcg_gen_br(label_index);
tcg_temp_free_i64(t0); } else if (cond != TCG_COND_NEVER) {
TCGv_i64 t0 = tcg_const_i64(arg2);
tcg_gen_brcond_i64(cond, arg1, t0, label_index);
tcg_temp_free_i64(t0);
}
} }
static inline void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, static inline void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,

View File

@ -864,6 +864,8 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
static const char * const cond_name[] = static const char * const cond_name[] =
{ {
[TCG_COND_NEVER] = "never",
[TCG_COND_ALWAYS] = "always",
[TCG_COND_EQ] = "eq", [TCG_COND_EQ] = "eq",
[TCG_COND_NE] = "ne", [TCG_COND_NE] = "ne",
[TCG_COND_LT] = "lt", [TCG_COND_LT] = "lt",

View File

@ -266,18 +266,28 @@ typedef int TCGv_i64;
#define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1) #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1)
#define TCG_CALL_DUMMY_ARG ((TCGArg)(-1)) #define TCG_CALL_DUMMY_ARG ((TCGArg)(-1))
/* Conditions. Note that these are layed out for easy manipulation by
the the functions below:
bit 0 is used for inverting;
bit 1 is signed,
bit 2 is unsigned,
bit 3 is used with bit 0 for swapping signed/unsigned. */
typedef enum { typedef enum {
TCG_COND_EQ, /* non-signed */
TCG_COND_NE, TCG_COND_NEVER = 0 | 0 | 0 | 0,
TCG_COND_LT, TCG_COND_ALWAYS = 0 | 0 | 0 | 1,
TCG_COND_GE, TCG_COND_EQ = 8 | 0 | 0 | 0,
TCG_COND_LE, TCG_COND_NE = 8 | 0 | 0 | 1,
TCG_COND_GT, /* signed */
TCG_COND_LT = 0 | 0 | 2 | 0,
TCG_COND_GE = 0 | 0 | 2 | 1,
TCG_COND_LE = 8 | 0 | 2 | 0,
TCG_COND_GT = 8 | 0 | 2 | 1,
/* unsigned */ /* unsigned */
TCG_COND_LTU, TCG_COND_LTU = 0 | 4 | 0 | 0,
TCG_COND_GEU, TCG_COND_GEU = 0 | 4 | 0 | 1,
TCG_COND_LEU, TCG_COND_LEU = 8 | 4 | 0 | 0,
TCG_COND_GTU, TCG_COND_GTU = 8 | 4 | 0 | 1,
} TCGCond; } TCGCond;
/* Invert the sense of the comparison. */ /* Invert the sense of the comparison. */
@ -289,18 +299,17 @@ static inline TCGCond tcg_invert_cond(TCGCond c)
/* Swap the operands in a comparison. */ /* Swap the operands in a comparison. */
static inline TCGCond tcg_swap_cond(TCGCond c) static inline TCGCond tcg_swap_cond(TCGCond c)
{ {
int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15); return c & 6 ? (TCGCond)(c ^ 9) : c;
return (TCGCond)(c ^ mask);
} }
static inline TCGCond tcg_unsigned_cond(TCGCond c) static inline TCGCond tcg_unsigned_cond(TCGCond c)
{ {
return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c); return c & 2 ? (TCGCond)(c ^ 6) : c;
} }
static inline bool is_unsigned_cond(TCGCond c) static inline bool is_unsigned_cond(TCGCond c)
{ {
return c >= TCG_COND_LTU; return (c & 4) != 0;
} }
#define TEMP_VAL_DEAD 0 #define TEMP_VAL_DEAD 0