This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix reg notes after store motion
- From: law at redhat dot com
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 15 Sep 2003 17:02:51 -0600
- Subject: Fix reg notes after store motion
- Reply-to: law at redhat dot com
This is an update to Zdenek's patch originally written to resolve the
problems noted in this thread.
http://gcc.gnu.org/ml/gcc-patches/2003-04/msg00086.html
It turns out the problem Zdenek was fixing is triggered with the existing
store-motion implementation on the tree-ssa branch.
Anyway, all I've done is updated some of the comments and dealt with
minor changes in function signatures in gcse.c
Bootstrapped and regression tested.
* gcse.c (remove_reachable_equiv_notes): New.
(replace_store_insn): Call it. Update antic list.
(store_killed_in_insn): Take REG_EQUAL notes into account.
(build_store_vectors, delete_store): Add parameter to
replace_store_insn call.
Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.273
diff -c -3 -p -r1.273 gcse.c
*** gcse.c 15 Sep 2003 01:55:49 -0000 1.273
--- gcse.c 15 Sep 2003 22:58:43 -0000
*************** static bool store_killed_before (rtx, rt
*** 692,698 ****
static void build_store_vectors (void);
static void insert_insn_start_bb (rtx, basic_block);
static int insert_store (struct ls_expr *, edge);
! static void replace_store_insn (rtx, rtx, basic_block);
static void delete_store (struct ls_expr *, basic_block);
static void free_store_memory (void);
static void store_motion (void);
--- 692,699 ----
static void build_store_vectors (void);
static void insert_insn_start_bb (rtx, basic_block);
static int insert_store (struct ls_expr *, edge);
! static void remove_reachable_equiv_notes (basic_block, struct ls_expr *);
! static void replace_store_insn (rtx, rtx, basic_block, struct ls_expr *);
static void delete_store (struct ls_expr *, basic_block);
static void free_store_memory (void);
static void store_motion (void);
*************** find_loads (rtx x, rtx store_pattern, in
*** 7254,7260 ****
static bool
store_killed_in_insn (rtx x, rtx x_regs, rtx insn, int after)
{
! rtx reg, base;
if (!INSN_P (insn))
return false;
--- 7255,7261 ----
static bool
store_killed_in_insn (rtx x, rtx x_regs, rtx insn, int after)
{
! rtx reg, base, note;
if (!INSN_P (insn))
return false;
*************** store_killed_in_insn (rtx x, rtx x_regs,
*** 7305,7314 ****
return true;
}
}
! return find_loads (SET_SRC (pat), x, after);
}
! else
! return find_loads (PATTERN (insn), x, after);
}
/* Returns true if the expression X is loaded or clobbered on or after INSN
--- 7306,7331 ----
return true;
}
}
! if (find_loads (SET_SRC (pat), x, after))
! return true;
}
! else if (find_loads (PATTERN (insn), x, after))
! return true;
!
! /* If this insn has a REG_EQUAL or REG_EQUIV note referencing a memory
! location aliased with X, then this insn kills X. */
! note = find_reg_equal_equiv_note (insn);
! if (! note)
! return false;
! note = XEXP (note, 0);
!
! /* However, if the note represents a must alias rather than a may
! alias relationship, then it does not kill X. */
! if (expr_equiv_p (note, x))
! return false;
!
! /* See if there are any aliased loads in the note. */
! return find_loads (note, x, after);
}
/* Returns true if the expression X is loaded or clobbered on or after INSN
*************** build_store_vectors (void)
*** 7396,7402 ****
rtx r = gen_reg_rtx (GET_MODE (ptr->pattern));
if (gcse_file)
fprintf (gcse_file, "Removing redundant store:\n");
! replace_store_insn (r, XEXP (st, 0), bb);
continue;
}
SET_BIT (ae_gen[bb->index], ptr->index);
--- 7413,7419 ----
rtx r = gen_reg_rtx (GET_MODE (ptr->pattern));
if (gcse_file)
fprintf (gcse_file, "Removing redundant store:\n");
! replace_store_insn (r, XEXP (st, 0), bb, ptr);
continue;
}
SET_BIT (ae_gen[bb->index], ptr->index);
*************** insert_store (struct ls_expr * expr, edg
*** 7551,7563 ****
return 1;
}
/* This routine will replace a store with a SET to a specified register. */
static void
! replace_store_insn (rtx reg, rtx del, basic_block bb)
{
! rtx insn;
insn = gen_move_insn (reg, SET_SRC (single_set (del)));
insn = emit_insn_after (insn, del);
--- 7568,7654 ----
return 1;
}
+ /* Remove any REG_EQUAL or REG_EQUIV notes containing a reference to the
+ memory location in SMEXPR set in basic block BB.
+
+ This could be rather expensive. */
+
+ static void
+ remove_reachable_equiv_notes (basic_block bb, struct ls_expr *smexpr)
+ {
+ edge *stack = xmalloc (sizeof (edge) * n_basic_blocks), act;
+ sbitmap visited = sbitmap_alloc (last_basic_block);
+ int stack_top = 0;
+ rtx last, insn, note;
+ rtx mem = smexpr->pattern;
+
+ sbitmap_zero (visited);
+ act = bb->succ;
+
+ while (1)
+ {
+ if (!act)
+ {
+ if (!stack_top)
+ {
+ free (stack);
+ sbitmap_free (visited);
+ return;
+ }
+ act = stack[--stack_top];
+ }
+ bb = act->dest;
+
+ if (bb == EXIT_BLOCK_PTR
+ || TEST_BIT (visited, bb->index)
+ || TEST_BIT (ae_kill[bb->index], smexpr->index))
+ {
+ act = act->succ_next;
+ continue;
+ }
+ SET_BIT (visited, bb->index);
+
+ if (TEST_BIT (st_antloc[bb->index], smexpr->index))
+ {
+ for (last = ANTIC_STORE_LIST (smexpr);
+ BLOCK_FOR_INSN (XEXP (last, 0)) != bb;
+ last = XEXP (last, 1))
+ continue;
+ last = XEXP (last, 0);
+ }
+ else
+ last = NEXT_INSN (bb->end);
+
+ for (insn = bb->head; insn != last; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ note = find_reg_equal_equiv_note (insn);
+ if (!note || !expr_equiv_p (XEXP (note, 0), mem))
+ continue;
+
+ if (gcse_file)
+ fprintf (gcse_file, "STORE_MOTION drop REG_EQUAL note at insn %d:\n",
+ INSN_UID (insn));
+ remove_note (insn, note);
+ }
+ act = act->succ_next;
+ if (bb->succ)
+ {
+ if (act)
+ stack[stack_top++] = act;
+ act = bb->succ;
+ }
+ }
+ }
+
/* This routine will replace a store with a SET to a specified register. */
static void
! replace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr)
{
! rtx insn, mem, note, set, ptr;
+ mem = smexpr->pattern;
insn = gen_move_insn (reg, SET_SRC (single_set (del)));
insn = emit_insn_after (insn, del);
*************** replace_store_insn (rtx reg, rtx del, ba
*** 7571,7577 ****
--- 7662,7696 ----
fprintf (gcse_file, "\n");
}
+ for (ptr = ANTIC_STORE_LIST (smexpr); ptr; ptr = XEXP (ptr, 1))
+ if (XEXP (ptr, 0) == del)
+ {
+ XEXP (ptr, 0) = insn;
+ break;
+ }
delete_insn (del);
+
+ /* Now we must handle REG_EQUAL notes whose contents is equal to the mem;
+ they are no longer accurate provided that they are reached by this
+ definition, so drop them. */
+ for (; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ set = single_set (insn);
+ if (!set)
+ continue;
+ if (expr_equiv_p (SET_DEST (set), mem))
+ return;
+ note = find_reg_equal_equiv_note (insn);
+ if (!note || !expr_equiv_p (XEXP (note, 0), mem))
+ continue;
+
+ if (gcse_file)
+ fprintf (gcse_file, "STORE_MOTION drop REG_EQUAL note at insn %d:\n",
+ INSN_UID (insn));
+ remove_note (insn, note);
+ }
+ remove_reachable_equiv_notes (bb, smexpr);
}
*************** delete_store (struct ls_expr * expr, bas
*** 7595,7601 ****
{
/* We know there is only one since we deleted redundant
ones during the available computation. */
! replace_store_insn (reg, del, bb);
break;
}
}
--- 7714,7720 ----
{
/* We know there is only one since we deleted redundant
ones during the available computation. */
! replace_store_insn (reg, del, bb, expr);
break;
}
}