From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by sourceware.org (Postfix) with ESMTPS id EE8613858CDA for ; Thu, 30 Mar 2023 12:01:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EE8613858CDA Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linux.ibm.com Received: from pps.filterd (m0098419.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 32UBcJRh017764; Thu, 30 Mar 2023 12:01:37 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=message-id : date : mime-version : subject : to : references : cc : from : in-reply-to : content-type : content-transfer-encoding; s=pp1; bh=aC050zqQFb77kJ55/ZHTUafjbg9GyyyOlGOPk84TveM=; b=T0ZykkX+hBMvmdH+fsIKsungLkVAIcAahDnNmGVywufIl4gsSTkIuwDBDgSQNXrFzFRq G/rk936XD4MkDDqeDChh8DNuq0IMhZFAVv3fIlbh6lLP9TmDnpGqXt8dIkZN4DgnvNoy nzqKTYzZqmFE+C+5p+JR0O7zZjCA0a1Mu1ayLWMYINcj5d62+8dviN5A6my/DiKVralv BzcFsCuSpj8E+xEIVfwC6lefNzRi9k4mxClR8RXaH7UJbyI8mMLFQg/tdyvpwjTMiUgE 4bEk493l+T8CUqHtJ9q/YG3lRz1wSAJ280nndbhfYzMEvFZjCxiHfNJRa7eGPwLiC3Ff Zw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com (PPS) with ESMTPS id 3pmpr8csyt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 30 Mar 2023 12:01:36 +0000 Received: from m0098419.ppops.net (m0098419.ppops.net [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 32UBgFEe003168; Thu, 30 Mar 2023 12:01:13 GMT Received: from ppma04wdc.us.ibm.com (1a.90.2fa9.ip4.static.sl-reverse.com [169.47.144.26]) by mx0b-001b2d01.pphosted.com (PPS) with ESMTPS id 3pmpr8cske-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 30 Mar 2023 12:01:12 +0000 Received: from pps.filterd (ppma04wdc.us.ibm.com [127.0.0.1]) by ppma04wdc.us.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 32UAR7aE005821; Thu, 30 Mar 2023 12:00:49 GMT Received: from smtprelay02.dal12v.mail.ibm.com ([9.208.130.97]) by ppma04wdc.us.ibm.com (PPS) with ESMTPS id 3phrk7bph9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 30 Mar 2023 12:00:49 +0000 Received: from smtpav05.dal12v.mail.ibm.com (smtpav05.dal12v.mail.ibm.com [10.241.53.104]) by smtprelay02.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 32UC0mV346006784 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 30 Mar 2023 12:00:48 GMT Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C123858067; Thu, 30 Mar 2023 12:00:48 +0000 (GMT) Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1D9255805D; Thu, 30 Mar 2023 12:00:46 +0000 (GMT) Received: from [9.43.98.51] (unknown [9.43.98.51]) by smtpav05.dal12v.mail.ibm.com (Postfix) with ESMTP; Thu, 30 Mar 2023 12:00:45 +0000 (GMT) Message-ID: <05b5dcba-9343-0b6c-44a7-d4a6d128e7aa@linux.ibm.com> Date: Thu, 30 Mar 2023 17:30:43 +0530 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.9.0 Subject: Re: [PATCH v2] rtl-optimization: ppc backend generates unnecessary extension. To: gcc-patches@gcc.gnu.org References: Content-Language: en-US Cc: Segher Boessenkool , Peter Bergner , Richard Biener , Jeff Law From: Ajit Agarwal In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: kPCgl1zuQQpvhvSPR7NjmRsgn4cdHPvJ X-Proofpoint-GUID: V6AnLVnq1f6oq0gepoFjUc7t6Kvj-lTI X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.942,Hydra:6.0.573,FMLib:17.11.170.22 definitions=2023-03-30_04,2023-03-30_01,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 impostorscore=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 adultscore=0 suspectscore=0 phishscore=0 priorityscore=1501 clxscore=1015 mlxlogscore=999 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2303200000 definitions=main-2303300095 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,GIT_PATCH_0,NICE_REPLY_A,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Hello All: This patch added enhancement to extimination elimination for rs6000 target. Bootstrapped and regtested on powerpc64-linux-gnu. Thanks & Regards Ajit rtl-optimization: ppc backend generates unnecessary extension. Eliminate unnecessary redundant zero extension within basic blocks. 2023-03-30 Ajit Kumar Agarwal gcc/ChangeLog: * ree.cc(is_feasible_elim_across_basic_blocks): Add checks to enable extension elimination.. * ree.cc(combine_reaching_defs): Add checks to enable extension elimination. --- gcc/ree.cc | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 116 insertions(+), 5 deletions(-) diff --git a/gcc/ree.cc b/gcc/ree.cc index d05d37f9a23..7e4cce5cee4 100644 --- a/gcc/ree.cc +++ b/gcc/ree.cc @@ -253,6 +253,56 @@ struct ext_cand static int max_insn_uid; +/* Get all the reaching definitions of an instruction. The definitions are + desired for REG used in INSN. Return the definition list or NULL if a + definition is missing. If DEST is non-NULL, additionally push the INSN + of the definitions onto DEST. */ + +static struct df_link * +get_defs (rtx_insn *insn, rtx reg, vec *dest) +{ + df_ref use; + struct df_link *ref_chain, *ref_link; + + FOR_EACH_INSN_USE (use, insn) + { + if (GET_CODE (DF_REF_REG (use)) == SUBREG) + return NULL; + if (REGNO (DF_REF_REG (use)) == REGNO (reg)) + break; + } + + if (use == NULL) return NULL; + + gcc_assert (use != NULL); + + ref_chain = DF_REF_CHAIN (use); + + for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) + { + /* Problem getting some definition for this instruction. */ + if (ref_link->ref == NULL) + return NULL; + if (DF_REF_INSN_INFO (ref_link->ref) == NULL) + return NULL; + /* As global regs are assumed to be defined at each function call + dataflow can report a call_insn as being a definition of REG. + But we can't do anything with that in this pass so proceed only + if the instruction really sets REG in a way that can be deduced + from the RTL structure. */ + if (global_regs[REGNO (reg)] + && !set_of (reg, DF_REF_INSN (ref_link->ref))) + return NULL; + } + + if (dest) + for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) + dest->safe_push (DF_REF_INSN (ref_link->ref)); + + return ref_chain; +} + + /* Identify instruction AND with identical zero extension. */ static unsigned int @@ -393,6 +443,7 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set) machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_set = NULL_RTX; rtx cand_pat = single_set (cand->insn); + if (insn_is_zext_p(cand->insn) && CONST_INT_P (orig_src) && INTVAL (orig_src) != 0) return false; @@ -401,6 +452,7 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set) then we need to change the original load to reference the destination of the extension. Then we need to emit a copy from that destination to the original destination of the load. */ + // print_rtl_single(stdout, cand_pat); rtx new_reg; bool copy_needed = (REGNO (SET_DEST (cand_pat)) != REGNO (XEXP (SET_SRC (cand_pat), 0))); @@ -547,6 +599,7 @@ transform_ifelse (ext_cand *cand, rtx_insn *def_insn) return false; } +#if 0 /* Get all the reaching definitions of an instruction. The definitions are desired for REG used in INSN. Return the definition list or NULL if a definition is missing. If DEST is non-NULL, additionally push the INSN @@ -593,7 +646,7 @@ get_defs (rtx_insn *insn, rtx reg, vec *dest) return ref_chain; } - +#endif /* Get all the reaching uses of an instruction. The uses are desired for REG set in INSN. Return use list or NULL if a use is missing or irregular. */ @@ -848,6 +901,36 @@ is_feasible_elim_across_basic_blocks (ext_cand *cand, && REGNO (XEXP (PATTERN (BB_END (bb)), 0)) != REGNO (SET_DEST (cand->expr))) return false; + if (cand->code == ZERO_EXTEND + && GET_CODE ((PATTERN (def_insn))) == PARALLEL) + return false; + + if (cand->code == ZERO_EXTEND + && GET_CODE ((PATTERN (def_insn))) == SET + && GET_CODE (SET_SRC (PATTERN (def_insn))) != XOR) + return false; + + if (cand->code == ZERO_EXTEND + && GET_CODE ((PATTERN (def_insn))) == SET + && GET_CODE (SET_SRC (PATTERN (def_insn))) == XOR) + { + vec *dest = XCNEWVEC (vec, 4); + if (!get_defs (def_insn, XEXP (SET_SRC (PATTERN(def_insn)), 0), dest)) + return false; + + int i; + rtx_insn *def_insn; + + FOR_EACH_VEC_ELT (*dest, i, def_insn) + { + if ((GET_CODE (PATTERN (def_insn)) == SET + && GET_CODE (SET_SRC (PATTERN (def_insn))) == ASHIFT) + || GET_CODE (PATTERN (def_insn)) == PARALLEL) + return false; + } + XDELETEVEC (dest); + } + return true; } @@ -873,7 +956,8 @@ merge_def_and_ext (ext_cand *cand, rtx_insn *def_insn, ext_state *state) if (!feasible) return false; - if (((!copy_needed && (insn_is_zext_p (cand->insn)) + if (((!copy_needed && (insn_is_zext_p (cand->insn) + || (cand->code == ZERO_EXTEND && ext_src_mode == QImode)) && (GET_MODE (SET_DEST (*sub_rtx)) != ext_src_mode && state->modified[INSN_UID (def_insn)].kind == EXT_MODIFIED_NONE)) || ((state->modified[INSN_UID (def_insn)].kind @@ -1211,15 +1295,22 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) definitions could be merged. */ if (apply_change_group ()) { - if (dump_file) - fprintf (dump_file, "All merges were successful.\n"); + if (state->modified_list.length() == 0) return false; + + if (cand->code == ZERO_EXTEND + && GET_CODE (PATTERN (state->modified_list[0])) == SET + && GET_CODE (SET_SRC (PATTERN (state->modified_list[0]))) != XOR) + return false; + + if (dump_file) + fprintf (dump_file, "All merges were successful.\n"); FOR_EACH_VEC_ELT (state->modified_list, i, def_insn) { ext_modified *modified = &state->modified[INSN_UID (def_insn)]; if (modified->kind == EXT_MODIFIED_NONE) modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT - : EXT_MODIFIED_SEXT); + : EXT_MODIFIED_SEXT); if (copy_needed) modified->do_not_reextend = 1; @@ -1228,6 +1319,26 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) } else { + if (state->modified_list.length() == 0) return false; + + if (cand->code == ZERO_EXTEND + && GET_CODE (PATTERN(state->modified_list[0])) == SET + && GET_CODE (SET_SRC (PATTERN (state->modified_list[0]))) != XOR) + return false; + + if (cand->code == ZERO_EXTEND) + { + FOR_EACH_VEC_ELT (state->modified_list, i, def_insn) + { + ext_modified *modified = &state->modified[INSN_UID (def_insn)]; + if (modified->kind == EXT_MODIFIED_NONE) + modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT + : EXT_MODIFIED_SEXT); + + modified->do_not_reextend = 1; + } + return true; + } /* Changes need not be cancelled explicitly as apply_change_group does it. Print list of definitions in the dump_file for debug purposes. This extension cannot be deleted. */ -- 2.31.1 On 28/03/23 10:19 pm, Ajit Agarwal via Gcc-patches wrote: > Hello All: > > This patch makes REE pass as a default pass in rs6000 target. And > add necessary subroutines to eliminate extensions across basic blocks. > > Bootstrapped and regtested on powerpc64-linu-gnu. > > Thanks & Regards > Ajit > > > rtl-optimization: ppc backend generates unnecessary > extension. > > Eliminate unnecessary redundant zero extension across basic > blocks. > > 2023-03-28 Ajit Kumar Agarwal > > gcc/ChangeLog: > > * ree.cc(insn_s_zext_p): New function. > * ree.cc(is_feasible_elim_across_basic_blocks): > New function. > * ree.cc(merge_def_and_ext): Add call to > is_feasible_elim_across_basic_blocks to check feasibility > of extension elimination across basic blocks. > * common/config/rs6000/rs6000-common.cc: Add free pass > as default pass in rs6000 target. > --- > gcc/common/config/rs6000/rs6000-common.cc | 3 +- > gcc/ree.cc | 269 +++++++++++++++++----- > 2 files changed, 209 insertions(+), 63 deletions(-) > > diff --git a/gcc/common/config/rs6000/rs6000-common.cc b/gcc/common/config/rs6000/rs6000-common.cc > index 2140c442ba9..e7780dc0c5d 100644 > --- a/gcc/common/config/rs6000/rs6000-common.cc > +++ b/gcc/common/config/rs6000/rs6000-common.cc > @@ -30,6 +30,8 @@ > /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ > static const struct default_options rs6000_option_optimization_table[] = > { > + /* Enable -free for zero extension and sign extension elimination.*/ > + { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 }, > /* Split multi-word types early. */ > { OPT_LEVELS_ALL, OPT_fsplit_wide_types_early, NULL, 1 }, > /* Enable -fsched-pressure for first pass instruction scheduling. */ > @@ -42,7 +44,6 @@ static const struct default_options rs6000_option_optimization_table[] = > /* -frename-registers leads to non-optimal codegen and performance > on rs6000, turn it off by default. */ > { OPT_LEVELS_ALL, OPT_frename_registers, NULL, 0 }, > - > /* Double growth factor to counter reduced min jump length. */ > { OPT_LEVELS_ALL, OPT__param_max_grow_copy_bb_insns_, NULL, 16 }, > { OPT_LEVELS_NONE, 0, NULL, 0 } > diff --git a/gcc/ree.cc b/gcc/ree.cc > index 63d8cf9f237..d05d37f9a23 100644 > --- a/gcc/ree.cc > +++ b/gcc/ree.cc > @@ -253,6 +253,53 @@ struct ext_cand > > static int max_insn_uid; > > +/* Identify instruction AND with identical zero extension. */ > + > +static unsigned int > +insn_is_zext_p(rtx insn) > +{ > + if (GET_CODE (insn) == AND) > + { > + rtx set = XEXP (insn, 0); > + if (REG_P(set)) > + { > + if (CONST_INT_P (XEXP (insn, 1)) > + && INTVAL (XEXP (insn, 1)) == 1) > + return 1; > + } > + else > + return 0; > + } > + > + return 0; > +} > + > +/* Identify instruction AND with identical zero extension. */ > + > +static unsigned int > +insn_is_zext_p(rtx_insn * insn) > +{ > + rtx body = PATTERN (insn); > + > + if (GET_CODE (body) == PARALLEL) return 0; > + > + if (GET_CODE(body) == SET && GET_CODE (SET_SRC (body)) == AND) > + { > + rtx set = XEXP (SET_SRC(body), 0); > + > + if (REG_P(set) && GET_MODE(SET_DEST(body)) > + == GET_MODE(set)) > + { > + if (CONST_INT_P (XEXP (SET_SRC (body), 1)) > + && INTVAL (XEXP (SET_SRC (body), 1)) == 1) > + return 1; > + } > + else > + return 0; > + } > + return 0; > +} > + > /* Update or remove REG_EQUAL or REG_EQUIV notes for INSN. */ > > static bool > @@ -297,6 +344,31 @@ update_reg_equal_equiv_notes (rtx_insn *insn, machine_mode new_mode, > return true; > } > > +/* Return true if INSN is > + (SET (reg REGNO (def_reg)) (if_then_else (cond) (REG x1) (REG x2))) > + and store x1 and x2 in REG_1 and REG_2. */ > + > +static bool > +is_cond_copy_insn (rtx_insn *insn, rtx *reg1, rtx *reg2) > +{ > + rtx expr = single_set (insn); > + > + if (expr != NULL_RTX > + && GET_CODE (expr) == SET > + && GET_CODE (SET_DEST (expr)) == REG > + && GET_CODE (SET_SRC (expr)) == IF_THEN_ELSE > + && GET_CODE (XEXP (SET_SRC (expr), 1)) == REG > + && GET_CODE (XEXP (SET_SRC (expr), 2)) == REG) > + { > + *reg1 = XEXP (SET_SRC (expr), 1); > + *reg2 = XEXP (SET_SRC (expr), 2); > + return true; > + } > + > + return false; > +} > + > + > /* Given a insn (CURR_INSN), an extension candidate for removal (CAND) > and a pointer to the SET rtx (ORIG_SET) that needs to be modified, > this code modifies the SET rtx to a new SET rtx that extends the > @@ -321,6 +393,9 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set) > machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set)); > rtx new_set = NULL_RTX; > rtx cand_pat = single_set (cand->insn); > + if (insn_is_zext_p(cand->insn) > + && CONST_INT_P (orig_src) && INTVAL (orig_src) != 0) > + return false; > > /* If the extension's source/destination registers are not the same > then we need to change the original load to reference the destination > @@ -359,8 +434,14 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set) > else if (GET_CODE (orig_src) == cand->code) > { > /* Here is a sequence of two extensions. Try to merge them. */ > - rtx temp_extension > - = gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0)); > + rtx temp_extension = NULL_RTX; > + if (GET_CODE (SET_SRC (cand_pat)) == AND) > + temp_extension > + = gen_rtx_fmt_ee (cand->code, cand->mode, XEXP (orig_src, 0), > + XEXP (orig_src, 1)); > + else > + temp_extension > + = gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0)); > rtx simplified_temp_extension = simplify_rtx (temp_extension); > if (simplified_temp_extension) > temp_extension = simplified_temp_extension; > @@ -370,8 +451,9 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set) > else if (GET_CODE (orig_src) == IF_THEN_ELSE) > { > /* Only IF_THEN_ELSE of phi-type copies are combined. Otherwise, > - in general, IF_THEN_ELSE should not be combined. */ > - return true; > + in general, IF_THEN_ELSE should not be combined. Relaxed > + cases with IF_THEN_ELSE across basic blocls */ > + return true; > } > else > { > @@ -541,30 +623,6 @@ get_uses (rtx_insn *insn, rtx reg) > return ref_chain; > } > > -/* Return true if INSN is > - (SET (reg REGNO (def_reg)) (if_then_else (cond) (REG x1) (REG x2))) > - and store x1 and x2 in REG_1 and REG_2. */ > - > -static bool > -is_cond_copy_insn (rtx_insn *insn, rtx *reg1, rtx *reg2) > -{ > - rtx expr = single_set (insn); > - > - if (expr != NULL_RTX > - && GET_CODE (expr) == SET > - && GET_CODE (SET_DEST (expr)) == REG > - && GET_CODE (SET_SRC (expr)) == IF_THEN_ELSE > - && GET_CODE (XEXP (SET_SRC (expr), 1)) == REG > - && GET_CODE (XEXP (SET_SRC (expr), 2)) == REG) > - { > - *reg1 = XEXP (SET_SRC (expr), 1); > - *reg2 = XEXP (SET_SRC (expr), 2); > - return true; > - } > - > - return false; > -} > - > enum ext_modified_kind > { > /* The insn hasn't been modified by ree pass yet. */ > @@ -709,6 +767,90 @@ get_sub_rtx (rtx_insn *def_insn) > return sub_rtx; > } > > +/* Find feasibility of extension elimination > + across basic blocks. */ > + > +static bool > +is_feasible_elim_across_basic_blocks (ext_cand *cand, > + rtx_insn *def_insn) > +{ > + basic_block bb = BLOCK_FOR_INSN (cand->insn); > + edge fallthru_edge; > + edge e; > + edge_iterator ei; > + > + FOR_EACH_EDGE (e, ei, bb->preds) > + { > + rtx_insn *insn = BB_END (e->src) ? PREV_INSN (BB_END (e->src)) : NULL; > + > + if (insn && NONDEBUG_INSN_P (insn) > + && GET_CODE (PATTERN (insn)) == SET && SET_SRC (PATTERN(insn)) > + && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE) > + { > + if (e->dest == bb) > + { > + basic_block jump_block = e->dest; > + if (jump_block == bb) > + { > + if (single_succ_p (BLOCK_FOR_INSN (def_insn))) > + { > + fallthru_edge = single_succ_edge (BLOCK_FOR_INSN (def_insn)); > + if (BB_END (fallthru_edge->dest) && (bb != fallthru_edge->dest > + || e->dest != fallthru_edge->dest)) > + return false; > + } > + else > + return false; > + } > + else return false; > + } > + else > + { > + if (single_succ_p (e->dest)) > + { > + fallthru_edge = single_succ_edge (e->dest); > + if (BB_END (fallthru_edge->dest) && bb != fallthru_edge->dest) > + return false; > + } > + } > + } > + } > + if (single_succ_p (BLOCK_FOR_INSN (def_insn))) > + { > + fallthru_edge = single_succ_edge (BLOCK_FOR_INSN (def_insn)); > + if (BB_END (fallthru_edge->dest) && bb != fallthru_edge->dest) > + return false; > + } > + else > + return false; > + > + rtx set = single_set(cand->insn); > + /* The destination register of the extension insn must not be > + used or set between the def_insn and cand->insn exclusive. */ > + if (INSN_CHAIN_CODE_P (GET_CODE (def_insn)) > + && INSN_CHAIN_CODE_P (cand->code)) > + if ((cand->code == ZERO_EXTEND) > + && REG_P (SET_DEST (set)) && NEXT_INSN (def_insn) > + && (reg_used_between_p (SET_DEST (set), def_insn, cand->insn) > + || reg_set_between_p (SET_DEST (set), def_insn, cand->insn))) > + return false; > + > + if (cand->code == ZERO_EXTEND && (bb != BLOCK_FOR_INSN (def_insn) > + || DF_INSN_LUID (def_insn) > DF_INSN_LUID (cand->insn))) > + return false; > + > + if (insn_is_zext_p (cand->insn) > + && GET_CODE (PATTERN (BB_END (bb))) != USE) > + return false; > + > + if (insn_is_zext_p (cand->insn) > + && GET_CODE (PATTERN (BB_END (bb))) == USE > + && REGNO (XEXP (PATTERN (BB_END (bb)), 0)) != REGNO (SET_DEST (cand->expr))) > + return false; > + > + return true; > +} > + > /* Merge the DEF_INSN with an extension. Calls combine_set_extension > on the SET pattern. */ > > @@ -727,12 +869,18 @@ merge_def_and_ext (ext_cand *cand, rtx_insn *def_insn, ext_state *state) > bool copy_needed > = (REGNO (SET_DEST (cand->expr)) != REGNO (XEXP (SET_SRC (cand->expr), 0))); > > - if (!copy_needed || (GET_MODE (SET_DEST (*sub_rtx)) == ext_src_mode > - || ((state->modified[INSN_UID (def_insn)].kind > - == (cand->code == ZERO_EXTEND || cand->code == AND > + bool feasible = is_feasible_elim_across_basic_blocks (cand, def_insn); > + > + if (!feasible) return false; > + > + if (((!copy_needed && (insn_is_zext_p (cand->insn)) > + && (GET_MODE (SET_DEST (*sub_rtx)) != ext_src_mode > + && state->modified[INSN_UID (def_insn)].kind == EXT_MODIFIED_NONE)) > + || ((state->modified[INSN_UID (def_insn)].kind > + == (cand->code == ZERO_EXTEND > ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT)) > - && state->modified[INSN_UID (def_insn)].mode > - == ext_src_mode))) > + && state->modified[INSN_UID (def_insn)].mode > + == ext_src_mode))) > { > if (GET_MODE_UNIT_SIZE (GET_MODE (SET_DEST (*sub_rtx))) > >= GET_MODE_UNIT_SIZE (cand->mode)) > @@ -759,7 +907,7 @@ static inline rtx > get_extended_src_reg (rtx src) > { > while (GET_CODE (src) == SIGN_EXTEND || GET_CODE (src) == ZERO_EXTEND > - || GET_CODE (src) == AND) > + || insn_is_zext_p(src)) > src = XEXP (src, 0); > gcc_assert (REG_P (src)); > return src; > @@ -1008,7 +1156,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) > machine_mode mode; > > if (state->modified[INSN_UID (cand->insn)].kind > - != (cand->code == ZERO_EXTEND || cand->code == AND > + != (cand->code == ZERO_EXTEND > ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT) > || state->modified[INSN_UID (cand->insn)].mode != cand->mode > || (set == NULL_RTX)) > @@ -1019,7 +1167,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) > cand->mode = mode; > } > > - merge_successful = true; > + merge_successful = false; > > /* Go through the defs vector and try to merge all the definitions > in this vector. */ > @@ -1027,7 +1175,10 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) > FOR_EACH_VEC_ELT (state->defs_list, defs_ix, def_insn) > { > if (merge_def_and_ext (cand, def_insn, state)) > - state->modified_list.safe_push (def_insn); > + { > + merge_successful = true; > + state->modified_list.safe_push (def_insn); > + } > else > { > merge_successful = false; > @@ -1058,14 +1209,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) > cannot be merged, we entirely give up. In the future, we should allow > extensions to be partially eliminated along those paths where the > definitions could be merged. */ > - int num_clobbers = 0; > - int icode = recog (cand->insn, cand->insn, > - (GET_CODE (cand->expr) == SET > - && ! reload_completed > - && ! reload_in_progress) > - ? &num_clobbers : 0); > - > - if (apply_change_group () || (icode < 0)) > + if (apply_change_group ()) > { > if (dump_file) > fprintf (dump_file, "All merges were successful.\n"); > @@ -1074,7 +1218,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) > { > ext_modified *modified = &state->modified[INSN_UID (def_insn)]; > if (modified->kind == EXT_MODIFIED_NONE) > - modified->kind = (cand->code == ZERO_EXTEND || cand->code == AND ? EXT_MODIFIED_ZEXT > + modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT > : EXT_MODIFIED_SEXT); > > if (copy_needed) > @@ -1082,19 +1226,19 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) > } > return true; > } > - else > - { > - /* Changes need not be cancelled explicitly as apply_change_group > - does it. Print list of definitions in the dump_file for debug > - purposes. This extension cannot be deleted. */ > - if (dump_file) > - { > - fprintf (dump_file, > - "Merge cancelled, non-mergeable definitions:\n"); > - FOR_EACH_VEC_ELT (state->modified_list, i, def_insn) > - print_rtl_single (dump_file, def_insn); > - } > - } > + else > + { > + /* Changes need not be cancelled explicitly as apply_change_group > + does it. Print list of definitions in the dump_file for debug > + purposes. This extension cannot be deleted. */ > + if (dump_file) > + { > + fprintf (dump_file, > + "Merge cancelled, non-mergeable definitions:\n"); > + FOR_EACH_VEC_ELT (state->modified_list, i, def_insn) > + print_rtl_single (dump_file, def_insn); > + } > + } > } > else > { > @@ -1128,7 +1272,7 @@ add_removable_extension (const_rtx expr, rtx_insn *insn, > mode = GET_MODE (dest); > > if (REG_P (dest) > - && (code == SIGN_EXTEND || code == ZERO_EXTEND || code == AND) > + && (code == SIGN_EXTEND || code == ZERO_EXTEND || insn_is_zext_p(src)) > && REG_P (XEXP (src, 0))) > { > rtx reg = XEXP (src, 0); > @@ -1140,7 +1284,7 @@ add_removable_extension (const_rtx expr, rtx_insn *insn, > a path from the entry to this zero-extension that leaves this register > uninitialized, removing the extension could change the behavior of > correct programs. So first, check it is not the case. */ > - if (code == ZERO_EXTEND && !bitmap_bit_p (init_regs, REGNO (reg))) > + if ((code == ZERO_EXTEND && !bitmap_bit_p (init_regs, REGNO (reg)))) > { > if (dump_file) > { > @@ -1390,9 +1534,10 @@ find_and_remove_re (void) > reinsn_list.release (); > XDELETEVEC (state.modified); > > - if (dump_file && num_re_opportunities > 0) > + if (dump_file && num_re_opportunities > 0) > fprintf (dump_file, "Elimination opportunities = %d realized = %d\n", > num_re_opportunities, num_realized); > + > } > > /* Find and remove redundant extensions. */