From patchwork Tue Mar 5 00:32:53 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 224873 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 1E2772C040A for ; Tue, 5 Mar 2013 11:40:15 +1100 (EST) Received: from localhost ([::1]:50594 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UCfvR-0007uU-8b for incoming@patchwork.ozlabs.org; Mon, 04 Mar 2013 19:40:13 -0500 Received: from eggs.gnu.org ([208.118.235.92]:45940) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UCfp3-0005YZ-IQ for qemu-devel@nongnu.org; Mon, 04 Mar 2013 19:33:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UCfp0-00047Q-Fl for qemu-devel@nongnu.org; Mon, 04 Mar 2013 19:33:37 -0500 Received: from mail-ia0-x229.google.com ([2607:f8b0:4001:c02::229]:63524) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UCfp0-00047I-9y for qemu-devel@nongnu.org; Mon, 04 Mar 2013 19:33:34 -0500 Received: by mail-ia0-f169.google.com with SMTP id j5so5556217iaf.0 for ; Mon, 04 Mar 2013 16:33:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=s1Wtr0jLi5bWGhohs/eafLRX9hsR/gNOqylPCVHUOjI=; b=e3ND2fZ/k8KSUeZ2SVZgZae6/7soIwJy+zRKhphgHM+bWQ7v3mwF7ZaSOfauKhBHDR 6sC1mpZatdAu+GEtwArfQ0i1w2wyAk3rq0t5bzbgoDfDzAtKbOgzku3F2zNZYGN+zT1A Wkyk2MfOwO6OhWfHZXYDcLrPrDDvE8RLYCFwyq5ldzlI7CtbUHubxR+OTtKXRxj/uuZm qSrVIimaAhWhhKU1NEYIy6H33UOtr6HnP9amwoxzRBhNYN/slSK8hATb4g70ESERDcvW u+Pd0sleIxzLdtkdZw6LN7N3XDKiKzecWbjkTF6+oCJwdU01Zya3AW6MuzfQn+d3ayqj k5/g== X-Received: by 10.42.67.10 with SMTP id r10mr25633759ici.7.1362443613850; Mon, 04 Mar 2013 16:33:33 -0800 (PST) Received: from pebble.twiddle.net (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPS id ih1sm12171205igc.3.2013.03.04.16.33.32 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 04 Mar 2013 16:33:33 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Mon, 4 Mar 2013 16:32:53 -0800 Message-Id: <1362443590-28191-11-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1362443590-28191-1-git-send-email-rth@twiddle.net> References: <1362443590-28191-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:4001:c02::229 Cc: av1474@comtv.ru Subject: [Qemu-devel] [PATCH v2 10/27] tcg-ppc64: Improve constant add and sub ops. 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 Use SUBFIC to implement subtraction with constant op1. Improve constant addition -- previously we'd emit useless addis with 0. Use new constraints to force the driver to pull full 64-bit constants into a register. Signed-off-by: Richard Henderson Reviewed-by: Aurelien Jarno --- tcg/ppc64/tcg-target.c | 117 ++++++++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 45 deletions(-) diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 0e4826d..d12fd61 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -329,6 +329,7 @@ static int tcg_target_const_match (tcg_target_long val, #define MULLI OPCD( 7) #define CMPLI OPCD( 10) #define CMPI OPCD( 11) +#define SUBFIC OPCD( 8) #define LWZU OPCD( 33) #define STWU OPCD( 37) @@ -988,32 +989,6 @@ static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX); } -static void ppc_addi32(TCGContext *s, TCGReg rt, TCGReg ra, tcg_target_long si) -{ - if (!si && rt == ra) - return; - - if (si == (int16_t) si) - tcg_out32(s, ADDI | TAI(rt, ra, si)); - else { - uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15); - tcg_out32(s, ADDIS | TAI(rt, ra, h)); - tcg_out32(s, ADDI | TAI(rt, rt, si)); - } -} - -static void ppc_addi64(TCGContext *s, TCGReg rt, TCGReg ra, tcg_target_long si) -{ - /* XXX: suboptimal */ - if (si == (int16_t) si - || ((((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0)) - ppc_addi32 (s, rt, ra, si); - else { - tcg_out_movi (s, TCG_TYPE_I64, 0, si); - tcg_out32(s, ADD | TAB(rt, ra, 0)); - } -} - static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2, int const_arg2, int cr, int arch64) { @@ -1226,6 +1201,7 @@ void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr) static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args) { + TCGArg a0, a1, a2; int c; switch (opc) { @@ -1314,16 +1290,37 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, break; case INDEX_op_add_i32: - if (const_args[2]) - ppc_addi32 (s, args[0], args[1], args[2]); - else - tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); + a0 = args[0], a1 = args[1], a2 = args[2]; + if (const_args[2]) { + int32_t l, h; + do_addi_32: + l = (int16_t)a2; + h = a2 - l; + if (h) { + tcg_out32(s, ADDIS | TAI(a0, a1, h >> 16)); + a1 = a0; + } + if (l || a0 != a1) { + tcg_out32(s, ADDI | TAI(a0, a1, l)); + } + } else { + tcg_out32(s, ADD | TAB(a0, a1, a2)); + } break; case INDEX_op_sub_i32: - if (const_args[2]) - ppc_addi32 (s, args[0], args[1], -args[2]); - else - tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); + a0 = args[0], a1 = args[1], a2 = args[2]; + if (const_args[1]) { + if (const_args[2]) { + tcg_out_movi(s, TCG_TYPE_I32, a0, a1 - a2); + } else { + tcg_out32(s, SUBFIC | TAI(a0, a2, a1)); + } + } else if (const_args[2]) { + a2 = -a2; + goto do_addi_32; + } else { + tcg_out32(s, SUBF | TAB(a0, a2, a1)); + } break; case INDEX_op_and_i64: @@ -1453,16 +1450,46 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, break; case INDEX_op_add_i64: - if (const_args[2]) - ppc_addi64 (s, args[0], args[1], args[2]); - else - tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); + a0 = args[0], a1 = args[1], a2 = args[2]; + if (const_args[2]) { + int32_t l0, h1, h2; + do_addi_64: + /* We can always split any 32-bit constant into + 3 sign-extending pieces. */ + l0 = (int16_t)a2; + a2 -= l0; + h1 = ((int64_t)a2 > 0 && (int32_t)a2 < 0 ? 0x40000000 : 0); + h2 = a2 - h1; + + if (h2) { + tcg_out32(s, ADDIS | TAI(a0, a1, h2 >> 16)); + a1 = a0; + } + if (h1) { + tcg_out32(s, ADDIS | TAI(a0, a1, h1 >> 16)); + a1 = a0; + } + if (l0 || a0 != a1) { + tcg_out32(s, ADDI | TAI(a0, a1, l0)); + } + } else { + tcg_out32(s, ADD | TAB(a0, a1, a2)); + } break; case INDEX_op_sub_i64: - if (const_args[2]) - ppc_addi64 (s, args[0], args[1], -args[2]); - else - tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); + a0 = args[0], a1 = args[1], a2 = args[2]; + if (const_args[1]) { + if (const_args[2]) { + tcg_out_movi(s, TCG_TYPE_I64, a0, a1 - a2); + } else { + tcg_out32(s, SUBFIC | TAI(a0, a2, a1)); + } + } else if (const_args[2]) { + a2 = -a2; + goto do_addi_64; + } else { + tcg_out32(s, SUBF | TAB(a0, a2, a1)); + } break; case INDEX_op_shl_i64: @@ -1613,7 +1640,7 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_divu_i32, { "r", "r", "r" } }, { INDEX_op_rem_i32, { "r", "r", "r" } }, { INDEX_op_remu_i32, { "r", "r", "r" } }, - { INDEX_op_sub_i32, { "r", "r", "ri" } }, + { INDEX_op_sub_i32, { "r", "rI", "ri" } }, { INDEX_op_and_i32, { "r", "r", "ri" } }, { INDEX_op_or_i32, { "r", "r", "ri" } }, { INDEX_op_xor_i32, { "r", "r", "ri" } }, @@ -1628,8 +1655,8 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_neg_i32, { "r", "r" } }, { INDEX_op_not_i32, { "r", "r" } }, - { INDEX_op_add_i64, { "r", "r", "ri" } }, - { INDEX_op_sub_i64, { "r", "r", "ri" } }, + { INDEX_op_add_i64, { "r", "r", "rTU" } }, + { INDEX_op_sub_i64, { "r", "rI", "rTU" } }, { INDEX_op_and_i64, { "r", "r", "rU" } }, { INDEX_op_or_i64, { "r", "r", "rU" } }, { INDEX_op_xor_i64, { "r", "r", "rU" } },