From patchwork Mon May 13 00:40:13 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joern Rennecke X-Patchwork-Id: 243226 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 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id A213E2C00A5 for ; Mon, 13 May 2013 10:40:24 +1000 (EST) 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:to:subject:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=ONwJN7qMW+dl1Y7F QfNlpcjyXNJ1NLK95qWQ9XidIxbvdmQSMtnWjJKn8AWQTXrR/hxkL/x/364+rpH7 JXehBZ4uwYEu7DUTD7GUynBTUkenL6Vr5fQW7Yxz1uir/ABEGTrxTLbHxtbo8hLO ZDfPo45D6ufURViKE8jgQQGkdWU= 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:to:subject:mime-version:content-type :content-transfer-encoding; s=default; bh=EByDq1jrd8n+laRQ9oNZJc WMZxE=; b=QXzLiok8YaiMUN3XqHtKu6ZUPhwRnk/X3lc81qHwM/jwqmeanm8nI9 MZKEuMmysoUZBKnEu1QTDAOxYqd8+b3awY6hetjYMq2zZQb+s1NnOdPPrUsYkLKI 4gY96jCAY+Xc5Hrk+I2mwxSAiLRIok54s6gUy3MFXthVA9ZG7GIss= Received: (qmail 15304 invoked by alias); 13 May 2013 00:40:17 -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 15294 invoked by uid 89); 13 May 2013 00:40:17 -0000 X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, MIME_QP_LONG_LINE, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from c62.cesmail.net (HELO c62.cesmail.net) (216.154.195.54) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Mon, 13 May 2013 00:40:15 +0000 Received: from unknown (HELO epsilon2) ([192.168.1.60]) by c62.cesmail.net with ESMTP; 12 May 2013 20:40:13 -0400 Received: from cust213-dsl91-135-11.idnet.net (cust213-dsl91-135-11.idnet.net [91.135.11.213]) by webmail.spamcop.net (Horde MIME library) with HTTP; Sun, 12 May 2013 20:40:13 -0400 Message-ID: <20130512204013.sp5y97czcwkk8ssg-nzlynne@webmail.spamcop.net> Date: Sun, 12 May 2013 20:40:13 -0400 From: Joern Rennecke To: gcc-patches@gcc.gnu.org Subject: Commited: fix epiphany data flow / mode switching problem MIME-Version: 1.0 User-Agent: Internet Messaging Program (IMP) H3 (4.1.4) X-Virus-Found: No Data flow based optimizations between mode switching and the emitting of the prologue code have become more aggressive, making it necessary to emit the saving of the config register during mode switching, lest mode switching instructions are deleted. Committed to trunk and gcc-4_8-branch. 2013-05-12 Joern Rennecke * config/epiphany/epiphany.c (epiphany_init): Check size of NUM_MODES_FOR_MODE_SWITCHING. (epiphany_expand_prologue): Remove CONFIG_REGNUM initial value handling code. (epiphany_optimize_mode_switching): Handle EPIPHANY_MSW_ENTITY_CONFIG. (epiphany_mode_needed, epiphany_mode_entry_exit): Likewise. (emit_set_fp_mode, epiphany_mode_after): Likewise. (epiphany_mode_needed) : Don't return 1 for FP_MODE_NONE. * config/epiphany/epiphany.h (NUM_MODES_FOR_MODE_SWITCHING): Add value for EPIPHANY_MSW_ENTITY_CONFIG. (EPIPHANY_MSW_ENTITY_CONFIG, EPIPHANY_MSW_ENTITY_NUM): Define. * config/epiphany/epiphany.md (save_config): New pattern. Index: config/epiphany/epiphany.c =================================================================== --- config/epiphany/epiphany.c (revision 198806) +++ config/epiphany/epiphany.c (working copy) @@ -181,6 +181,8 @@ epiphany_init (void) = { &pass_split_all_insns.pass, "mode_sw", 1, PASS_POS_INSERT_AFTER }; + static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING; +#define N_ENTITIES ARRAY_SIZE (num_modes) epiphany_init_reg_tables (); @@ -196,6 +198,8 @@ epiphany_init (void) register_pass (&mode_sw3_info); register_pass (&insert_use_info); register_pass (&mode_sw2_info); + /* Verify that NUM_MODES_FOR_MODE_SWITCHING has one value per entity. */ + gcc_assert (N_ENTITIES == EPIPHANY_MSW_ENTITY_NUM); #if 1 /* As long as peep2_rescan is not implemented, (see http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html,) @@ -1773,44 +1777,6 @@ epiphany_expand_prologue (void) } frame_insn (gen_stack_adjust_add (off, mem)); } - - /* Mode switching uses get_hard_reg_initial_val after - emit_initial_value_sets, so we have to fix this up now. */ - save_config = has_hard_reg_initial_val (SImode, CONFIG_REGNUM); - if (save_config) - { - if (REG_P (save_config)) - { - if (REGNO (save_config) >= FIRST_PSEUDO_REGISTER) - gcc_assert (!df_regs_ever_live_p (REGNO (save_config))); - else - frame_move_insn (save_config, - get_hard_reg_initial_reg (save_config)); - } - else - { - rtx save_dst = save_config; - - reg = gen_rtx_REG (SImode, GPR_IP); - gcc_assert (MEM_P (save_dst)); - if (!memory_operand (save_dst, SImode)) - { - rtx addr = XEXP (save_dst, 0); - rtx reg2 = gen_rtx_REG (SImode, GPR_16); - - gcc_assert (GET_CODE (addr) == PLUS); - gcc_assert (XEXP (addr, 0) == hard_frame_pointer_rtx - || XEXP (addr, 0) == stack_pointer_rtx); - emit_move_insn (reg2, XEXP (addr, 1)); - save_dst - = replace_equiv_address (save_dst, - gen_rtx_PLUS (Pmode, XEXP (addr, 0), - reg2)); - } - emit_move_insn (reg, get_hard_reg_initial_reg (save_config)); - emit_move_insn (save_dst, reg); - } - } } void @@ -2271,6 +2237,7 @@ epiphany_optimize_mode_switching (int en { case EPIPHANY_MSW_ENTITY_AND: case EPIPHANY_MSW_ENTITY_OR: + case EPIPHANY_MSW_ENTITY_CONFIG: return true; case EPIPHANY_MSW_ENTITY_NEAREST: case EPIPHANY_MSW_ENTITY_TRUNC: @@ -2289,7 +2256,8 @@ epiphany_optimize_mode_switching (int en int epiphany_mode_priority_to_mode (int entity, unsigned priority) { - if (entity == EPIPHANY_MSW_ENTITY_AND || entity == EPIPHANY_MSW_ENTITY_OR) + if (entity == EPIPHANY_MSW_ENTITY_AND || entity == EPIPHANY_MSW_ENTITY_OR + || entity== EPIPHANY_MSW_ENTITY_CONFIG) return priority; if (priority > 3) switch (priority) @@ -2341,7 +2309,8 @@ epiphany_mode_needed (int entity, rtx in if (recog_memoized (insn) < 0) { if (entity == EPIPHANY_MSW_ENTITY_AND - || entity == EPIPHANY_MSW_ENTITY_OR) + || entity == EPIPHANY_MSW_ENTITY_OR + || entity == EPIPHANY_MSW_ENTITY_CONFIG) return 2; return FP_MODE_NONE; } @@ -2350,9 +2319,24 @@ epiphany_mode_needed (int entity, rtx in switch (entity) { case EPIPHANY_MSW_ENTITY_AND: - return mode != FP_MODE_INT ? 1 : 2; + return mode != FP_MODE_NONE && mode != FP_MODE_INT ? 1 : 2; case EPIPHANY_MSW_ENTITY_OR: return mode == FP_MODE_INT ? 1 : 2; + case EPIPHANY_MSW_ENTITY_CONFIG: + /* We must know/save config before we set it to something else. + Where we need the original value, we are fine with having it + just unchanged from the function start. + Because of the nature of the mode switching optimization, + a restore will be dominated by a clobber. */ + if (mode != FP_MODE_NONE && mode != FP_MODE_CALLER) + return 1; + /* A cpecial case are abnormal edges, which are deemed to clobber + the mode as well. We need to pin this effect on a actually + dominating insn, and one where the frame can be accessed, too, in + case the pseudo used to save CONFIG doesn't get a hard register. */ + if (CALL_P (insn) && find_reg_note (insn, REG_EH_REGION, NULL_RTX)) + return 1; + return 2; case EPIPHANY_MSW_ENTITY_ROUND_KNOWN: if (recog_memoized (insn) == CODE_FOR_set_fp_mode) mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn); @@ -2396,6 +2380,10 @@ epiphany_mode_entry_exit (int entity, bo if (exit) return normal_mode == FP_MODE_INT ? 1 : 2; return 0; + case EPIPHANY_MSW_ENTITY_CONFIG: + if (exit) + return 2; + return normal_mode == FP_MODE_CALLER ? 0 : 1; case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN: if (normal_mode == FP_MODE_ROUND_NEAREST || normal_mode == FP_MODE_ROUND_TRUNC) @@ -2422,6 +2410,18 @@ epiphany_mode_after (int entity, int las return 0; return last_mode; } + /* If there is an abnormal edge, we don't want the config register to + be 'saved' again at the destination. + The frame pointer adjustment is inside a PARALLEL because of the + flags clobber. */ + if (entity == EPIPHANY_MSW_ENTITY_CONFIG && NONJUMP_INSN_P (insn) + && GET_CODE (PATTERN (insn)) == PARALLEL + && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET + && SET_DEST (XVECEXP (PATTERN (insn), 0, 0)) == frame_pointer_rtx) + { + gcc_assert (cfun->has_nonlocal_label); + return 1; + } if (recog_memoized (insn) < 0) return last_mode; if (get_attr_fp_mode (insn) == FP_MODE_ROUND_UNKNOWN @@ -2475,12 +2475,25 @@ emit_set_fp_mode (int entity, int mode, emit_move_insn (MACHINE_FUNCTION (cfun)->or_mask, GEN_INT(0x00080000)); return; } + else if (entity == EPIPHANY_MSW_ENTITY_CONFIG) + { + /* Mode switching optimization is done after emit_initial_value_sets, + so we have to take care of CONFIG_REGNUM here. */ + gcc_assert (mode >= 0 && mode <= 2); + rtx save = get_hard_reg_initial_val (SImode, CONFIG_REGNUM); + if (mode == 1) + emit_insn (gen_save_config (save)); + return; + } fp_mode = (enum attr_fp_mode) mode; src = NULL_RTX; switch (fp_mode) { case FP_MODE_CALLER: + /* The EPIPHANY_MSW_ENTITY_CONFIG processing must come later + so that the config save gets inserted before the first use. */ + gcc_assert (entity > EPIPHANY_MSW_ENTITY_CONFIG); src = get_hard_reg_initial_val (SImode, CONFIG_REGNUM); mask = MACHINE_FUNCTION (cfun)->and_mask; break; Index: config/epiphany/epiphany.h =================================================================== --- config/epiphany/epiphany.h (revision 198806) +++ config/epiphany/epiphany.h (working copy) @@ -896,7 +896,8 @@ #define OPTIMIZE_MODE_SWITCHING(ENTITY) finally an entity that runs in a second mode switching pass to resolve FP_MODE_ROUND_UNKNOWN. */ #define NUM_MODES_FOR_MODE_SWITCHING \ - { 2, 2, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE } + { 2, 2, 2, \ + FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE } #define MODE_NEEDED(ENTITY, INSN) epiphany_mode_needed((ENTITY), (INSN)) @@ -918,11 +919,13 @@ enum { EPIPHANY_MSW_ENTITY_AND, EPIPHANY_MSW_ENTITY_OR, + EPIPHANY_MSW_ENTITY_CONFIG, /* 1 means config is known or saved. */ EPIPHANY_MSW_ENTITY_NEAREST, EPIPHANY_MSW_ENTITY_TRUNC, EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN, EPIPHANY_MSW_ENTITY_ROUND_KNOWN, - EPIPHANY_MSW_ENTITY_FPU_OMNIBUS + EPIPHANY_MSW_ENTITY_FPU_OMNIBUS, + EPIPHANY_MSW_ENTITY_NUM }; extern int epiphany_normal_fp_rounding; Index: config/epiphany/epiphany.md =================================================================== --- config/epiphany/epiphany.md (revision 198806) +++ config/epiphany/epiphany.md (working copy) @@ -1448,6 +1448,16 @@ (define_insn "*movcc_i" [(set_attr "type" "flow") (set_attr "length" "20,4")]) +(define_insn_and_split "save_config" + [(set (match_operand:SI 0 "gpr_operand" "=r") (reg:SI CONFIG_REGNUM)) + (use (reg:SI FP_NEAREST_REGNUM)) + (use (reg:SI FP_TRUNCATE_REGNUM)) + (use (reg:SI FP_ANYFP_REGNUM))] + "" + "#" + "reload_completed" + [(set (match_dup 0) (reg:SI CONFIG_REGNUM))]) + (define_insn_and_split "set_fp_mode" [(set (reg:SI FP_NEAREST_REGNUM) (match_operand:SI 0 "set_fp_mode_operand" "rCfm"))