Hi, the alias-2.c testcase fails on targets with anchors. The reason is that the variable itself is anchored while the alias is not and they point to the same location. I folllowed the docs of SYMBOL_REF claiming that SYMBOL_REF_DECL if the symbol is label and tought it is safe to disambiguate them.
This patch commonizes the logic to compare_base_symbol_refs which acts equivalently to compare_base_decls but on tRTL's SYMBOL_REF and can handle querries when one parameter is DECL while other is anchor. I am not fully sure about the case where we know that the variable is in a block and we know its offset. With current implementation I do not think it is safe to use offset orracle because one offset is offset inside a variable, while other is offset inside of the block. This can be compensated for. Also it seems that the alias code should not ignore the base informaiton it has in memory attributes as it can be more precise. This patch fixes the alias-2.c testcase and was bootstrapped/regtsted on arm. OK? I will look into anchor code - it seems it should create anchor for the alias, too because it is non-interposable, but for some reason it does not. Honza PR middle-end/68832 * alias.c (compare_base_symbol_refs): New function. (rtx_equal_for_memref_p, base_alias_check, memrefs_conflict_p): Use it. Index: alias.c =================================================================== --- alias.c (revision 231722) +++ alias.c (working copy) @@ -158,6 +158,7 @@ static int write_dependence_p (const_rtx, const_rtx, machine_mode, rtx, bool, bool, bool); +static int compare_base_symbol_refs (const_rtx, const_rtx); static void memory_modified_1 (rtx, const_rtx, void *); @@ -1756,16 +1757,8 @@ return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y); case SYMBOL_REF: - { - tree x_decl = SYMBOL_REF_DECL (x); - tree y_decl = SYMBOL_REF_DECL (y); + return compare_base_symbol_refs (x, y) == 1; - if (!x_decl || !y_decl) - return XSTR (x, 0) == XSTR (y, 0); - else - return compare_base_decls (x_decl, y_decl) == 1; - } - case ENTRY_VALUE: /* This is magic, don't go through canonicalization et al. */ return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y)); @@ -2052,6 +2045,65 @@ return ret; } +/* Same as compare_base_decls but for SYMBOL_REF. + Return -2 if the offset based oracle can not be used (i.e. + we have a symbol and section anchor which is located insite + the same block. */ + +static int +compare_base_symbol_refs (const_rtx x_base, const_rtx y_base) +{ + tree x_decl = SYMBOL_REF_DECL (x_base); + tree y_decl = SYMBOL_REF_DECL (y_base); + bool binds_def = true; + if (x_decl && y_decl) + return compare_base_decls (x_decl, y_decl); + if (x_decl || y_decl) + { + if (!x_decl) + { + std::swap (x_decl, y_decl); + std::swap (x_base, y_base); + } + /* Variable and anchor representing the variable alias. If x_base + is not a static variable or y_base is not an anchor (it is a label) + we are safe. */ + if (!SYMBOL_REF_HAS_BLOCK_INFO_P (y_base) + || (TREE_CODE (x_decl) != VAR_DECL + || (!TREE_STATIC (x_decl) && !TREE_PUBLIC (x_decl)))) + return 0; + symtab_node *x_node = symtab_node::get_create (x_decl) + ->ultimate_alias_target (); + /* External variable can not be in section anchor. */ + if (!x_node->definition) + return 0; + x_base = XEXP (DECL_RTL (x_node->decl), 0); + /* If not in anchor, we can disambiguate. */ + if (!SYMBOL_REF_HAS_BLOCK_INFO_P (x_base)) + return 0; + + /* We have an alias of anchored variable. If it can be interposed; + we must assume it may or may not alias its anchor. */ + binds_def = decl_binds_to_current_def_p (x_decl); + } + /* If we have variable in section anchor, we can compare by offset. */ + if (SYMBOL_REF_HAS_BLOCK_INFO_P (x_base) + && SYMBOL_REF_HAS_BLOCK_INFO_P (y_base)) + { + if (SYMBOL_REF_BLOCK (x_base) != SYMBOL_REF_BLOCK (y_base)) + return 0; + if (SYMBOL_REF_BLOCK_OFFSET (x_base) == SYMBOL_REF_BLOCK_OFFSET (y_base)) + return binds_def ? 1 : -1; + /* Mixing anchors and non-anchors may result to false negative. + We probably never do that. */ + if (SYMBOL_REF_ANCHOR_P (x_base) != SYMBOL_REF_ANCHOR_P (y_base)) + return -2; + return 0; + } + /* Label and label or label and section anchor. Copare symbol name. */ + return XSTR (x_base, 0) == XSTR (y_base, 0); +} + /* Return 0 if the addresses X and Y are known to point to different objects, 1 if they might be pointers to the same object. */ @@ -2090,16 +2142,8 @@ return 1; if (GET_CODE (x_base) == SYMBOL_REF && GET_CODE (y_base) == SYMBOL_REF) - { - tree x_decl = SYMBOL_REF_DECL (x_base); - tree y_decl = SYMBOL_REF_DECL (y_base); + return compare_base_symbol_refs (x_base, y_base) != 0; - /* We can assume that no stores are made to labels. */ - if (!x_decl || !y_decl) - return 0; - return compare_base_decls (x_decl, y_decl) != 0; - } - /* The base addresses are different expressions. If they are not accessed via AND, there is no conflict. We can bring knowledge of object alignment into play here. For example, on alpha, "char a, b;" can @@ -2323,26 +2367,14 @@ if (GET_CODE (x) == SYMBOL_REF && GET_CODE (y) == SYMBOL_REF) { - tree x_decl = SYMBOL_REF_DECL (x); - tree y_decl = SYMBOL_REF_DECL (y); - int cmp; + int cmp = compare_base_symbol_refs (x,y); - if (!x_decl || !y_decl) - { - /* Label and normal symbol are never the same. */ - if (x_decl != y_decl) - return 0; - return offset_overlap_p (c, xsize, ysize); - } - else - cmp = compare_base_decls (x_decl, y_decl); - /* If both decls are the same, decide by offsets. */ if (cmp == 1) return offset_overlap_p (c, xsize, ysize); /* If decls are different or we know by offsets that there is no overlap, we win. */ - if (!cmp || !offset_overlap_p (c, xsize, ysize)) + if (!cmp || (cmp != -2 && !offset_overlap_p (c, xsize, ysize))) return 0; /* Decls may or may not be different and offsets overlap....*/ return -1;