aboutsummaryrefslogtreecommitdiff
path: root/gcc/ree.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2016-11-24 15:01:32 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2016-11-24 15:01:32 +0000
commit4da41abf84cc6796aa8b3ae38402ff7544dfc8d3 (patch)
tree5af5792fbbe2403186385fd0151819ac9a1dc7e4 /gcc/ree.c
parent0d56d3c17b709688ec817372311cde1cc445ae4b (diff)
downloadgcc-4da41abf84cc6796aa8b3ae38402ff7544dfc8d3.zip
gcc-4da41abf84cc6796aa8b3ae38402ff7544dfc8d3.tar.gz
gcc-4da41abf84cc6796aa8b3ae38402ff7544dfc8d3.tar.bz2
re PR rtl-optimization/78437 (invalid sign-extend conversion in REE pass)
PR rtl-optimization/78437 * ree.c (get_uses): New function. (combine_reaching_defs): When a copy is needed, return false if any reaching use of the source register reads it in a mode larger than the mode it is set in and WORD_REGISTER_OPERATIONS is true. From-SVN: r242839
Diffstat (limited to 'gcc/ree.c')
-rw-r--r--gcc/ree.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/gcc/ree.c b/gcc/ree.c
index 6bac17e..a7a6526 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -499,6 +499,35 @@ get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest)
return ref_chain;
}
+/* 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. */
+
+static struct df_link *
+get_uses (rtx_insn *insn, rtx reg)
+{
+ df_ref def;
+ struct df_link *ref_chain, *ref_link;
+
+ FOR_EACH_INSN_DEF (def, insn)
+ if (REGNO (DF_REF_REG (def)) == REGNO (reg))
+ break;
+
+ gcc_assert (def != NULL);
+
+ ref_chain = DF_REF_CHAIN (def);
+
+ for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
+ {
+ /* Problem getting some use for this instruction. */
+ if (ref_link->ref == NULL)
+ return NULL;
+ if (DF_REF_CLASS (ref_link->ref) != DF_REF_REGULAR)
+ return NULL;
+ }
+
+ 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. */
@@ -827,6 +856,23 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
if (reg_overlap_mentioned_p (tmp_reg, SET_DEST (PATTERN (cand->insn))))
return false;
+ /* 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. */
+ const unsigned int prec
+ = GET_MODE_PRECISION (GET_MODE (SET_DEST (*dest_sub_rtx)));
+ if (WORD_REGISTER_OPERATIONS && prec < BITS_PER_WORD)
+ {
+ struct df_link *uses = get_uses (def_insn, src_reg);
+ if (!uses)
+ return false;
+
+ for (df_link *use = uses; use; use = use->next)
+ if (GET_MODE_PRECISION (GET_MODE (*DF_REF_LOC (use->ref))) > prec)
+ return false;
+ }
+
/* The destination register of the extension insn must not be
used or set between the def_insn and cand->insn exclusive. */
if (reg_used_between_p (SET_DEST (PATTERN (cand->insn)),