From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22092 invoked by alias); 13 Mar 2008 18:10:32 -0000 Received: (qmail 21754 invoked by uid 22791); 13 Mar 2008 18:10:30 -0000 X-Spam-Check-By: sourceware.org Received: from eos.fwall.u-szeged.hu (HELO eos.fwall.u-szeged.hu) (160.114.120.248) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 13 Mar 2008 18:10:04 +0000 Received: from localhost ([127.0.0.1] helo=eos.fwall.u-szeged.hu) by eos.fwall.u-szeged.hu with esmtp (Exim 4.67) (envelope-from ) id 1JZrsN-0002IG-UR for gcc-patches@gcc.gnu.org; Thu, 13 Mar 2008 19:10:00 +0100 Received: from sol.cc.u-szeged.hu ([160.114.8.24]) by eos.fwall.u-szeged.hu with esmtp (Exim 4.67) (envelope-from ) id 1JZrsN-0002ID-Pi for gcc-patches@gcc.gnu.org; Thu, 13 Mar 2008 19:09:59 +0100 Received: from d6104.ktv.u-szeged.hu ([160.114.136.104] helo=[192.168.2.106]) by sol.cc.u-szeged.hu with esmtp (Exim 4.51) id 1JZrsN-0004o0-Fj for gcc-patches@gcc.gnu.org; Thu, 13 Mar 2008 19:09:59 +0100 Message-ID: <47D96EBD.6020002@inf.u-szeged.hu> Date: Thu, 13 Mar 2008 18:10:00 -0000 From: =?ISO-8859-2?Q?G=E1bor_L=F3ki?= User-Agent: Mozilla Thunderbird 1.0.2 (Windows/20050317) MIME-Version: 1.0 To: GCC Patches Subject: [PATCH] Fix PR33642, unrecognizable insn for -frtl-abstract-sequences Content-Type: multipart/mixed; boundary="------------040003030607050705090805" X-SZTE-local: YES X-SZTE-HU-local: YES X-SZTE-AVcheck: YES Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2008-03/txt/msg00824.txt.bz2 This is a multi-part message in MIME format. --------------040003030607050705090805 Content-Type: text/plain; charset=ISO-8859-2; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1443 Hi, This patch fixes the PR33642 for rtl-factoring.c. It contains the following modifications: - Redesign the cost computation (based on 'get_attr_length'), because the previous one fails on many targets. - The generation of indirect jump sequence has been also modified. An intermediate register move have been inserted before indirect jump if the target requires it. - Use constant pool if the target doesn't allow to store a symbol reference directly to a register. - Detect the need of intermediate register and constant pool during initialization. Bootstrapped on i686-linux, x86_64-linux. Regtested on i686-linux, x86_64-linux, arm-eabi, mips-elf, powerpc-elf, sh-elf. It has a known deficiency: fails into an 'unrecognizable insn' error on arm-eabi with '-O0 -fPIC -frtl-abstract-sequences' flags. Currently I don't know why, but I will look into it. Ok for trunk? --Gabor 2008-03-13 Gabor Loki PR gcc/33642 * rtl-factoring.c (get_default_length, compute_rtx_length): New. Computes the length of INSNs. (compute_rtx_cost): Use COMPUTE_RTX_LENGTH instead of GET_ATTR_LENGTH. (match_seqs): Initialize IJMP_REG field. (recompute_gain_for_pattern_seq): Find a register for IJMP_REG. (gen_symbol_ref_rtx_for_label): Force constant to memory if necessary. (split_pattern_seq): Use IJMP_REG for indirect jump. (compute_init_costs): Detect the need of intermediate register and constant pool. --------------040003030607050705090805 Content-Type: text/x-patch; name="PR33642_0313.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="PR33642_0313.patch" Content-length: 9354 Index: gcc/rtl-factoring.c =================================================================== --- gcc/rtl-factoring.c (revision 133102) +++ gcc/rtl-factoring.c (working copy) @@ -37,6 +37,8 @@ #include "output.h" #include "df.h" #include "addresses.h" +#include "insn-attr.h" +#include "recog.h" /* Sequence abstraction: @@ -202,6 +204,9 @@ /* The register used to hold the return address during the pseudo-call. */ rtx link_reg; + + /* The register for indirect jump. */ + rtx ijmp_reg; /* The sequences matching this pattern. */ matching_seq matching_seqs; @@ -271,6 +276,12 @@ /* Cost of returning. */ static int seq_return_cost; +/* Register class for indirect jump. */ +static enum reg_class ijmp_class; + +/* Use constant pool to store generated symbol references. */ +static int use_const_pool = 0; + /* Returns the first insn preceding INSN for which INSN_P is true and belongs to the same basic block. Returns NULL_RTX if no such insn can be found. */ @@ -308,9 +319,59 @@ return hash; } -/* Compute the cost of INSN rtx for abstraction. */ +/* Returns default length of INSN or its PATTERN if INSN isn't recognized. */ +static inline int +get_default_length (rtx insn) +{ + rtx body = PATTERN (insn); + if (recog_memoized (insn) >= 0) + return insn_default_length (insn); + else if (recog_memoized (body) >= 0) + return insn_default_length (body); + else + return 0; +} + +/* Compute the length of INSN. */ + static int +compute_rtx_length (rtx insn) +{ + rtx body; + int i; + int length = 0; + + switch (GET_CODE (insn)) + { + case CALL_INSN: + length = get_default_length (insn); + break; + + case JUMP_INSN: + length = get_default_length (insn); + break; + + case INSN: + body = PATTERN (insn); + if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER) + return 0; + else if (GET_CODE (body) == SEQUENCE) + for (i = 0; i < XVECLEN (body, 0); i++) + length += compute_rtx_length (XVECEXP (body, 0, i)); + else + length = get_default_length (insn); + break; + + default: + break; + } + return length; +} + +/* Compute and cache the cost of INSN rtx. */ + +static int compute_rtx_cost (rtx insn) { struct hash_bucket_def tmp_bucket; @@ -340,7 +401,7 @@ /* If we can't parse the INSN cost will be the instruction length. */ if (cost == -1) { - cost = get_attr_length (insn); + cost = compute_rtx_length (insn); /* Cache the length. */ if (elem) @@ -349,7 +410,7 @@ /* If we can't get an accurate estimate for a complex instruction, assume that it has the same cost as a single fast instruction. */ - return cost != 0 ? cost : COSTS_N_INSNS (1); + return cost > 0 ? cost : COSTS_N_INSNS (1); } /* Determines the number of common insns in the sequences ending in INSN1 and @@ -405,6 +466,7 @@ pseq->abstracted_length = 0; pseq->cost = 0; pseq->link_reg = NULL_RTX; + pseq->ijmp_reg = NULL_RTX; pseq->matching_seqs = NULL; pseq->next_pattern_seq = pattern_seqs; pattern_seqs = pseq; @@ -594,6 +656,7 @@ /* Initialize data. */ SET_HARD_REG_SET (linkregs); pseq->link_reg = NULL_RTX; + pseq->ijmp_reg = NULL_RTX; pseq->abstracted_length = 0; pseq->gain = -(seq_call_cost - seq_jump_cost + seq_return_cost); @@ -697,7 +760,7 @@ #else || (!ok_for_base_p_1 (i, Pmode, MEM, SCRATCH)) || (!reg_class_subset_p (REGNO_REG_CLASS (i), - base_reg_class (VOIDmode, MEM, SCRATCH))) + base_reg_class (VOIDmode, MEM, SCRATCH))) #endif || (hascall && call_used_regs[i]) || (!call_used_regs[i] && !df_regs_ever_live_p (i))) @@ -714,7 +777,28 @@ /* Abstraction is not possible if no link register is available, so set gain to 0. */ if (!pseq->link_reg) - pseq->gain = 0; + { + pseq->gain = 0; + return; + } + + if (reg_class_subset_p (REGNO_REG_CLASS (i), ijmp_class)) + return; + + /* Find a register for indirect jump. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (reg_class_subset_p (REGNO_REG_CLASS (i), ijmp_class) + && (!hascall || !call_used_regs[i]) + && (call_used_regs[i] || df_regs_ever_live_p (i))) + { + pseq->ijmp_reg = gen_rtx_REG (Pmode, i); + break; + } + if (!pseq->ijmp_reg) + { + pseq->gain = 0; + return; + } } /* Deallocates memory occupied by PSEQ and its matching seqs. */ @@ -938,7 +1022,7 @@ /* Builds a symbol_ref for LABEL. */ static rtx -gen_symbol_ref_rtx_for_label (const_rtx label) +gen_symbol_ref_rtx_for_label (rtx label) { char name[20]; rtx sym; @@ -946,6 +1030,10 @@ ASM_GENERATE_INTERNAL_LABEL (name, "L", CODE_LABEL_NUMBER (label)); sym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_LOCAL; + if (use_const_pool) { + LABEL_PRESERVE_P (label) = 1; + return force_const_mem (Pmode, sym); + } return sym; } @@ -1004,7 +1092,7 @@ { rtx insn; basic_block bb; - rtx retlabel, retjmp, saveinsn; + rtx retlabel, saveinsn; int i; seq_block sb; @@ -1020,8 +1108,19 @@ /* Emit an indirect jump via the link register after the sequence acting as the return insn. Also emit a barrier and update the basic block. */ if (!find_reg_note (BB_END (bb), REG_NORETURN, NULL)) - retjmp = emit_jump_insn_after (gen_indirect_jump (pattern_seqs->link_reg), - BB_END (bb)); + { + if (!reg_class_subset_p (REGNO_REG_CLASS (REGNO (pattern_seqs->link_reg)), + ijmp_class)) + { + emit_insn_after (gen_move_insn (pattern_seqs->ijmp_reg, + pattern_seqs->link_reg), BB_END (bb)); + emit_jump_insn_after (gen_indirect_jump (pattern_seqs->ijmp_reg), + BB_END (bb)); + } + else + emit_jump_insn_after (gen_indirect_jump (pattern_seqs->link_reg), + BB_END (bb)); + } emit_barrier_after (BB_END (bb)); /* Replace all outgoing edges with a new one to the block of RETLABEL. */ @@ -1335,32 +1434,91 @@ static void compute_init_costs (void) { - rtx rtx_jump, rtx_store, rtx_return, reg, label; + rtx rtx_jump, rtx_store, rtx_return, reg, jmp_reg, label, tmp; basic_block bb; + int i, regno, jmpno; FOR_EACH_BB (bb) if (BB_HEAD (bb)) break; label = block_label (bb); - reg = gen_rtx_REG (Pmode, 0); + regno = 0; + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (regno_ok_for_base_p (i, Pmode, MEM, SCRATCH)) + { + regno = i; + break; + } + reg = gen_rtx_REG (Pmode, regno); + /* Pattern for indirect jump. */ rtx_jump = gen_indirect_jump (reg); - /* Pattern for storing address. */ - rtx_store = gen_rtx_SET (VOIDmode, reg, gen_symbol_ref_rtx_for_label (label)); + /* The cost of jump. */ + if (GET_CODE (rtx_jump) == JUMP_INSN) + tmp = rtx_jump; + else + tmp = make_jump_insn_raw (rtx_jump); + seq_jump_cost = compute_rtx_cost (tmp); - /* Pattern for return insn. */ - rtx_return = gen_jump (label); + /* Determine the register class for indirect jump. */ + extract_insn (tmp); + preprocess_constraints (); + ijmp_class = NO_REGS; + if (recog_data.n_operands == 1) + { + char c; + const char *p = recog_data.constraints[0]; + for (;(c = *p) != '\0';) + { + if (c == 'r' || c == 'g') + ijmp_class = GENERAL_REGS; + else + ijmp_class = REG_CLASS_FROM_CONSTRAINT (c, p); + + if (ijmp_class != NO_REGS) + break; + p += CONSTRAINT_LEN (c, p); + } + } - /* The cost of jump. */ - seq_jump_cost = compute_rtx_cost (make_jump_insn_raw (rtx_jump)); + jmpno = 0; + jmp_reg = NULL_RTX; + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (reg_class_subset_p (REGNO_REG_CLASS (i), ijmp_class)) + { + jmp_reg = gen_rtx_REG (Pmode, i); + jmpno = i; + break; + } + if (REGNO_REG_CLASS (regno) != REGNO_REG_CLASS (jmpno)) + seq_jump_cost += compute_rtx_cost (gen_move_insn (jmp_reg, reg)); + + /* Pattern for storing address. */ + rtx_store = gen_move_insn (reg, gen_symbol_ref_rtx_for_label (label)); + for (tmp = rtx_store; tmp; tmp = NEXT_INSN(tmp)) + if (recog_memoized(tmp) < 0 && GET_CODE (PATTERN (tmp)) != USE) + { + use_const_pool = 1; + break; + } + /* Try to use constant pool for symbol reference. */ + if (use_const_pool) + { + rtx_store = gen_move_insn (reg, gen_symbol_ref_rtx_for_label (label)); + for (tmp = rtx_store; tmp; tmp = NEXT_INSN(tmp)) + gcc_assert (recog_memoized(tmp) >= 0); + } + /* The cost of calling sequence. */ - seq_call_cost = seq_jump_cost + compute_rtx_cost (make_insn_raw (rtx_store)); + seq_call_cost = seq_jump_cost + compute_rtx_cost (rtx_store) + + COSTS_N_INSNS (use_const_pool); /* The cost of return. */ + rtx_return = gen_jump (label); seq_return_cost = compute_rtx_cost (make_jump_insn_raw (rtx_return)); /* Simple heuristic for minimal sequence cost. */ --------------040003030607050705090805--