2004-01-12 Jan Hubicka <jh@suse.cz>
- Partial fox for PR opt/10776 II
+ * alias.c: Invlude varray.h
+ (alias_sets): Turn into varray.
+ (get_alias_set_entry): Use VARRAY; mark inline.
+ (mems_in_disjoint_alias_sets_p): Mark inline.
+ (record_alias_subset): Use varray.
+ (init_alias_once): Initialize varray.
+ (new_alias_set): Grow array.
+ * varray.c: Make VARRAY_GENERIC_PTR non GTYized.
+
+2004-01-12 Jan Hubicka <jh@suse.cz>
+
+ Partial fix for PR opt/10776 II
* cselib.c: Include params.h
(cselib_invalidate_mem): Limit amount of nonconflicting memory
locations.
gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(GGC_H) $(RECOG_H) $(EXPR_H) \
$(BASIC_BLOCK_H) function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) \
- except.h gt-gcse.h $(TREE_H)
+ except.h gt-gcse.h $(TREE_H) cselib.h
sibcall.o : sibcall.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
function.h hard-reg-set.h flags.h insn-config.h $(RECOG_H) $(BASIC_BLOCK_H)
resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) coretypes.h \
#include "timevar.h"
#include "target.h"
#include "cgraph.h"
+#include "varray.h"
/* The alias sets assigned to MEMs assist the back-end in determining
which MEMs can alias which other MEMs. In general, two MEMs in
static bool copying_arguments;
/* The splay-tree used to store the various alias set entries. */
-static splay_tree alias_sets;
+varray_type alias_sets;
\f
/* Returns a pointer to the alias set entry for ALIAS_SET, if there is
such an entry, or NULL otherwise. */
-static alias_set_entry
+static inline alias_set_entry
get_alias_set_entry (HOST_WIDE_INT alias_set)
{
- splay_tree_node sn
- = splay_tree_lookup (alias_sets, (splay_tree_key) alias_set);
-
- return sn != 0 ? ((alias_set_entry) sn->value) : 0;
+ return (alias_set_entry)VARRAY_GENERIC_PTR (alias_sets, alias_set);
}
/* Returns nonzero if the alias sets for MEM1 and MEM2 are such that
the two MEMs cannot alias each other. */
-static int
+static inline int
mems_in_disjoint_alias_sets_p (rtx mem1, rtx mem2)
{
#ifdef ENABLE_CHECKING
static HOST_WIDE_INT last_alias_set;
if (flag_strict_aliasing)
- return ++last_alias_set;
+ {
+ VARRAY_GROW (alias_sets, last_alias_set + 2);
+ return ++last_alias_set;
+ }
else
return 0;
}
superset_entry->children
= splay_tree_new (splay_tree_compare_ints, 0, 0);
superset_entry->has_zero_child = 0;
- splay_tree_insert (alias_sets, (splay_tree_key) superset,
- (splay_tree_value) superset_entry);
+ VARRAY_GENERIC_PTR (alias_sets, superset) = superset_entry;
}
if (subset == 0)
= gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
#endif
- alias_sets = splay_tree_new (splay_tree_compare_ints, 0, 0);
+ VARRAY_GENERIC_PTR_INIT (alias_sets, 10, "alias sets");
}
/* Set MEMORY_MODIFIED when X modifies DATA (that is assumed
{
enum machine_mode mode;
rtx exp;
+ rtx addr;
};
static int
{
struct check_dependence_data *d = (struct check_dependence_data *) data;
if (*x && GET_CODE (*x) == MEM)
- return true_dependence (d->exp, d->mode, *x, cse_rtx_varies_p);
+ return canon_true_dependence (d->exp, d->mode, d->addr, *x,
+ cse_rtx_varies_p);
else
return 0;
}
{
int i;
struct table_elt *p;
+ rtx addr;
switch (GET_CODE (x))
{
return;
case MEM:
+ addr = canon_rtx (get_addr (XEXP (x, 0)));
/* Calculate the canonical version of X here so that
true_dependence doesn't generate new RTL for X on each call. */
x = canon_rtx (x);
if (!p->canon_exp)
p->canon_exp = canon_rtx (p->exp);
d.exp = x;
+ d.addr = addr;
d.mode = full_mode;
if (for_each_rtx (&p->canon_exp, check_dependence, &d))
remove_from_table (p, i);
static void add_mem_for_addr (cselib_val *, cselib_val *, rtx);
static cselib_val *cselib_lookup_mem (rtx, int);
static void cselib_invalidate_regno (unsigned int, enum machine_mode);
-static int cselib_mem_conflict_p (rtx, rtx);
static void cselib_invalidate_mem (rtx);
static void cselib_invalidate_rtx (rtx, rtx, void *);
static void cselib_record_set (rtx, cselib_val *, cselib_val *);
el = ggc_alloc (sizeof (struct elt_loc_list));
el->next = next;
el->loc = loc;
+ el->canon_loc = NULL;
el->setting_insn = cselib_current_insn;
el->in_libcall = cselib_current_insn_in_libcall;
return el;
}
}
}
-
-/* The memory at address MEM_BASE is being changed.
- Return whether this change will invalidate VAL. */
+\f
+/* Return 1 if X has a value that can vary even between two
+ executions of the program. 0 means X can be compared reliably
+ against certain constants or near-constants. */
static int
-cselib_mem_conflict_p (rtx mem_base, rtx val)
+cselib_rtx_varies_p (rtx x ATTRIBUTE_UNUSED, int from_alias ATTRIBUTE_UNUSED)
{
- enum rtx_code code;
- const char *fmt;
- int i, j;
-
- code = GET_CODE (val);
- switch (code)
- {
- /* Get rid of a few simple cases quickly. */
- case REG:
- case PC:
- case CC0:
- case SCRATCH:
- case CONST:
- case CONST_INT:
- case CONST_DOUBLE:
- case CONST_VECTOR:
- case SYMBOL_REF:
- case LABEL_REF:
- return 0;
-
- case MEM:
- if (GET_MODE (mem_base) == BLKmode
- || GET_MODE (val) == BLKmode
- || anti_dependence (val, mem_base))
- return 1;
-
- /* The address may contain nested MEMs. */
- break;
-
- default:
- break;
- }
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- if (cselib_mem_conflict_p (mem_base, XEXP (val, i)))
- return 1;
- }
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (val, i); j++)
- if (cselib_mem_conflict_p (mem_base, XVECEXP (val, i, j)))
- return 1;
- }
-
+ /* We actually don't need to verify very hard. This is because
+ if X has actually changed, we invalidate the memory anyway,
+ so assume that all common memory addresses are
+ invariant. */
return 0;
}
{
cselib_val **vp, *v, *next;
int num_mems = 0;
+ rtx mem_addr;
+
+ mem_addr = canon_rtx (get_addr (XEXP (mem_rtx, 0)));
+ mem_rtx = canon_rtx (mem_rtx);
vp = &first_containing_mem;
for (v = *vp; v != &dummy_val; v = next)
while (*p)
{
rtx x = (*p)->loc;
+ rtx canon_x = (*p)->canon_loc;
cselib_val *addr;
struct elt_list **mem_chain;
p = &(*p)->next;
continue;
}
+ if (!canon_x)
+ canon_x = (*p)->canon_loc = canon_rtx (x);
if (num_mems < PARAM_VALUE (PARAM_MAX_CSELIB_MEMORY_LOCATIONS)
- && ! cselib_mem_conflict_p (mem_rtx, x))
+ && ! canon_true_dependence (mem_rtx, GET_MODE (mem_rtx), mem_addr,
+ x, cselib_rtx_varies_p))
{
has_mem = true;
num_mems++;
struct elt_loc_list *next;
/* An rtl expression that holds the value. */
rtx loc;
+ rtx canon_loc;
/* The insn that made the equivalence. */
rtx setting_insn;
/* True when setting insn is inside libcall. */
{ sizeof (unsigned long), 1 },
{ sizeof (HOST_WIDE_INT), 1 },
{ sizeof (unsigned HOST_WIDE_INT), 1 },
- { sizeof (void *), 1 },
+ { sizeof (void *), 0 },
{ sizeof (char *), 1 },
{ sizeof (struct rtx_def *), 1 },
{ sizeof (struct rtvec_def *), 1 },