From patchwork Mon Sep 24 21:21:40 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 186568 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 4689B2C0085 for ; Tue, 25 Sep 2012 07:22:16 +1000 (EST) Received: from localhost ([::1]:48409 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGG6Y-0007Ww-9t for incoming@patchwork.ozlabs.org; Mon, 24 Sep 2012 17:22:14 -0400 Received: from eggs.gnu.org ([208.118.235.92]:48424) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGG6F-0007Hm-9Q for qemu-devel@nongnu.org; Mon, 24 Sep 2012 17:21:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TGG6D-0000g9-9G for qemu-devel@nongnu.org; Mon, 24 Sep 2012 17:21:55 -0400 Received: from mail-qa0-f52.google.com ([209.85.216.52]:42774) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TGG6D-0000g1-3X for qemu-devel@nongnu.org; Mon, 24 Sep 2012 17:21:53 -0400 Received: by qabg24 with SMTP id g24so2550154qab.4 for ; Mon, 24 Sep 2012 14:21:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=IqLuHdjghu/yHPf/EHEUQoL1oR66LEbYXY0OTA50Z4o=; b=SECawXeDWQiSsSZPV6SbpxoF8PKJ8MBCJjAH3bbXlSLxrAOc+/Za10zuPQq6dOLpZ/ S3v0PuM8NlZ7JNxmXy6ISKcl5DWOuLwpcFH9SNBLXuTxxMCZ/mKhhRHxIg3wtioFPOdJ g2AN3TMS/zhd8iy7j+jzh4MWt3386BtJGujZKITc3zXZfntWOvy41MkMEB51n7QrUy7q UGMyku4TpUT+2b9yXSei8zdz45MRCbnOKdVJNve72+okMtZG72juRB5bRCtXxyMI1Dun ObkYz3vb1QD1Qu/o+0+HGrqJ4vHblnFL5LDzE9FzAoFIBWOxXyWpUz3us3nFejdbOYvW s/+g== Received: by 10.229.69.92 with SMTP id y28mr7165117qci.9.1348521712550; Mon, 24 Sep 2012 14:21:52 -0700 (PDT) Received: from anchor.twiddle.home.com ([173.160.232.49]) by mx.google.com with ESMTPS id fl3sm26994652qab.3.2012.09.24.14.21.51 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 24 Sep 2012 14:21:52 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Mon, 24 Sep 2012 14:21:40 -0700 Message-Id: <1348521701-18238-3-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1348521701-18238-1-git-send-email-rth@twiddle.net> References: <1348521701-18238-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.216.52 Cc: aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 2/3] tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- tcg/arm/tcg-target.c | 2 +- tcg/hppa/tcg-target.c | 2 +- tcg/i386/tcg-target.c | 2 +- tcg/optimize.c | 6 ++++ tcg/ppc/tcg-target.c | 2 +- tcg/ppc64/tcg-target.c | 2 +- tcg/s390/tcg-target.c | 4 +-- tcg/sparc/tcg-target.c | 2 +- tcg/tcg-op.h | 82 ++++++++++++++++++++++++++++++++++++++------------ tcg/tcg.c | 2 ++ tcg/tcg.h | 37 ++++++++++++++--------- 11 files changed, 102 insertions(+), 41 deletions(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 2bad0a2..62196d1 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -335,7 +335,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 2c79c10..5eef1a6 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -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_NE] = COND_EQ | COND_FALSE, diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 122d636..b21c7d8 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/optimize.c b/tcg/optimize.c index 35532a1..edb2b0e 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -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; case TCG_COND_GTU: return (uint32_t)temps[x].val > (uint32_t)temps[y].val; + default: + break; } break; 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; case TCG_COND_GTU: return (uint64_t)temps[x].val > (uint64_t)temps[y].val; + default: + break; } break; } @@ -362,6 +366,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, case TCG_COND_LEU: case TCG_COND_EQ: return 1; + default: + break; } } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) { switch (c) { diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 90c275d..6519da0 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -437,7 +437,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 19944bc..a96432e 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -418,7 +418,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 6e95eba..e3b31c7 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, diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 8fd7f86..bb43e83 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -512,7 +512,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 6d28f82..d61b7f8 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 b3c2650..d349386 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -860,6 +860,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 120daab..c726122 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -266,18 +266,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. */ @@ -289,18 +299,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 >= TCG_COND_LTU; + return (c & 4) != 0; } #define TEMP_VAL_DEAD 0