From patchwork Sat Jun 13 09:57:27 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 483829 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 7756914028F for ; Sat, 13 Jun 2015 19:57:42 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=bzMyoLKo; 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:from :to:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=aZHPvmBIc2FsoLiTrPgqBi3pwVwSl5pQGdOYVeL15O39eVuSS3OeN ByywE/0vCUa+eSD5DhnJd/nZ9Vf4Q/5PSu4r2R/RS0op1eUiYiUd6SOz2xJmV5rZ 0wWP0OhU6VG6ypWWCwgxNgsW/LknxhtUOx+Tfzenig8F36dQVdcc80= 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:from :to:subject:date:message-id:mime-version:content-type; s= default; bh=v4I+IRPWHhFgRmySs8C6ubEhKzk=; b=bzMyoLKo8TkC0RJWz+QH 8kpv/I0OYTQUi/m/IKQ8vmVHDB6vcZP49Zp+PeKOs+CeaiiHdW8qErWLWAoxMXTN yt6pFML63R+QiiZCOrIBABPGHP9eZJM99msYw+RUPywzxs0fySz89EGUDZxCwWJg ubnYOdiblclrH1xBfA378HI= Received: (qmail 89268 invoked by alias); 13 Jun 2015 09:57:35 -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 89259 invoked by uid 89); 13 Jun 2015 09:57:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.5 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-wi0-f171.google.com Received: from mail-wi0-f171.google.com (HELO mail-wi0-f171.google.com) (209.85.212.171) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Sat, 13 Jun 2015 09:57:32 +0000 Received: by wiga1 with SMTP id a1so34889108wig.0 for ; Sat, 13 Jun 2015 02:57:29 -0700 (PDT) X-Received: by 10.194.61.236 with SMTP id t12mr34425571wjr.59.1434189449381; Sat, 13 Jun 2015 02:57:29 -0700 (PDT) Received: from localhost ([95.144.14.193]) by mx.google.com with ESMTPSA id ej5sm9636542wjd.22.2015.06.13.02.57.28 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 13 Jun 2015 02:57:28 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, rdsandiford@googlemail.com Subject: RFA: Make classify_insn available to the generators Date: Sat, 13 Jun 2015 10:57:27 +0100 Message-ID: <87381w3p88.fsf@googlemail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) MIME-Version: 1.0 gen_expand and gen_split have some fairly complex tests that really just repeat what's in classify_insn. This patch moves classify_insn to rtl.c, so that it's available to the generators. It also adds a generator-specific UNKNOWN return code for cases where we need to choose at (GCC) runtime. This is preparing for a patch series that I'll post about soon. Bootstrapped & regression-tested on x86_64-linux-gnu. Also tested with config-list.mk. OK for the rtl bits? The test for whether a barrier is needed seems a little weak: what about indirect jumps, jumps with match_operand sources, or jumps in PARALLELs? That for another day though. At least this patch means we'll only have to update one place rather than two. Thanks, Richard gcc/ * rtl.h (classify_insn): Declare. * emit-rtl.c (classify_insn): Move to... * rtl.c: ...here and add generator support. * gensupport.h (get_emit_function, needs_barrier_p): Declare. * gensupport.c (get_emit_function, needs_barrier_p): New functions. * genemit.c (gen_emit_seq): New function. (gen_expand, gen_split): Use it. Index: gcc/rtl.h =================================================================== --- gcc/rtl.h 2015-06-13 10:37:47.781963830 +0100 +++ gcc/rtl.h 2015-06-13 10:38:55.640981540 +0100 @@ -2665,6 +2665,7 @@ extern rtvec rtvec_alloc (int); extern rtvec shallow_copy_rtvec (rtvec); extern bool shared_const_p (const_rtx); extern rtx copy_rtx (rtx); +extern enum rtx_code classify_insn (rtx); extern void dump_rtx_statistics (void); /* In emit-rtl.c */ Index: gcc/emit-rtl.c =================================================================== --- gcc/emit-rtl.c 2015-06-13 10:37:47.781963830 +0100 +++ gcc/emit-rtl.c 2015-06-13 10:38:55.638981628 +0100 @@ -5309,43 +5309,6 @@ set_dst_reg_note (rtx insn, enum reg_not return NULL_RTX; } -/* Return an indication of which type of insn should have X as a body. - The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */ - -static enum rtx_code -classify_insn (rtx x) -{ - if (LABEL_P (x)) - return CODE_LABEL; - if (GET_CODE (x) == CALL) - return CALL_INSN; - if (ANY_RETURN_P (x)) - return JUMP_INSN; - if (GET_CODE (x) == SET) - { - if (SET_DEST (x) == pc_rtx) - return JUMP_INSN; - else if (GET_CODE (SET_SRC (x)) == CALL) - return CALL_INSN; - else - return INSN; - } - if (GET_CODE (x) == PARALLEL) - { - int j; - for (j = XVECLEN (x, 0) - 1; j >= 0; j--) - if (GET_CODE (XVECEXP (x, 0, j)) == CALL) - return CALL_INSN; - else if (GET_CODE (XVECEXP (x, 0, j)) == SET - && SET_DEST (XVECEXP (x, 0, j)) == pc_rtx) - return JUMP_INSN; - else if (GET_CODE (XVECEXP (x, 0, j)) == SET - && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) - return CALL_INSN; - } - return INSN; -} - /* Emit the rtl pattern X as an appropriate kind of insn. If X is a label, it is simply added into the insn chain. */ Index: gcc/rtl.c =================================================================== --- gcc/rtl.c 2015-06-13 10:37:47.781963830 +0100 +++ gcc/rtl.c 2015-06-13 10:38:55.639981584 +0100 @@ -658,6 +658,54 @@ rtx_equal_p (const_rtx x, const_rtx y) return 1; } +/* Return an indication of which type of insn should have X as a body. + In generator files, this can be UNKNOWN if the answer is only known + at (GCC) runtime. Otherwise the value is CODE_LABEL, INSN, CALL_INSN + or JUMP_INSN. */ + +enum rtx_code +classify_insn (rtx x) +{ + if (LABEL_P (x)) + return CODE_LABEL; + if (GET_CODE (x) == CALL) + return CALL_INSN; + if (ANY_RETURN_P (x)) + return JUMP_INSN; + if (GET_CODE (x) == SET) + { + if (GET_CODE (SET_DEST (x)) == PC) + return JUMP_INSN; + else if (GET_CODE (SET_SRC (x)) == CALL) + return CALL_INSN; + else + return INSN; + } + if (GET_CODE (x) == PARALLEL) + { + int j; + for (j = XVECLEN (x, 0) - 1; j >= 0; j--) + if (GET_CODE (XVECEXP (x, 0, j)) == CALL) + return CALL_INSN; + else if (GET_CODE (XVECEXP (x, 0, j)) == SET + && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC) + return JUMP_INSN; + else if (GET_CODE (XVECEXP (x, 0, j)) == SET + && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) + return CALL_INSN; + } +#ifdef GENERATOR_FILE + if (GET_CODE (x) == MATCH_OPERAND + || GET_CODE (x) == MATCH_OPERATOR + || GET_CODE (x) == MATCH_PARALLEL + || GET_CODE (x) == MATCH_OP_DUP + || GET_CODE (x) == MATCH_DUP + || GET_CODE (x) == PARALLEL) + return UNKNOWN; +#endif + return INSN; +} + void dump_rtx_statistics (void) { Index: gcc/gensupport.h =================================================================== --- gcc/gensupport.h 2015-06-13 10:38:52.370125288 +0100 +++ gcc/gensupport.h 2015-06-13 10:38:55.639981584 +0100 @@ -111,5 +111,7 @@ struct pattern_stats extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec); extern void compute_test_codes (rtx, int, char *); +extern const char *get_emit_function (rtx); +extern bool needs_barrier_p (rtx); #endif /* GCC_GENSUPPORT_H */ Index: gcc/gensupport.c =================================================================== --- gcc/gensupport.c 2015-06-13 10:38:52.370125288 +0100 +++ gcc/gensupport.c 2015-06-13 10:38:55.639981584 +0100 @@ -2983,3 +2983,37 @@ get_pattern_stats (struct pattern_stats MAX (stats->max_dup_opno, stats->max_scratch_opno)) + 1; } + +/* Return the emit_* function that should be used for pattern X. */ + +const char * +get_emit_function (rtx x) +{ + switch (classify_insn (x)) + { + case INSN: + return "emit_insn"; + + case CALL_INSN: + return "emit_call_insn"; + + case JUMP_INSN: + return "emit_jump_insn"; + + case UNKNOWN: + return "emit"; + + default: + gcc_unreachable (); + } +} + +/* Return true if we must emit a barrier after pattern X. */ + +bool +needs_barrier_p (rtx x) +{ + return (GET_CODE (x) == SET + && GET_CODE (SET_DEST (x)) == PC + && GET_CODE (SET_SRC (x)) == LABEL_REF); +} Index: gcc/genemit.c =================================================================== --- gcc/genemit.c 2015-06-13 10:38:52.369125332 +0100 +++ gcc/genemit.c 2015-06-13 10:38:55.639981584 +0100 @@ -268,6 +268,23 @@ gen_exp (rtx x, enum rtx_code subroutine } printf (")"); } + +/* Output code to emit the instruction patterns in VEC, with each element + becoming a separate instruction. USED is as for gen_exp. */ + +static void +gen_emit_seq (rtvec vec, char *used) +{ + for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) + { + rtx next = RTVEC_ELT (vec, i); + printf (" %s (", get_emit_function (next)); + gen_exp (next, DEFINE_EXPAND, used); + printf (");\n"); + if (needs_barrier_p (next)) + printf (" emit_barrier ();"); + } +} /* Generate the `gen_...' function for a DEFINE_INSN. */ @@ -475,49 +492,8 @@ gen_expand (rtx expand) printf (" }\n"); } - /* Output code to construct the rtl for the instruction bodies. - Use emit_insn to add them to the sequence being accumulated. - But don't do this if the user's code has set `no_more' nonzero. */ - used = XCNEWVEC (char, stats.num_operand_vars); - - for (i = 0; i < XVECLEN (expand, 1); i++) - { - rtx next = XVECEXP (expand, 1, i); - if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) - || (GET_CODE (next) == PARALLEL - && ((GET_CODE (XVECEXP (next, 0, 0)) == SET - && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) - || ANY_RETURN_P (XVECEXP (next, 0, 0)))) - || ANY_RETURN_P (next)) - printf (" emit_jump_insn ("); - else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) - || GET_CODE (next) == CALL - || (GET_CODE (next) == PARALLEL - && GET_CODE (XVECEXP (next, 0, 0)) == SET - && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) - || (GET_CODE (next) == PARALLEL - && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) - printf (" emit_call_insn ("); - else if (LABEL_P (next)) - printf (" emit_label ("); - else if (GET_CODE (next) == MATCH_OPERAND - || GET_CODE (next) == MATCH_DUP - || GET_CODE (next) == MATCH_OPERATOR - || GET_CODE (next) == MATCH_OP_DUP - || GET_CODE (next) == MATCH_PARALLEL - || GET_CODE (next) == MATCH_PAR_DUP - || GET_CODE (next) == PARALLEL) - printf (" emit ("); - else - printf (" emit_insn ("); - gen_exp (next, DEFINE_EXPAND, used); - printf (");\n"); - if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC - && GET_CODE (SET_SRC (next)) == LABEL_REF) - printf (" emit_barrier ();"); - } - + gen_emit_seq (XVEC (expand, 1), used); XDELETEVEC (used); /* Call `get_insns' to extract the list of all the @@ -601,44 +577,7 @@ gen_split (rtx split) printf (" (void) operand%d;\n", i); } - /* Output code to construct the rtl for the instruction bodies. - Use emit_insn to add them to the sequence being accumulated. - But don't do this if the user's code has set `no_more' nonzero. */ - - for (i = 0; i < XVECLEN (split, 2); i++) - { - rtx next = XVECEXP (split, 2, i); - if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) - || (GET_CODE (next) == PARALLEL - && GET_CODE (XVECEXP (next, 0, 0)) == SET - && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) - || ANY_RETURN_P (next)) - printf (" emit_jump_insn ("); - else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) - || GET_CODE (next) == CALL - || (GET_CODE (next) == PARALLEL - && GET_CODE (XVECEXP (next, 0, 0)) == SET - && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) - || (GET_CODE (next) == PARALLEL - && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) - printf (" emit_call_insn ("); - else if (LABEL_P (next)) - printf (" emit_label ("); - else if (GET_CODE (next) == MATCH_OPERAND - || GET_CODE (next) == MATCH_OPERATOR - || GET_CODE (next) == MATCH_PARALLEL - || GET_CODE (next) == MATCH_OP_DUP - || GET_CODE (next) == MATCH_DUP - || GET_CODE (next) == PARALLEL) - printf (" emit ("); - else - printf (" emit_insn ("); - gen_exp (next, GET_CODE (split), used); - printf (");\n"); - if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC - && GET_CODE (SET_SRC (next)) == LABEL_REF) - printf (" emit_barrier ();"); - } + gen_emit_seq (XVEC (split, 2), used); /* Call `get_insns' to make a list of all the insns emitted within this gen_... function. */