From patchwork Wed Aug 12 16:18:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyrylo Tkachov X-Patchwork-Id: 506693 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 26D8F1401B5 for ; Thu, 13 Aug 2015 02:19:01 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=NA8BrVky; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=uuw3GuerVL3Cvm9MjKPO579kR2xXhhMNyRBWjNyFm2Jv7C 7rRw1v/KbLrVzew6GgKehFvE1pwtKYGTI48FK3mMmwlobS3WDI7wwG2Y/0yLlz8L 54x8wNrtgFn6RRjD+3M1UPSMA2cWa/8z4V9qifMR8dIYveotLf4viQhafZKU8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=ksvmKPLM6WGRotOMKcJ8ttztJkQ=; b=NA8BrVkyC8FLBkk08DBd QpInVDxGn56p9Bp1TMPiWprX5Drb2dH1Siw+uItC9Zd/M4Hkv7hr710H8fgey/Kv kMNtEmQ6W9rR11bJfwghbqKMgMCd9M4jfCm1LMapg/sgnjjH46YaIImW1nvMD2Nq nCzvPHiZ+WrmcPawa56eC8I= Received: (qmail 31001 invoked by alias); 12 Aug 2015 16:18:54 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 30986 invoked by uid 89); 12 Aug 2015 16:18:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, SPF_PASS autolearn=ham version=3.3.2 X-HELO: eu-smtp-delivery-143.mimecast.com Received: from eu-smtp-delivery-143.mimecast.com (HELO eu-smtp-delivery-143.mimecast.com) (207.82.80.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 12 Aug 2015 16:18:51 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-38-XSJ6vywOSoWn5DCaaqCIUA-1; Wed, 12 Aug 2015 17:18:45 +0100 Received: from [10.2.207.50] ([10.1.2.79]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 12 Aug 2015 17:18:45 +0100 Message-ID: <55CB71E4.6040507@arm.com> Date: Wed, 12 Aug 2015 17:18:44 +0100 From: Kyrill Tkachov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: GCC Patches Subject: [PATCH][RTL-ifcvt] Allow PLUS+immediate expression in noce_try_store_flag_constants X-MC-Unique: XSJ6vywOSoWn5DCaaqCIUA-1 X-IsSubscribed: yes Hi all, This patch is a sequel to: https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02567.html It allows if-conversion of expressions of the form: if (test) x := y + c1; else x := y + c2 where c1 and c2 are a pair constants that can be optimised using the existing rules in noce_try_store_flag_constants. The resulting sequence looks something like: x := (test [!=,==] 0) + y; x := x + [c1,c2]; This patch reuses the logic for the combinations of diff and STORE_FLAG signs that is hammered out in https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02567.html. That means we just extract the constants c1 and c2 from the PLUS rtx and use their diff as the driver for the logic in that function. Currently, this patch allows only the case where diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE as it is the most beneficial case (from looking at SPEC2006 on aarch64) and also the least tricky to get right. In the future I suppose that restriction can be relaxed if needed, but in any case this should be an improvement over the existing situation. On aarch64 this allows us for code: int barsi (int x) { return x > 100 ? x + 4 : x + 3; } to generate: barsi: cmp w0, 101 cinc w0, w0, ge add w0, w0, 3 ret instead of the current: barsi: add w1, w0, 4 add w2, w0, 3 cmp w0, 101 csel w0, w2, w1, lt ret thus saving one instruction and using two fewer registers. Bootstrapped and tested on arm, aarch64, x86_64. Ok for trunk? Thanks, Kyrill 2015-08-12 Kyrylo Tkachov * ifcvt.c (noce_try_store_flag_constants): Handle PLUS-immediate expressions in A and B. 2015-08-12 Kyrylo Tkachov * gcc.target/aarch64/cinc_common_1.c: New test. commit ce0de8d30962bf00339dc3a030401a4be2a7a248 Author: Kyrylo Tkachov Date: Thu Jul 30 15:14:27 2015 +0100 [ifcvt][unfinished] Allow PLUS+immediate expression in noce_try_store_flag_constants diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index f815166..7a44e29 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -1198,17 +1198,35 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) HOST_WIDE_INT itrue, ifalse, diff, tmp; int normalize; bool can_reverse; - machine_mode mode; + machine_mode mode = GET_MODE (if_info->x);; + rtx common = NULL_RTX; if (!noce_simple_bbs (if_info)) return FALSE; - if (CONST_INT_P (if_info->a) - && CONST_INT_P (if_info->b)) + rtx a = if_info->a; + rtx b = if_info->b; + + /* Handle cases like x := test ? y + 3 : y + 4. */ + if (GET_CODE (a) == PLUS + && GET_CODE (b) == PLUS + && CONST_INT_P (XEXP (a, 1)) + && CONST_INT_P (XEXP (b, 1)) + && rtx_equal_p (XEXP (a, 0), XEXP (b, 0)) + && noce_operand_ok (XEXP (a, 0)) + && if_info->branch_cost >= 2) { - mode = GET_MODE (if_info->x); - ifalse = INTVAL (if_info->a); - itrue = INTVAL (if_info->b); + common = XEXP (a, 0); + + a = XEXP (a, 1); + b = XEXP (b, 1); + } + + if (CONST_INT_P (a) + && CONST_INT_P (b)) + { + ifalse = INTVAL (a); + itrue = INTVAL (b); bool subtract_flag_p = false; diff = (unsigned HOST_WIDE_INT) itrue - ifalse; @@ -1241,6 +1259,11 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) { reversep = can_reverse; subtract_flag_p = !can_reverse; + /* If we need to subtract the flag and we have PLUS-immediate + A and B then it is unlikely to be beneficial to play tricks + here. */ + if (subtract_flag_p && common) + return FALSE; } /* test ? 3 : 4 => can_reverse | 3 + (test == 0) @@ -1249,6 +1272,11 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) { reversep = can_reverse; subtract_flag_p = !can_reverse; + /* If we need to subtract the flag and we have PLUS-immediate + A and B then it is unlikely to be beneficial to play tricks + here. */ + if (subtract_flag_p && common) + return FALSE; } /* test ? 4 : 3 => 4 + (test != 0). */ @@ -1290,6 +1318,15 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) } start_sequence (); + + /* If we have x := test ? x + 3 : x + 4 then move the original + x out of the way while we store flags. */ + if (common && rtx_equal_p (common, if_info->x)) + { + common = gen_reg_rtx (mode); + noce_emit_move_insn (common, if_info->x); + } + target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize); if (! target) { @@ -1301,13 +1338,27 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) => x = 3 + (test == 0); */ if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE) { + /* Add the common part now. This may allow combine to merge this + with the store flag operation earlier into some sort of conditional + increment/decrement if the target allows it. */ + if (common) + target = expand_simple_binop (mode, PLUS, + target, common, + target, 0, OPTAB_WIDEN); + /* Always use ifalse here. It should have been swapped with itrue when appropriate when reversep is true. */ target = expand_simple_binop (mode, subtract_flag_p ? MINUS : PLUS, gen_int_mode (ifalse, mode), target, if_info->x, 0, OPTAB_WIDEN); } - + /* Other cases are not beneficial when the original A and B are PLUS + expressions. */ + else if (common) + { + end_sequence (); + return FALSE; + } /* if (test) x = 8; else x = 0; => x = (test != 0) << 3; */ else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0) diff --git a/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c b/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c new file mode 100644 index 0000000..d041263 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c @@ -0,0 +1,64 @@ +/* { dg-do run } */ +/* { dg-options "-save-temps -O2 -fno-inline" } */ + +extern void abort (void); + +int +foosi (int x) +{ + return x > 100 ? x - 2 : x - 1; +} + +int +barsi (int x) +{ + return x > 100 ? x + 4 : x + 3; +} + +long +foodi (long x) +{ + return x > 100 ? x - 2 : x - 1; +} + +long +bardi (long x) +{ + return x > 100 ? x + 4 : x + 3; +} + +/* { dg-final { scan-assembler-times "cs?inc\tw\[0-9\]*" 2 } } */ +/* { dg-final { scan-assembler-times "cs?inc\tx\[0-9\]*" 2 } } */ + +int +main (void) +{ + if (foosi (105) != 103) + abort (); + + if (foosi (95) != 94) + abort (); + + if (barsi (105) != 109) + abort (); + + if (barsi (95) != 98) + abort (); + + if (foodi (105) != 103) + abort (); + + if (foodi (95) != 94) + abort (); + + if (bardi (105) != 109) + abort (); + + if (bardi (95) != 98) + abort (); + + return 0; +} + +/* { dg-final { scan-assembler-not "csel\tx\[0-9\]*.*" } } */ +/* { dg-final { scan-assembler-not "csel\tw\[0-9\]*.*" } } */