Message ID | 1347224784-19472-3-git-send-email-rth@twiddle.net |
---|---|
State | New |
Headers | show |
On Sun, Sep 09, 2012 at 02:04:20PM -0700, Richard Henderson wrote: > 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> > Cc: Aurelien Jarno <aurelien@aurel32.net> > --- > tcg/arm/tcg-target.c | 2 +- > tcg/hppa/tcg-target.c | 2 +- > tcg/i386/tcg-target.c | 2 +- > tcg/ppc/tcg-target.c | 2 +- > tcg/ppc64/tcg-target.c | 2 +- > tcg/s390/tcg-target.c | 6 ++-- > tcg/sparc/tcg-target.c | 2 +- > tcg/tcg-op.h | 82 ++++++++++++++++++++++++++++++++++++++------------ > tcg/tcg.c | 2 ++ > tcg/tcg.h | 40 ++++++++++++++++-------- > 10 files changed, 101 insertions(+), 41 deletions(-) > > diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c > index cf0ca3d..bb9516c 100644 > --- a/tcg/arm/tcg-target.c > +++ b/tcg/arm/tcg-target.c > @@ -342,7 +342,7 @@ enum arm_cond_code_e { > 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_NE] = COND_NE, > [TCG_COND_LT] = COND_LT, > diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c > index 2885212..9cd97d5 100644 > --- a/tcg/hppa/tcg-target.c > +++ b/tcg/hppa/tcg-target.c > @@ -738,7 +738,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_NE] = COND_EQ | COND_FALSE, > diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c > index da17bba..5dfa113 100644 > --- a/tcg/i386/tcg-target.c > +++ b/tcg/i386/tcg-target.c > @@ -338,7 +338,7 @@ static inline int tcg_target_const_match(tcg_target_long val, > #define JCC_JLE 0xe > #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_NE] = JCC_JNE, > [TCG_COND_LT] = JCC_JL, > diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c > index 0cff181..4c70fba 100644 > --- a/tcg/ppc/tcg-target.c > +++ b/tcg/ppc/tcg-target.c > @@ -456,7 +456,7 @@ enum { > 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_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, > [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, > diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c > index 27a0ae8..62dff6a 100644 > --- a/tcg/ppc64/tcg-target.c > +++ b/tcg/ppc64/tcg-target.c > @@ -428,7 +428,7 @@ enum { > 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_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, > [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, > diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c > index 04662c1..2bffdb2 100644 > --- a/tcg/s390/tcg-target.c > +++ b/tcg/s390/tcg-target.c > @@ -268,7 +268,7 @@ static const int tcg_target_call_oarg_regs[] = { > #define S390_CC_ALWAYS 15 > > /* 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_NE] = S390_CC_NE, > [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 > unsigned instruction variation, however since the test is vs zero we > 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_NE] = S390_CC_NE, > [TCG_COND_LT] = S390_CC_LT, > @@ -1138,7 +1138,7 @@ static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val) > static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, > TCGArg c2, int c2const) > { > - bool is_unsigned = (c > TCG_COND_GT); > + bool is_unsigned = is_unsigned_cond(c); > if (c2const) { > if (c2 == 0) { > if (type == TCG_TYPE_I32) { > diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c > index 247a278..0a25065 100644 > --- a/tcg/sparc/tcg-target.c > +++ b/tcg/sparc/tcg-target.c > @@ -510,7 +510,7 @@ static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index) > } > #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_NE] = COND_NE, > [TCG_COND_LT] = COND_L, > diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h > index 169d3b2..96a30de 100644 > --- a/tcg/tcg-op.h > +++ b/tcg/tcg-op.h > @@ -627,29 +627,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, > 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, > int32_t arg2, int label_index) > { > - TCGv_i32 t0 = tcg_const_i32(arg2); > - tcg_gen_brcond_i32(cond, arg1, t0, label_index); > - tcg_temp_free_i32(t0); > + if (cond == TCG_COND_ALWAYS) { > + tcg_gen_br(label_index); > + } 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, > 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, > TCGv_i32 arg1, int32_t arg2) > { > - TCGv_i32 t0 = tcg_const_i32(arg2); > - tcg_gen_setcond_i32(cond, ret, arg1, t0); > - tcg_temp_free_i32(t0); > + if (cond == TCG_COND_ALWAYS) { > + tcg_gen_movi_i32(ret, 1); > + } 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) > @@ -945,17 +965,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, > TCGv_i64 arg2, int label_index) > { > - tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, > - TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2), > - TCGV_HIGH(arg2), cond, label_index); > + if (cond == TCG_COND_ALWAYS) { > + tcg_gen_br(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, > TCGv_i64 arg1, TCGv_i64 arg2) > { > - tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), > - TCGV_LOW(arg1), TCGV_HIGH(arg1), > - TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); > + if (cond == TCG_COND_ALWAYS) { > + tcg_gen_movi_i32(TCGV_LOW(ret), 1); > + } 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); > } > > @@ -1210,13 +1240,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, > 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, > 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) > @@ -1334,9 +1374,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, > int64_t arg2, int label_index) > { > - TCGv_i64 t0 = tcg_const_i64(arg2); > - tcg_gen_brcond_i64(cond, arg1, t0, label_index); > - tcg_temp_free_i64(t0); > + if (cond == TCG_COND_ALWAYS) { > + tcg_gen_br(label_index); > + } 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, > diff --git a/tcg/tcg.c b/tcg/tcg.c > index 8386b70..42c3b40 100644 > --- a/tcg/tcg.c > +++ b/tcg/tcg.c > @@ -861,6 +861,8 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val) > > static const char * const cond_name[] = > { > + [TCG_COND_NEVER] = "never", > + [TCG_COND_ALWAYS] = "always", > [TCG_COND_EQ] = "eq", > [TCG_COND_NE] = "ne", > [TCG_COND_LT] = "lt", > diff --git a/tcg/tcg.h b/tcg/tcg.h > index a9367fe..6c37f15 100644 > --- a/tcg/tcg.h > +++ b/tcg/tcg.h > @@ -268,18 +268,28 @@ typedef int TCGv_i64; > #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-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 { > - TCG_COND_EQ, > - TCG_COND_NE, > - TCG_COND_LT, > - TCG_COND_GE, > - TCG_COND_LE, > - TCG_COND_GT, > + /* non-signed */ > + TCG_COND_NEVER = 0 | 0 | 0 | 0, > + TCG_COND_ALWAYS = 0 | 0 | 0 | 1, > + TCG_COND_EQ = 8 | 0 | 0 | 0, > + TCG_COND_NE = 8 | 0 | 0 | 1, > + /* 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 */ > - TCG_COND_LTU, > - TCG_COND_GEU, > - TCG_COND_LEU, > - TCG_COND_GTU, > + TCG_COND_LTU = 0 | 4 | 0 | 0, > + TCG_COND_GEU = 0 | 4 | 0 | 1, > + TCG_COND_LEU = 8 | 4 | 0 | 0, > + TCG_COND_GTU = 8 | 4 | 0 | 1, > } TCGCond; > > /* Invert the sense of the comparison. */ > @@ -291,13 +301,17 @@ static inline TCGCond tcg_invert_cond(TCGCond c) > /* Swap the operands in a comparison. */ > static inline TCGCond tcg_swap_cond(TCGCond c) > { > - int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15); > - return (TCGCond)(c ^ mask); > + return c & 6 ? (TCGCond)(c ^ 9) : 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) > +{ > + return (c & 4) != 0; > } > > #define TEMP_VAL_DEAD 0 Technically looks fine, but I still don't really fully see the point of doing that. So I guess: Reviewed: Aurelien Jarno <aurelien@aurel32.net>
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index cf0ca3d..bb9516c 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -342,7 +342,7 @@ enum arm_cond_code_e { 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_NE] = COND_NE, [TCG_COND_LT] = COND_LT, diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 2885212..9cd97d5 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -738,7 +738,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_NE] = COND_EQ | COND_FALSE, diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index da17bba..5dfa113 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -338,7 +338,7 @@ static inline int tcg_target_const_match(tcg_target_long val, #define JCC_JLE 0xe #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_NE] = JCC_JNE, [TCG_COND_LT] = JCC_JL, diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 0cff181..4c70fba 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -456,7 +456,7 @@ enum { 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_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 27a0ae8..62dff6a 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -428,7 +428,7 @@ enum { 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_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 04662c1..2bffdb2 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -268,7 +268,7 @@ static const int tcg_target_call_oarg_regs[] = { #define S390_CC_ALWAYS 15 /* 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_NE] = S390_CC_NE, [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 unsigned instruction variation, however since the test is vs zero we 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_NE] = S390_CC_NE, [TCG_COND_LT] = S390_CC_LT, @@ -1138,7 +1138,7 @@ static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val) static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, TCGArg c2, int c2const) { - bool is_unsigned = (c > TCG_COND_GT); + bool is_unsigned = is_unsigned_cond(c); if (c2const) { if (c2 == 0) { if (type == TCG_TYPE_I32) { diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 247a278..0a25065 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -510,7 +510,7 @@ static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index) } #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_NE] = COND_NE, [TCG_COND_LT] = COND_L, diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 169d3b2..96a30de 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -627,29 +627,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, 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, int32_t arg2, int label_index) { - TCGv_i32 t0 = tcg_const_i32(arg2); - tcg_gen_brcond_i32(cond, arg1, t0, label_index); - tcg_temp_free_i32(t0); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_br(label_index); + } 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, 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, TCGv_i32 arg1, int32_t arg2) { - TCGv_i32 t0 = tcg_const_i32(arg2); - tcg_gen_setcond_i32(cond, ret, arg1, t0); - tcg_temp_free_i32(t0); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_movi_i32(ret, 1); + } 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) @@ -945,17 +965,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, TCGv_i64 arg2, int label_index) { - tcg_gen_op6ii_i32(INDEX_op_brcond2_i32, - TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2), - TCGV_HIGH(arg2), cond, label_index); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_br(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, TCGv_i64 arg1, TCGv_i64 arg2) { - tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret), - TCGV_LOW(arg1), TCGV_HIGH(arg1), - TCGV_LOW(arg2), TCGV_HIGH(arg2), cond); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_movi_i32(TCGV_LOW(ret), 1); + } 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); } @@ -1210,13 +1240,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, 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, 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) @@ -1334,9 +1374,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, int64_t arg2, int label_index) { - TCGv_i64 t0 = tcg_const_i64(arg2); - tcg_gen_brcond_i64(cond, arg1, t0, label_index); - tcg_temp_free_i64(t0); + if (cond == TCG_COND_ALWAYS) { + tcg_gen_br(label_index); + } 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, diff --git a/tcg/tcg.c b/tcg/tcg.c index 8386b70..42c3b40 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -861,6 +861,8 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val) static const char * const cond_name[] = { + [TCG_COND_NEVER] = "never", + [TCG_COND_ALWAYS] = "always", [TCG_COND_EQ] = "eq", [TCG_COND_NE] = "ne", [TCG_COND_LT] = "lt", diff --git a/tcg/tcg.h b/tcg/tcg.h index a9367fe..6c37f15 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -268,18 +268,28 @@ typedef int TCGv_i64; #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-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 { - TCG_COND_EQ, - TCG_COND_NE, - TCG_COND_LT, - TCG_COND_GE, - TCG_COND_LE, - TCG_COND_GT, + /* non-signed */ + TCG_COND_NEVER = 0 | 0 | 0 | 0, + TCG_COND_ALWAYS = 0 | 0 | 0 | 1, + TCG_COND_EQ = 8 | 0 | 0 | 0, + TCG_COND_NE = 8 | 0 | 0 | 1, + /* 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 */ - TCG_COND_LTU, - TCG_COND_GEU, - TCG_COND_LEU, - TCG_COND_GTU, + TCG_COND_LTU = 0 | 4 | 0 | 0, + TCG_COND_GEU = 0 | 4 | 0 | 1, + TCG_COND_LEU = 8 | 4 | 0 | 0, + TCG_COND_GTU = 8 | 4 | 0 | 1, } TCGCond; /* Invert the sense of the comparison. */ @@ -291,13 +301,17 @@ static inline TCGCond tcg_invert_cond(TCGCond c) /* Swap the operands in a comparison. */ static inline TCGCond tcg_swap_cond(TCGCond c) { - int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15); - return (TCGCond)(c ^ mask); + return c & 6 ? (TCGCond)(c ^ 9) : 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) +{ + return (c & 4) != 0; } #define TEMP_VAL_DEAD 0
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> Cc: Aurelien Jarno <aurelien@aurel32.net> --- tcg/arm/tcg-target.c | 2 +- tcg/hppa/tcg-target.c | 2 +- tcg/i386/tcg-target.c | 2 +- tcg/ppc/tcg-target.c | 2 +- tcg/ppc64/tcg-target.c | 2 +- tcg/s390/tcg-target.c | 6 ++-- tcg/sparc/tcg-target.c | 2 +- tcg/tcg-op.h | 82 ++++++++++++++++++++++++++++++++++++++------------ tcg/tcg.c | 2 ++ tcg/tcg.h | 40 ++++++++++++++++-------- 10 files changed, 101 insertions(+), 41 deletions(-)