Index: gcc/tree-ssa-alias.c =================================================================== --- gcc/tree-ssa-alias.c (revision 204089) +++ gcc/tree-ssa-alias.c (working copy) @@ -1985,23 +1985,24 @@ stmt_may_clobber_ref_p (gimple stmt, tre return stmt_may_clobber_ref_p_1 (stmt, &r); } /* If STMT kills the memory reference REF return true, otherwise return false. */ static bool stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref) { /* For a must-alias check we need to be able to constrain - the access properly. */ - ao_ref_base (ref); - if (ref->max_size == -1) + the access properly. + FIXME: except for BUILTIN_FREE. */ + if (!ao_ref_base (ref) + || ref->max_size == -1) return false; if (gimple_has_lhs (stmt) && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME /* The assignment is not necessarily carried out if it can throw and we can catch it in the current function where we could inspect the previous value. ??? We only need to care about the RHS throwing. For aggregate assignments or similar calls and non-call exceptions the LHS might throw as well. */ @@ -2064,37 +2065,45 @@ stmt_kills_ref_p_1 (gimple stmt, ao_ref case BUILT_IN_MEMPCPY: case BUILT_IN_MEMMOVE: case BUILT_IN_MEMSET: case BUILT_IN_MEMCPY_CHK: case BUILT_IN_MEMPCPY_CHK: case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMSET_CHK: { tree dest = gimple_call_arg (stmt, 0); tree len = gimple_call_arg (stmt, 2); - tree base = NULL_TREE; - HOST_WIDE_INT offset = 0; + tree rbase = ref->base; + HOST_WIDE_INT roffset = ref->offset; if (!host_integerp (len, 0)) return false; - if (TREE_CODE (dest) == ADDR_EXPR) - base = get_addr_base_and_unit_offset (TREE_OPERAND (dest, 0), - &offset); - else if (TREE_CODE (dest) == SSA_NAME) - base = dest; - if (base - && base == ao_ref_base (ref)) + ao_ref dref; + ao_ref_init_from_ptr_and_size (&dref, dest, len); + tree base = ao_ref_base (&dref); + HOST_WIDE_INT offset = dref.offset; + if (!base) + return false; + if (TREE_CODE (base) == MEM_REF) + { + if (TREE_CODE (rbase) != MEM_REF) + return false; + // Compare pointers. + offset += 8 * TREE_INT_CST_LOW (TREE_OPERAND (base, 1)); + roffset += 8 * TREE_INT_CST_LOW (TREE_OPERAND (rbase, 1)); + base = TREE_OPERAND (base, 0); + rbase = TREE_OPERAND (rbase, 0); + } + if (base == rbase) { - HOST_WIDE_INT size = TREE_INT_CST_LOW (len); - if (offset <= ref->offset / BITS_PER_UNIT - && (offset + size - >= ((ref->offset + ref->max_size + BITS_PER_UNIT - 1) - / BITS_PER_UNIT))) + HOST_WIDE_INT size = 8 * TREE_INT_CST_LOW (len); + if (offset <= roffset + && offset + size >= (roffset + ref->max_size)) return true; } break; } case BUILT_IN_VA_END: { tree ptr = gimple_call_arg (stmt, 0); if (TREE_CODE (ptr) == ADDR_EXPR) {