Hello All: This is patch-4 to improve ree pass for rs6000 target. Use ABI interfaces support.
Bootstrapped and regtested on powerpc64-linux-gnu. Thanks & Regards Ajit ree: Improve ree pass for rs6000 target. For rs6000 target we see redundant zero and sign extension and done to improve ree pass to eliminate such redundant zero and sign extension. Support of ABI interfaces. 2023-04-19 Ajit Kumar Agarwal <aagar...@linux.ibm.com> gcc/ChangeLog: * ree.cc (combline_reaching_defs): Add zero_extend and sign_extend. Add FUNCTION_ARG_REGNO_P abi interfaces calls and FUNCTION_VALUE_REGNO_P support. (add_removable_extension): Add FUNCTION_ARG_REGNO_P abi interface calls. gcc/testsuite/ChangeLog: * g++.target/powerpc/zext-elim-3.C --- gcc/ree.cc | 127 +++++++++++++----- .../g++.target/powerpc/zext-elim-3.C | 16 +++ 2 files changed, 113 insertions(+), 30 deletions(-) create mode 100644 gcc/testsuite/g++.target/powerpc/zext-elim-3.C diff --git a/gcc/ree.cc b/gcc/ree.cc index 413aec7c8eb..33c803f16ce 100644 --- a/gcc/ree.cc +++ b/gcc/ree.cc @@ -473,7 +473,8 @@ get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest) break; } - gcc_assert (use != NULL); + if (use == NULL) + return NULL; ref_chain = DF_REF_CHAIN (use); @@ -514,7 +515,8 @@ get_uses (rtx_insn *insn, rtx reg) if (REGNO (DF_REF_REG (def)) == REGNO (reg)) break; - gcc_assert (def != NULL); + if (def == NULL) + return NULL; ref_chain = DF_REF_CHAIN (def); @@ -771,6 +773,58 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) state->defs_list.truncate (0); state->copies_list.truncate (0); + if (cand->code == ZERO_EXTEND) + { + rtx orig_src = XEXP (SET_SRC (cand->expr),0); + rtx set = single_set (cand->insn); + + if (!set) + return false; + + machine_mode ext_dst_mode = GET_MODE (SET_DEST (set)); + + if (!get_defs (cand->insn, orig_src, NULL)) + { + bool copy_needed + = (REGNO (SET_DEST (cand->expr)) != REGNO (XEXP (SET_SRC (cand->expr), 0))); + + if (!copy_needed && ext_dst_mode != GET_MODE (orig_src) + && FUNCTION_ARG_REGNO_P (REGNO (orig_src)) + && !FUNCTION_VALUE_REGNO_P (REGNO (orig_src))) + { + if (side_effects_p (PATTERN (cand->insn))) + return false; + + struct df_link *uses + = get_uses (cand->insn, SET_DEST (PATTERN (cand->insn))); + + if (!uses) return false; + + for (df_link *use = uses; use; use = use->next) + { + if (!use->ref) + return false; + + if (BLOCK_FOR_INSN (cand->insn) + != BLOCK_FOR_INSN (DF_REF_INSN (use->ref))) + return false; + + rtx_insn *insn = DF_REF_INSN (use->ref); + + if (GET_CODE (PATTERN (insn)) == SET) + { + rtx_code code = GET_CODE (SET_SRC (PATTERN (insn))); + if (GET_RTX_CLASS (code) == RTX_BIN_ARITH + || GET_RTX_CLASS (code) == RTX_COMM_ARITH + || GET_RTX_CLASS (code) == RTX_UNARY) + return false; + } + } + return true; + } + } + } + outcome = make_defs_and_copies_lists (cand->insn, set_pat, state); if (!outcome) @@ -1112,26 +1166,35 @@ add_removable_extension (const_rtx expr, rtx_insn *insn, rtx reg = XEXP (src, 0); struct df_link *defs, *def; ext_cand *cand; + defs = get_defs (insn, reg, NULL); /* Zero-extension of an undefined value is partly defined (it's completely undefined for sign-extension, though). So if there exists 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 (!defs && code == ZERO_EXTEND && FUNCTION_ARG_REGNO_P (REGNO (reg))) { - if (dump_file) - { - fprintf (dump_file, "Cannot eliminate extension:\n"); - print_rtl_single (dump_file, insn); - fprintf (dump_file, " because it can operate on uninitialized" - " data\n"); - } + ext_cand e = {expr, code, mode, insn}; + insn_list->safe_push (e); return; } + + if ((code == ZERO_EXTEND + && !bitmap_bit_p (init_regs, REGNO (reg)))) + { + if (dump_file) + { + fprintf (dump_file, "Cannot eliminate extension:\n"); + print_rtl_single (dump_file, insn); + fprintf (dump_file, " because it can operate on uninitialized" + " data\n"); + } + return; + } + /* Second, make sure we can get all the reaching definitions. */ - defs = get_defs (insn, reg, NULL); if (!defs) { if (dump_file) @@ -1321,7 +1384,8 @@ find_and_remove_re (void) && (REGNO (SET_DEST (set)) != REGNO (XEXP (SET_SRC (set), 0)))) { reinsn_copy_list.safe_push (curr_cand->insn); - reinsn_copy_list.safe_push (state.defs_list[0]); + if (state.defs_list.length() != 0) + reinsn_copy_list.safe_push (state.defs_list[0]); } reinsn_del_list.safe_push (curr_cand->insn); state.modified[INSN_UID (curr_cand->insn)].deleted = 1; @@ -1342,24 +1406,27 @@ find_and_remove_re (void) Remember that the memory reference will be changed to refer to the destination of the extention. So we're actually emitting a copy from the new destination to the old destination. */ - for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2) - { - rtx_insn *curr_insn = reinsn_copy_list[i]; - rtx_insn *def_insn = reinsn_copy_list[i + 1]; - - /* Use the mode of the destination of the defining insn - for the mode of the copy. This is necessary if the - defining insn was used to eliminate a second extension - that was wider than the first. */ - rtx sub_rtx = *get_sub_rtx (def_insn); - rtx set = single_set (curr_insn); - rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)), - REGNO (XEXP (SET_SRC (set), 0))); - rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)), - REGNO (SET_DEST (set))); - rtx new_set = gen_rtx_SET (new_dst, new_src); - emit_insn_after (new_set, def_insn); - } + for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2) + { + rtx_insn *curr_insn = reinsn_copy_list[i]; + + if ((i+1) < reinsn_copy_list.length()) + { + rtx_insn *def_insn = reinsn_copy_list[i + 1]; + /* Use the mode of the destination of the defining insn + for the mode of the copy. This is necessary if the + defining insn was used to eliminate a second extension + that was wider than the first. */ + rtx sub_rtx = *get_sub_rtx (def_insn); + rtx set = single_set (curr_insn); + rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)), + REGNO (XEXP (SET_SRC (set), 0))); + rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)), + REGNO (SET_DEST (set))); + rtx new_set = gen_rtx_SET (new_dst, new_src); + emit_insn_after (new_set, def_insn); + } + } /* Delete all useless extensions here in one sweep. */ FOR_EACH_VEC_ELT (reinsn_del_list, i, curr_insn) diff --git a/gcc/testsuite/g++.target/powerpc/zext-elim-3.C b/gcc/testsuite/g++.target/powerpc/zext-elim-3.C new file mode 100644 index 00000000000..1d443af066a --- /dev/null +++ b/gcc/testsuite/g++.target/powerpc/zext-elim-3.C @@ -0,0 +1,16 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mcpu=power9 -O2 -free" } */ + +void *memset(void *b, int c, unsigned long len) +{ + unsigned long i; + + for (i = 0; i < len; i++) + ((unsigned char *)b)[i] = c; + + return b; +} + +/* { dg-final { scan-assembler-not "rlwinm" } } */ -- 2.31.1