X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Falias.c;h=a1e12fba44ebceaa869cee148cdfae73eadd8ef3;hp=41a2f2318f74cd3757a3e4bef8c090aa3ca4b1c2;hb=6ff06d363f15102bf83a04bd7228a7fc13230995;hpb=48e1416a24d50cacbb2a5e06a9ee61dd8cbee313 diff --git a/gcc/alias.c b/gcc/alias.c index 41a2f2318f7..a1e12fba44e 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -1,6 +1,6 @@ /* Alias analysis for GNU C Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008, 2009 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by John Carr (jfc@mit.edu). This file is part of GCC. @@ -265,11 +265,6 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem) if (!expr) return false; - /* If MEM_OFFSET or MEM_SIZE are NULL punt. */ - if (!MEM_OFFSET (mem) - || !MEM_SIZE (mem)) - return false; - ao_ref_init (ref, expr); /* Get the base of the reference and see if we have to reject or @@ -278,17 +273,17 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem) if (base == NULL_TREE) return false; + /* The tree oracle doesn't like to have these. */ + if (TREE_CODE (base) == FUNCTION_DECL + || TREE_CODE (base) == LABEL_DECL) + return false; + /* If this is a pointer dereference of a non-SSA_NAME punt. ??? We could replace it with a pointer to anything. */ if (INDIRECT_REF_P (base) && TREE_CODE (TREE_OPERAND (base, 0)) != SSA_NAME) return false; - /* The tree oracle doesn't like to have these. */ - if (TREE_CODE (base) == FUNCTION_DECL - || TREE_CODE (base) == LABEL_DECL) - return false; - /* If this is a reference based on a partitioned decl replace the base with an INDIRECT_REF of the pointer representative we created during stack slot partitioning. */ @@ -307,6 +302,18 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem) ref->ref_alias_set = MEM_ALIAS_SET (mem); + /* If MEM_OFFSET or MEM_SIZE are NULL we have to punt. + Keep points-to related information though. */ + if (!MEM_OFFSET (mem) + || !MEM_SIZE (mem)) + { + ref->ref = NULL_TREE; + ref->offset = 0; + ref->size = -1; + ref->max_size = -1; + return true; + } + /* If the base decl is a parameter we can have negative MEM_OFFSET in case of promoted subregs on bigendian targets. Trust the MEM_EXPR here. */ @@ -406,7 +413,7 @@ alias_set_subset_of (alias_set_type set1, alias_set_type set2) /* Otherwise, check if set1 is a subset of set2. */ ase = get_alias_set_entry (set2); if (ase != 0 - && ((ase->has_zero_child && set1 == 0) + && (ase->has_zero_child || splay_tree_lookup (ase->children, (splay_tree_key) set1))) return true; @@ -1684,14 +1691,7 @@ base_alias_check (rtx x, rtx y, enum machine_mode x_mode, || (GET_CODE (y_base) == ADDRESS && GET_MODE (y_base) == Pmode)) return 0; - if (! flag_argument_noalias) - return 1; - - if (flag_argument_noalias > 1) - return 0; - - /* Weak noalias assertion (arguments are distinct, but may match globals). */ - return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode); + return 1; } /* Convert the address X into something we can use. This is done by returning @@ -1759,8 +1759,12 @@ addr_side_effect_eval (rtx addr, int size, int n_refs) return addr; } -/* Return nonzero if X and Y (memory addresses) could reference the - same location in memory. C is an offset accumulator. When +/* Return one if X and Y (memory addresses) reference the + same location in memory or if the references overlap. + Return zero if they do not overlap, else return + minus one in which case they still might reference the same location. + + C is an offset accumulator. When C is nonzero, we are testing aliases between X and Y + C. XSIZE is the size in bytes of the X reference, similarly YSIZE is the size in bytes for Y. @@ -1775,15 +1779,51 @@ addr_side_effect_eval (rtx addr, int size, int n_refs) align memory references, as is done on the Alpha. Nice to notice that varying addresses cannot conflict with fp if no - local variables had their addresses taken, but that's too hard now. */ + local variables had their addresses taken, but that's too hard now. + + ??? Contrary to the tree alias oracle this does not return + one for X + non-constant and Y + non-constant when X and Y are equal. + If that is fixed the TBAA hack for union type-punning can be removed. */ static int memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) { if (GET_CODE (x) == VALUE) - x = get_addr (x); + { + if (REG_P (y)) + { + struct elt_loc_list *l = NULL; + if (CSELIB_VAL_PTR (x)) + for (l = CSELIB_VAL_PTR (x)->locs; l; l = l->next) + if (REG_P (l->loc) && rtx_equal_for_memref_p (l->loc, y)) + break; + if (l) + x = y; + else + x = get_addr (x); + } + /* Don't call get_addr if y is the same VALUE. */ + else if (x != y) + x = get_addr (x); + } if (GET_CODE (y) == VALUE) - y = get_addr (y); + { + if (REG_P (x)) + { + struct elt_loc_list *l = NULL; + if (CSELIB_VAL_PTR (y)) + for (l = CSELIB_VAL_PTR (y)->locs; l; l = l->next) + if (REG_P (l->loc) && rtx_equal_for_memref_p (l->loc, x)) + break; + if (l) + y = x; + else + y = get_addr (y); + } + /* Don't call get_addr if x is the same VALUE. */ + else if (y != x) + y = get_addr (y); + } if (GET_CODE (x) == HIGH) x = XEXP (x, 0); else if (GET_CODE (x) == LO_SUM) @@ -1841,7 +1881,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) else if (CONST_INT_P (y1)) return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1)); - return 1; + return -1; } else if (CONST_INT_P (x1)) return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1)); @@ -1856,7 +1896,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) if (CONST_INT_P (y1)) return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1)); else - return 1; + return -1; } if (GET_CODE (x) == GET_CODE (y)) @@ -1871,7 +1911,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) rtx x1 = canon_rtx (XEXP (x, 1)); rtx y1 = canon_rtx (XEXP (y, 1)); if (! rtx_equal_for_memref_p (x1, y1)) - return 1; + return -1; x0 = canon_rtx (XEXP (x, 0)); y0 = canon_rtx (XEXP (y, 0)); if (rtx_equal_for_memref_p (x0, y0)) @@ -1880,7 +1920,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) /* Can't properly adjust our sizes. */ if (!CONST_INT_P (x1)) - return 1; + return -1; xsize /= INTVAL (x1); ysize /= INTVAL (x1); c /= INTVAL (x1); @@ -1939,9 +1979,10 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) || (rtx_equal_for_memref_p (x, y) && ((c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)))); - return 1; + return -1; } - return 1; + + return -1; } /* Functions to compute memory dependencies. @@ -2138,6 +2179,13 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y) if (exprx == 0 || expry == 0) return 0; + /* For spill-slot accesses make sure we have valid offsets. */ + if ((exprx == get_spill_slot_decl (false) + && ! MEM_OFFSET (x)) + || (expry == get_spill_slot_decl (false) + && ! MEM_OFFSET (y))) + return 0; + /* If both are field references, we may be able to determine something. */ if (TREE_CODE (exprx) == COMPONENT_REF && TREE_CODE (expry) == COMPONENT_REF @@ -2166,13 +2214,6 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y) exprx = t; } } - else if (INDIRECT_REF_P (exprx)) - { - exprx = TREE_OPERAND (exprx, 0); - if (flag_argument_noalias < 2 - || TREE_CODE (exprx) != PARM_DECL) - return 0; - } moffsety = MEM_OFFSET (y); if (TREE_CODE (expry) == COMPONENT_REF) @@ -2194,13 +2235,6 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y) expry = t; } } - else if (INDIRECT_REF_P (expry)) - { - expry = TREE_OPERAND (expry, 0); - if (flag_argument_noalias < 2 - || TREE_CODE (expry) != PARM_DECL) - return 0; - } if (! DECL_P (exprx) || ! DECL_P (expry)) return 0; @@ -2294,6 +2328,7 @@ true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x, { rtx x_addr, mem_addr; rtx base; + int ret; if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem)) return 1; @@ -2308,18 +2343,12 @@ true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x, || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER) return 1; - if (DIFFERENT_ALIAS_SETS_P (x, mem)) - return 0; - /* Read-only memory is by definition never modified, and therefore can't conflict with anything. We don't expect to find read-only set on MEM, but stupid user tricks can produce them, so don't die. */ if (MEM_READONLY_P (x)) return 0; - if (nonoverlapping_memrefs_p (mem, x)) - return 0; - /* If we have MEMs refering to different address spaces (which can potentially overlap), we cannot easily tell from the addresses whether the references overlap. */ @@ -2344,8 +2373,14 @@ true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x, x_addr = canon_rtx (x_addr); mem_addr = canon_rtx (mem_addr); - if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr, - SIZE_FOR_MODE (x), x_addr, 0)) + if ((ret = memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr, + SIZE_FOR_MODE (x), x_addr, 0)) != -1) + return ret; + + if (DIFFERENT_ALIAS_SETS_P (x, mem)) + return 0; + + if (nonoverlapping_memrefs_p (mem, x)) return 0; if (aliases_everything_p (x)) @@ -2378,6 +2413,8 @@ int canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool)) { + int ret; + if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem)) return 1; @@ -2391,18 +2428,12 @@ canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER) return 1; - if (DIFFERENT_ALIAS_SETS_P (x, mem)) - return 0; - /* Read-only memory is by definition never modified, and therefore can't conflict with anything. We don't expect to find read-only set on MEM, but stupid user tricks can produce them, so don't die. */ if (MEM_READONLY_P (x)) return 0; - if (nonoverlapping_memrefs_p (x, mem)) - return 0; - /* If we have MEMs refering to different address spaces (which can potentially overlap), we cannot easily tell from the addresses whether the references overlap. */ @@ -2416,8 +2447,14 @@ canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, return 0; x_addr = canon_rtx (x_addr); - if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr, - SIZE_FOR_MODE (x), x_addr, 0)) + if ((ret = memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr, + SIZE_FOR_MODE (x), x_addr, 0)) != -1) + return ret; + + if (DIFFERENT_ALIAS_SETS_P (x, mem)) + return 0; + + if (nonoverlapping_memrefs_p (x, mem)) return 0; if (aliases_everything_p (x)) @@ -2448,6 +2485,7 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep) rtx x_addr, mem_addr; const_rtx fixed_scalar; rtx base; + int ret; if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem)) return 1; @@ -2466,9 +2504,6 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep) if (!writep && MEM_READONLY_P (mem)) return 0; - if (nonoverlapping_memrefs_p (x, mem)) - return 0; - /* If we have MEMs refering to different address spaces (which can potentially overlap), we cannot easily tell from the addresses whether the references overlap. */ @@ -2494,8 +2529,11 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep) x_addr = canon_rtx (x_addr); mem_addr = canon_rtx (mem_addr); - if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr, - SIZE_FOR_MODE (x), x_addr, 0)) + if ((ret = memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr, + SIZE_FOR_MODE (x), x_addr, 0)) != -1) + return ret; + + if (nonoverlapping_memrefs_p (x, mem)) return 0; fixed_scalar