aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-01-11 20:34:56 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2018-01-11 20:34:56 +0100
commite2c0d088881e0c8e3ed27bba082187d091631421 (patch)
tree0d539ec18e2da914e8bf2ba569ed2baad4587991 /gcc
parent03943bbd4a468fb51b8a0102daa815c887a45711 (diff)
downloadgcc-e2c0d088881e0c8e3ed27bba082187d091631421.zip
gcc-e2c0d088881e0c8e3ed27bba082187d091631421.tar.gz
gcc-e2c0d088881e0c8e3ed27bba082187d091631421.tar.bz2
re PR target/82682 (FAIL: gcc.target/i386/pr50038.c scan-assembler-times movzbl 2 (found 3 times) since r253958)
PR target/82682 * ree.c (combine_reaching_defs): Optimize also reg2=exp; reg1=reg2; reg2=any_extend(reg1); into reg2=any_extend(exp); reg1=reg2;, formatting fix. From-SVN: r256551
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/ree.c77
2 files changed, 82 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 069d5bb..e676fec 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2018-01-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/82682
+ * ree.c (combine_reaching_defs): Optimize also
+ reg2=exp; reg1=reg2; reg2=any_extend(reg1); into
+ reg2=any_extend(exp); reg1=reg2;, formatting fix.
+
2018-01-11 Jan Hubicka <hubicka@ucw.cz>
PR middle-end/83189
diff --git a/gcc/ree.c b/gcc/ree.c
index aa0132b..8f0ce97 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -901,7 +901,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
REGNO (SET_DEST (pat)));
emit_move_insn (new_dst, new_src);
- rtx_insn *insn = get_insns();
+ rtx_insn *insn = get_insns ();
end_sequence ();
if (NEXT_INSN (insn))
return false;
@@ -910,8 +910,81 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
extract_insn (insn);
if (!constrain_operands (1, get_preferred_alternatives (insn, bb)))
return false;
- }
+ while (REG_P (SET_SRC (*dest_sub_rtx))
+ && (REGNO (SET_SRC (*dest_sub_rtx)) == REGNO (SET_DEST (pat))))
+ {
+ /* Considering transformation of
+ (set (reg2) (expression))
+ ...
+ (set (reg1) (reg2))
+ ...
+ (set (reg2) (any_extend (reg1)))
+
+ into
+
+ (set (reg2) (any_extend (expression)))
+ (set (reg1) (reg2))
+ ... */
+ struct df_link *defs
+ = get_defs (def_insn, SET_SRC (*dest_sub_rtx), NULL);
+ if (defs == NULL || defs->next)
+ break;
+
+ /* There is only one reaching def. */
+ rtx_insn *def_insn2 = DF_REF_INSN (defs->ref);
+
+ /* The defining statement must not have been modified either. */
+ if (state->modified[INSN_UID (def_insn2)].kind != EXT_MODIFIED_NONE)
+ break;
+
+ /* The def_insn2 and candidate insn must be in the same
+ block and def_insn follows def_insn2. */
+ if (bb != BLOCK_FOR_INSN (def_insn2)
+ || DF_INSN_LUID (def_insn2) > DF_INSN_LUID (def_insn))
+ break;
+
+ rtx *dest_sub_rtx2 = get_sub_rtx (def_insn2);
+ if (dest_sub_rtx2 == NULL
+ || !REG_P (SET_DEST (*dest_sub_rtx2)))
+ break;
+
+ /* On RISC machines we must make sure that changing the mode of
+ SRC_REG as destination register will not affect its reaching
+ uses, which may read its value in a larger mode because DEF_INSN
+ implicitly sets it in word mode. */
+ if (WORD_REGISTER_OPERATIONS && known_lt (prec, BITS_PER_WORD))
+ {
+ struct df_link *uses = get_uses (def_insn2, SET_DEST (pat));
+ if (!uses)
+ break;
+
+ df_link *use;
+ rtx dest2 = SET_DEST (*dest_sub_rtx2);
+ for (use = uses; use; use = use->next)
+ if (paradoxical_subreg_p (GET_MODE (*DF_REF_LOC (use->ref)),
+ GET_MODE (dest2)))
+ break;
+ if (use)
+ break;
+ }
+
+ /* The destination register of the extension insn must not be
+ used or set between the def_insn2 and def_insn exclusive.
+ Likewise for the other reg, i.e. check both reg1 and reg2
+ in the above comment. */
+ if (reg_used_between_p (SET_DEST (PATTERN (cand->insn)),
+ def_insn2, def_insn)
+ || reg_set_between_p (SET_DEST (PATTERN (cand->insn)),
+ def_insn2, def_insn)
+ || reg_used_between_p (src_reg, def_insn2, def_insn)
+ || reg_set_between_p (src_reg, def_insn2, def_insn))
+ break;
+
+ state->defs_list[0] = def_insn2;
+ break;
+ }
+ }
/* If cand->insn has been already modified, update cand->mode to a wider
mode if possible, or punt. */