From patchwork Sat May 7 01:52:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleg Endo X-Patchwork-Id: 619521 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 3r1s9x03kfz9t4g for ; Sat, 7 May 2016 11:53:24 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=c/ia06VF; 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:subject:from:to:date:content-type:mime-version; q= dns; s=default; b=g4jCVkqHCsRGHN2j0hHhV4nVAWhqlv/UQH+xFh4zBflkXs DdqmnfumTsQY/aIkBmsKITzD5SFZADHMxl3p+sy2tVomvIZnsv79lSCStXYTwxUQ j9EaXum+ZeXrpDnoykGHy0x/7/g7tTM38BDl+DFwD6NQSLcCZIQkoxS9PHfWw= 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:subject:from:to:date:content-type:mime-version; s= default; bh=vCdkB41XSfkQxueMWCyU0tiqyBA=; b=c/ia06VFIoBe4Pr5uJWj Zm//XmRXaPWBiU1c7JOOTGj35kISPt/FI3F7eIXvz8ILnD30o8IA37w3QVDYtrau TBIXo1/slpVrtPn9gs/M4TkcFGzuMSNEBGHL0/+DjE4WP7W+No0wu4QKz1p6dA8V GvcU3KmEWCGKLQ9GpxulDm0= Received: (qmail 4679 invoked by alias); 7 May 2016 01:53:15 -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 4664 invoked by uid 89); 7 May 2016 01:53:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=jump_target, designate X-HELO: mailout11.t-online.de Received: from mailout11.t-online.de (HELO mailout11.t-online.de) (194.25.134.85) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sat, 07 May 2016 01:53:04 +0000 Received: from fwd21.aul.t-online.de (fwd21.aul.t-online.de [172.20.27.66]) by mailout11.t-online.de (Postfix) with SMTP id 16130638B09 for ; Sat, 7 May 2016 03:52:59 +0200 (CEST) Received: from [192.168.0.16] (GQePewZeZhxl-m+RkD3vIw9+71mPWt56nbUiiutKN2SObYObvy4n9e8o4ZbtvbbgbS@[115.165.93.200]) by fwd21.t-online.de with (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384 encrypted) esmtp id 1ayrQN-4XBKd60; Sat, 7 May 2016 03:52:55 +0200 Message-ID: <1462585972.3864.24.camel@t-online.de> Subject: [SH][committed] Improve utilization of zero-displacement conditional branches From: Oleg Endo To: gcc-patches Date: Sat, 07 May 2016 10:52:52 +0900 Mime-Version: 1.0 X-IsSubscribed: yes Hi, On SH a conditional branch with a (physical) zero displacement jumps over the next instruction. On some SH hardware implementations these branches are handled in a special way which allows using it for conditional execution. A while ago I've added some hardcoded asm patterns to utilize this. It seems there has been an attempt to do something about it a long time ago with the "branch_zero" attribute. However I could not find any uses thereof and wasn't sure how to utilize it. The attached patch disables the delay slot (for the DBR pass) of conditional branches which branch over only one 2-byte instruction. This results in more zero-displacement branches to be emitted. Having this in place, it would also be possible to simplify those hardcoded asm patterns (e.g. SH abs patterns). However, while that works, doing so exposes the actual CFG to other passes and in quite some cases basic blocks get reordered in a very counterproductive way resulting in worse code. Tested on sh-elf with make -k check RUNTESTFLAGS="--target_board=sh-sim\{-m2/-ml,-m2/-mb, -m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}" Committed as r235993. Cheers, Oleg gcc/ChangeLog: * config/sh/sh-protos.h (sh_cbranch_distance): Declare new function. * config/sh/sh.c (sh_cbranch_distance): Implement it. * config/sh/sh.md (branch_zero): Remove define_attr. (define_delay): Disable delay slot if branch distance is one insn. diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index c47e2ea..d302394 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -348,6 +348,18 @@ private: extern sh_treg_insns sh_split_treg_set_expr (rtx x, rtx_insn* curr_insn); +enum +{ + /* An effective conditional branch distance of zero bytes is impossible. + Hence we can use it to designate an unknown value. */ + unknown_cbranch_distance = 0u, + infinite_cbranch_distance = ~0u +}; + +unsigned int +sh_cbranch_distance (rtx_insn* cbranch_insn, + unsigned int max_dist = infinite_cbranch_distance); + #endif /* RTX_CODE */ extern void sh_cpu_cpp_builtins (cpp_reader* pfile); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 809f679..6d1d1a3 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -1928,6 +1928,52 @@ sh_fixed_condition_code_regs (unsigned int* p1, unsigned int* p2) return true; } +/* Try to calculate the branch distance of a conditional branch in bytes. + + FIXME: Because of PR 59189 we can't use the CFG here. Instead just + walk from this insn into the next (fall-through) basic block and see if + we hit the label. */ +unsigned int +sh_cbranch_distance (rtx_insn* _cbranch_insn, unsigned int max_dist) +{ + rtx_jump_insn* cbranch_insn = safe_as_a (_cbranch_insn); + + if (dump_file) + { + fprintf (dump_file, "sh_cbranch_distance insn = \n"); + print_rtl_single (dump_file, cbranch_insn); + } + + unsigned int dist = 0; + + for (rtx_insn* i = next_nonnote_insn (cbranch_insn); + i != NULL && dist < max_dist; i = next_nonnote_insn (i)) + { + const unsigned int i_len = get_attr_length (i); + dist += i_len; + + if (dump_file) + fprintf (dump_file, " insn %d length = %u dist = %u\n", + INSN_UID (i), i_len, dist); + + if (rtx_code_label* l = dyn_cast (i)) + { + if (l == cbranch_insn->jump_target ()) + { + if (dump_file) + fprintf (dump_file, " cbranch dist = %u\n", dist); + return dist; + } + break; + } + } + + if (dump_file) + fprintf (dump_file, " cbranch dist = unknown\n"); + + return unknown_cbranch_distance; +} + enum rtx_code prepare_cbranch_operands (rtx *operands, machine_mode mode, enum rtx_code comparison) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 39270ce..406721d 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -477,16 +477,6 @@ (define_attr "is_sfunc" "" (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0))) -(define_attr "branch_zero" "yes,no" - (cond [(eq_attr "type" "!cbranch") (const_string "no") - (ne (symbol_ref "(next_active_insn (insn)\ - == (prev_active_insn\ - (XEXP (SET_SRC (PATTERN (insn)), 1))))\ - && get_attr_length (next_active_insn (insn)) == 2") - (const_int 0)) - (const_string "yes")] - (const_string "no"))) - ;; SH4 Double-precision computation with double-precision result - ;; the two halves are ready at different times. (define_attr "dfp_comp" "yes,no" @@ -539,8 +529,13 @@ (eq_attr "type" "!pstore,prget")) (nil) (nil)]) ;; Conditional branches with delay slots are available starting with SH2. +;; If zero displacement conditional branches are fast, disable the delay +;; slot if the branch jumps over only one 2-byte insn. (define_delay - (and (eq_attr "type" "cbranch") (match_test "TARGET_SH2")) + (and (eq_attr "type" "cbranch") + (match_test "TARGET_SH2") + (not (and (match_test "TARGET_ZDCBRANCH") + (match_test "sh_cbranch_distance (insn, 4) == 2")))) [(eq_attr "cond_delay_slot" "yes") (nil) (nil)]) ;; -------------------------------------------------------------------------