|
@@ -0,0 +1,111 @@
|
|
|
+From gcc bugzilla https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60155
|
|
|
+Upstream status: in trunk.
|
|
|
+
|
|
|
+Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
|
|
|
+
|
|
|
+--- trunk/gcc/gcse.c 2014/02/12 14:50:06 207726
|
|
|
++++ trunk/gcc/gcse.c 2014/04/04 22:25:51 209134
|
|
|
+@@ -2502,6 +2502,65 @@
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
++struct set_data
|
|
|
++{
|
|
|
++ rtx insn;
|
|
|
++ const_rtx set;
|
|
|
++ int nsets;
|
|
|
++};
|
|
|
++
|
|
|
++/* Increment number of sets and record set in DATA. */
|
|
|
++
|
|
|
++static void
|
|
|
++record_set_data (rtx dest, const_rtx set, void *data)
|
|
|
++{
|
|
|
++ struct set_data *s = (struct set_data *)data;
|
|
|
++
|
|
|
++ if (GET_CODE (set) == SET)
|
|
|
++ {
|
|
|
++ /* We allow insns having multiple sets, where all but one are
|
|
|
++ dead as single set insns. In the common case only a single
|
|
|
++ set is present, so we want to avoid checking for REG_UNUSED
|
|
|
++ notes unless necessary. */
|
|
|
++ if (s->nsets == 1
|
|
|
++ && find_reg_note (s->insn, REG_UNUSED, SET_DEST (s->set))
|
|
|
++ && !side_effects_p (s->set))
|
|
|
++ s->nsets = 0;
|
|
|
++
|
|
|
++ if (!s->nsets)
|
|
|
++ {
|
|
|
++ /* Record this set. */
|
|
|
++ s->nsets += 1;
|
|
|
++ s->set = set;
|
|
|
++ }
|
|
|
++ else if (!find_reg_note (s->insn, REG_UNUSED, dest)
|
|
|
++ || side_effects_p (set))
|
|
|
++ s->nsets += 1;
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
++static const_rtx
|
|
|
++single_set_gcse (rtx insn)
|
|
|
++{
|
|
|
++ struct set_data s;
|
|
|
++ rtx pattern;
|
|
|
++
|
|
|
++ gcc_assert (INSN_P (insn));
|
|
|
++
|
|
|
++ /* Optimize common case. */
|
|
|
++ pattern = PATTERN (insn);
|
|
|
++ if (GET_CODE (pattern) == SET)
|
|
|
++ return pattern;
|
|
|
++
|
|
|
++ s.insn = insn;
|
|
|
++ s.nsets = 0;
|
|
|
++ note_stores (pattern, record_set_data, &s);
|
|
|
++
|
|
|
++ /* Considered invariant insns have exactly one set. */
|
|
|
++ gcc_assert (s.nsets == 1);
|
|
|
++ return s.set;
|
|
|
++}
|
|
|
++
|
|
|
+ /* Emit move from SRC to DEST noting the equivalence with expression computed
|
|
|
+ in INSN. */
|
|
|
+
|
|
|
+@@ -2509,7 +2568,8 @@
|
|
|
+ gcse_emit_move_after (rtx dest, rtx src, rtx insn)
|
|
|
+ {
|
|
|
+ rtx new_rtx;
|
|
|
+- rtx set = single_set (insn), set2;
|
|
|
++ const_rtx set = single_set_gcse (insn);
|
|
|
++ rtx set2;
|
|
|
+ rtx note;
|
|
|
+ rtx eqv = NULL_RTX;
|
|
|
+
|
|
|
+@@ -3369,13 +3429,12 @@
|
|
|
+ FOR_EACH_VEC_ELT (occrs_to_hoist, j, occr)
|
|
|
+ {
|
|
|
+ rtx insn;
|
|
|
+- rtx set;
|
|
|
++ const_rtx set;
|
|
|
+
|
|
|
+ gcc_assert (!occr->deleted_p);
|
|
|
+
|
|
|
+ insn = occr->insn;
|
|
|
+- set = single_set (insn);
|
|
|
+- gcc_assert (set);
|
|
|
++ set = single_set_gcse (insn);
|
|
|
+
|
|
|
+ /* Create a pseudo-reg to store the result of reaching
|
|
|
+ expressions into. Get the mode for the new pseudo
|
|
|
+@@ -3456,10 +3515,8 @@
|
|
|
+ {
|
|
|
+ rtx reg;
|
|
|
+ enum reg_class pressure_class;
|
|
|
+- rtx set = single_set (insn);
|
|
|
++ const_rtx set = single_set_gcse (insn);
|
|
|
+
|
|
|
+- /* Considered invariant insns have only one set. */
|
|
|
+- gcc_assert (set != NULL_RTX);
|
|
|
+ reg = SET_DEST (set);
|
|
|
+ if (GET_CODE (reg) == SUBREG)
|
|
|
+ reg = SUBREG_REG (reg);
|