static int rtx_equal_for_memref_p (const_rtx, const_rtx);
static int memrefs_conflict_p (int, rtx, int, rtx, HOST_WIDE_INT);
static void record_set (rtx, const_rtx, void *);
-static int base_alias_check (rtx, rtx, enum machine_mode,
+static int base_alias_check (rtx, rtx, rtx, rtx, enum machine_mode,
enum machine_mode);
static rtx find_base_value (rtx);
static int mems_in_disjoint_alias_sets_p (const_rtx, const_rtx);
static alias_set_entry get_alias_set_entry (alias_set_type);
static bool nonoverlapping_component_refs_p (const_rtx, const_rtx);
static tree decl_for_component_ref (tree);
-static int write_dependence_p (const_rtx, const_rtx, int);
+static int write_dependence_p (const_rtx, enum machine_mode, rtx, const_rtx,
+ bool, bool);
static void memory_modified_1 (rtx, const_rtx, void *);
if (tmp1 == pic_offset_table_rtx && CONSTANT_P (tmp2))
return find_base_term (tmp2);
- /* If either operand is known to be a pointer, then use it
+ /* If either operand is known to be a pointer, then prefer it
to determine the base term. */
if (REG_P (tmp1) && REG_POINTER (tmp1))
+ ;
+ else if (REG_P (tmp2) && REG_POINTER (tmp2))
{
- rtx base = find_base_term (tmp1);
- if (base)
- return base;
+ rtx tem = tmp1;
+ tmp1 = tmp2;
+ tmp2 = tem;
}
- if (REG_P (tmp2) && REG_POINTER (tmp2))
- {
- rtx base = find_base_term (tmp2);
- if (base)
- return base;
- }
-
- /* Neither operand was known to be a pointer. Go ahead and find the
- base term for both operands. */
- tmp1 = find_base_term (tmp1);
- tmp2 = find_base_term (tmp2);
-
- /* If either base term is named object or a special address
+ /* Go ahead and find the base term for both operands. If either base
+ term is from a pointer or is a named object or a special address
(like an argument or stack reference), then use it for the
base term. */
- if (tmp1 != 0 && known_base_value_p (tmp1))
- return tmp1;
-
- if (tmp2 != 0 && known_base_value_p (tmp2))
- return tmp2;
+ rtx base = find_base_term (tmp1);
+ if (base != NULL_RTX
+ && ((REG_P (tmp1) && REG_POINTER (tmp1))
+ || known_base_value_p (base)))
+ return base;
+ base = find_base_term (tmp2);
+ if (base != NULL_RTX
+ && ((REG_P (tmp2) && REG_POINTER (tmp2))
+ || known_base_value_p (base)))
+ return base;
/* We could not determine which of the two operands was the
base register and which was the index. So we can determine
objects, 1 if they might be pointers to the same object. */
static int
-base_alias_check (rtx x, rtx y, enum machine_mode x_mode,
- enum machine_mode y_mode)
+base_alias_check (rtx x, rtx x_base, rtx y, rtx y_base,
+ enum machine_mode x_mode, enum machine_mode y_mode)
{
- rtx x_base = find_base_term (x);
- rtx y_base = find_base_term (y);
-
/* If the address itself has no known base see if a known equivalent
value has one. If either address still has no known base, nothing
is known about aliasing. */
&& CONSTANT_POOL_ADDRESS_P (base))))
return 0;
- if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
+ rtx mem_base = find_base_term (mem_addr);
+ if (! base_alias_check (x_addr, base, mem_addr, mem_base,
+ GET_MODE (x), mem_mode))
return 0;
x_addr = canon_rtx (x_addr);
}
/* Returns nonzero if a write to X might alias a previous read from
- (or, if WRITEP is nonzero, a write to) MEM. */
+ (or, if WRITEP is true, a write to) MEM.
+ If MEM_CANONCALIZED is nonzero, CANON_MEM_ADDR is the canonicalized
+ address of MEM, and MEM_MODE the mode for that access. */
static int
-write_dependence_p (const_rtx mem, const_rtx x, int writep)
+write_dependence_p (const_rtx mem, enum machine_mode mem_mode,
+ rtx canon_mem_addr, const_rtx x,
+ bool mem_canonicalized, bool writep)
{
rtx x_addr, mem_addr;
rtx base;
int ret;
+ gcc_checking_assert (mem_canonicalized ? (canon_mem_addr != NULL_RTX)
+ : (canon_mem_addr == NULL_RTX && mem_mode == VOIDmode));
+
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
return 1;
mem_addr = get_addr (mem_addr);
}
- if (! writep)
- {
- base = find_base_term (mem_addr);
- if (base && (GET_CODE (base) == LABEL_REF
- || (GET_CODE (base) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (base))))
- return 0;
- }
+ base = find_base_term (mem_addr);
+ if (! writep
+ && base
+ && (GET_CODE (base) == LABEL_REF
+ || (GET_CODE (base) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (base))))
+ return 0;
- if (! base_alias_check (x_addr, mem_addr, GET_MODE (x),
+ rtx x_base = find_base_term (x_addr);
+ if (! base_alias_check (x_addr, x_base, mem_addr, base, GET_MODE (x),
GET_MODE (mem)))
return 0;
x_addr = canon_rtx (x_addr);
- mem_addr = canon_rtx (mem_addr);
+ if (mem_canonicalized)
+ mem_addr = canon_mem_addr;
+ else
+ {
+ mem_addr = canon_rtx (mem_addr);
+ mem_mode = GET_MODE (mem);
+ }
- if ((ret = memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
+ if ((ret = memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
SIZE_FOR_MODE (x), x_addr, 0)) != -1)
return ret;
int
anti_dependence (const_rtx mem, const_rtx x)
{
- return write_dependence_p (mem, x, /*writep=*/0);
+ return write_dependence_p (mem, VOIDmode, NULL_RTX, x,
+ /*mem_canonicalized=*/false, /*writep=*/false);
+}
+
+/* Likewise, but we already have a canonicalized MEM_ADDR for MEM.
+ Also, consider MEM in MEM_MODE (which might be from an enclosing
+ STRICT_LOW_PART / ZERO_EXTRACT). */
+
+int
+canon_anti_dependence (const_rtx mem, enum machine_mode mem_mode,
+ rtx mem_addr, const_rtx x)
+{
+ return write_dependence_p (mem, mem_mode, mem_addr, x,
+ /*mem_canonicalized=*/true, /*writep=*/false);
}
/* Output dependence: X is written after store in MEM takes place. */
int
output_dependence (const_rtx mem, const_rtx x)
{
- return write_dependence_p (mem, x, /*writep=*/1);
+ return write_dependence_p (mem, VOIDmode, NULL_RTX, x,
+ /*mem_canonicalized=*/false, /*writep=*/true);
}
\f
mem_addr = get_addr (mem_addr);
}
- if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), GET_MODE (mem_addr)))
+ rtx x_base = find_base_term (x_addr);
+ rtx mem_base = find_base_term (mem_addr);
+ if (! base_alias_check (x_addr, x_base, mem_addr, mem_base,
+ GET_MODE (x), GET_MODE (mem_addr)))
return 0;
x_addr = canon_rtx (x_addr);