diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dc4f9a0bf61..9368985a8dd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,49 @@ +2010-09-03 Richard Guenther + + * tree.def (TARGET_MEM_REF): Merge TMR_SYMBOL and TMR_BASE. + Move TMR_OFFSET to second operand. Add TMR_INDEX2. + * tree.h (TMR_SYMBOL): Remove. + (TMR_BASE, TMR_OFFSET): Adjust. + (TMR_INDEX2): New. + * alias.c (ao_ref_from_mem): Use TMR_BASE. + * builtins.c (get_object_alignment): Merge TMR_BASE and + TMR_SYMBOL handling. + * cfgexpand.c (expand_debug_expr): Use TMR_BASE. + * gimple.c (get_base_address): Merge MEM_REF and TARGET_MEM_REF + handling. Also allow TARGET_MEM_REF as base address. + (walk_stmt_load_store_addr_ops): TMR_BASE is always non-NULL. + * gimplify.c (gimplify_expr): Gimplify TMR_BASE like MEM_REF + base. Gimplify TMR_INDEX2. + * tree-cfg.c (verify_types_in_gimple_reference): Adjust. + * tree-dfa.c (get_ref_base_and_extent): Likewise. + (get_addr_base_and_unit_offset): Likewise. + * tree-eh.c (tree_could_trap_p): Likewise. + * tree-pretty-print.c (dump_generic_node): Likewise. + * tree-ssa-address.c (tree_mem_ref_addr): Simplify. Handle + TMR_INDEX2. + (create_mem_ref_raw): Merge symbol and base. Move 2ndary + base to index2. + (get_address_description): Reconstruct addres description + from merged TMR_BASE and TMR_INDEX2. + (maybe_fold_tmr): Fold propagated addresses. + * tree-ssa-alias.c (indirect_ref_may_alias_decl_p): Merge + MEM_REF and TARGET_MEM_REF paths. + (indirect_refs_may_alias_p): Likewise. + * tree-ssa-live.c (mark_all_vars_used_1): Handle TMR_INDEX2 + instead of TMR_SYMBOL. + * tree-ssa-operands.c (get_tmr_operands): Simplify. + * tree-ssa-pre.c (create_component_ref_by_pieces_1): Adjust + according to changes ... + * tree-ssa-sccvn.c (copy_reference_ops_from_ref): ... here. + Split TARGET_MEM_REF into two fields plus the base. + * tree.c (mem_ref_offset): Simplify. + * tree-ssa-loop-im.c (for_each_index): Handle TMR_INDEX2. + * tree-ssa-loop-ivopts.c (find_interesting_uses_address): Likewise. + Strip NOPs when folding MEM_REF addresses. + * tree-ssa-sink.c (is_hidden_global_store): Handle TARGET_MEM_REF. + * gimple-fold.c (maybe_fold_reference): Fold TARGET_MEM_REF here ... + (fold_gimple_assign): ... not here. + 2010-09-03 Mingjie Xing * config/mips/mips.h (SHIFT_COUNT_TRUNCATED): Change the definition. diff --git a/gcc/alias.c b/gcc/alias.c index 580f8987d68..854ac27aa9d 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -301,14 +301,14 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem) ref->base = build_simple_mem_ref (*(tree *)namep); } else if (TREE_CODE (base) == TARGET_MEM_REF - && TMR_SYMBOL (base) - && TREE_CODE (TREE_OPERAND (TMR_SYMBOL (base), 0)) == VAR_DECL - && ! TREE_STATIC (TREE_OPERAND (TMR_SYMBOL (base), 0)) + && TREE_CODE (TMR_BASE (base)) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (TMR_BASE (base), 0)) == VAR_DECL + && ! TREE_STATIC (TREE_OPERAND (TMR_BASE (base), 0)) && cfun->gimple_df->decls_to_pointers != NULL) { void *namep; namep = pointer_map_contains (cfun->gimple_df->decls_to_pointers, - TREE_OPERAND (TMR_SYMBOL (base), 0)); + TREE_OPERAND (TMR_BASE (base), 0)); if (namep) ref->base = build_simple_mem_ref (*(tree *)namep); } diff --git a/gcc/builtins.c b/gcc/builtins.c index 2cebb0e9dcd..c2176d9aae3 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -331,9 +331,7 @@ get_object_alignment (tree exp, unsigned int max_align) max_align)); bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT; } - else if (TREE_CODE (exp) == TARGET_MEM_REF - && TMR_BASE (exp) - && POINTER_TYPE_P (TREE_TYPE (TMR_BASE (exp)))) + else if (TREE_CODE (exp) == TARGET_MEM_REF) { struct ptr_info_def *pi; tree addr = TMR_BASE (exp); @@ -365,22 +363,7 @@ get_object_alignment (tree exp, unsigned int max_align) } else if (TMR_INDEX (exp)) align = BITS_PER_UNIT; - } - else if (TREE_CODE (exp) == TARGET_MEM_REF - && TMR_SYMBOL (exp)) - { - align = get_object_alignment (TREE_OPERAND (TMR_SYMBOL (exp), 0), - max_align); - if (TMR_OFFSET (exp)) - bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT; - if (TMR_INDEX (exp) && TMR_STEP (exp)) - { - unsigned HOST_WIDE_INT step = TREE_INT_CST_LOW (TMR_STEP (exp)); - align = MIN (align, (step & -step) * BITS_PER_UNIT); - } - else if (TMR_INDEX (exp)) - align = BITS_PER_UNIT; - if (TMR_BASE (exp)) + if (TMR_INDEX2 (exp)) align = BITS_PER_UNIT; } else diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 1852885fba0..a979d6f3c1a 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2468,8 +2468,8 @@ expand_debug_expr (tree exp) return op0; case TARGET_MEM_REF: - if (TMR_SYMBOL (exp) - && !DECL_RTL_SET_P (TREE_OPERAND (TMR_SYMBOL (exp), 0))) + if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR + && !DECL_RTL_SET_P (TREE_OPERAND (TMR_BASE (exp), 0))) return NULL; op0 = expand_debug_expr diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 59aa946a883..8a48316f00d 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -528,6 +528,18 @@ maybe_fold_reference (tree expr, bool is_lhs) return expr; } } + else if (TREE_CODE (*t) == TARGET_MEM_REF) + { + tree tem = maybe_fold_tmr (*t); + if (tem) + { + *t = tem; + tem = maybe_fold_reference (expr, is_lhs); + if (tem) + return tem; + return expr; + } + } else if (!is_lhs && DECL_P (*t)) { @@ -602,9 +614,6 @@ fold_gimple_assign (gimple_stmt_iterator *si) COND_EXPR_THEN (rhs), COND_EXPR_ELSE (rhs)); } - else if (TREE_CODE (rhs) == TARGET_MEM_REF) - return maybe_fold_tmr (rhs); - else if (REFERENCE_CLASS_P (rhs)) return maybe_fold_reference (rhs, false); diff --git a/gcc/gimple.c b/gcc/gimple.c index c0b5052eb54..bb68be691ad 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -3004,18 +3004,17 @@ get_base_address (tree t) while (handled_component_p (t)) t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == MEM_REF + if ((TREE_CODE (t) == MEM_REF + || TREE_CODE (t) == TARGET_MEM_REF) && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR) t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); - else if (TREE_CODE (t) == TARGET_MEM_REF - && TMR_SYMBOL (t)) - t = TREE_OPERAND (TMR_SYMBOL (t), 0); if (SSA_VAR_P (t) || TREE_CODE (t) == STRING_CST || TREE_CODE (t) == CONSTRUCTOR || INDIRECT_REF_P (t) - || TREE_CODE (t) == MEM_REF) + || TREE_CODE (t) == MEM_REF + || TREE_CODE (t) == TARGET_MEM_REF) return t; else return NULL_TREE; @@ -4725,7 +4724,6 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data, if (TREE_CODE (rhs) == ADDR_EXPR) ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data); else if (TREE_CODE (rhs) == TARGET_MEM_REF - && TMR_BASE (rhs) != NULL_TREE && TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR) ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data); else if (TREE_CODE (rhs) == OBJ_TYPE_REF @@ -4734,7 +4732,6 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data, 0), data); lhs = gimple_assign_lhs (stmt); if (TREE_CODE (lhs) == TARGET_MEM_REF - && TMR_BASE (lhs) != NULL_TREE && TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR) ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data); } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index bdb97ec9ba0..1723f42d8a2 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -6977,20 +6977,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE; - if (TMR_SYMBOL (*expr_p)) - /* We can't gimplify the symbol part. Assert it is - already gimple instead. - ??? This isn't exactly the same as ADDR_EXPR - plus is_gimple_mem_ref_addr (), see fixed_address_object_p. */ - gcc_assert (TREE_CODE (TMR_SYMBOL (*expr_p)) == ADDR_EXPR - && (TREE_CODE (TREE_OPERAND (TMR_SYMBOL (*expr_p), 0)) - == VAR_DECL)); if (TMR_BASE (*expr_p)) r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p, - post_p, is_gimple_val, fb_either); + post_p, is_gimple_mem_ref_addr, fb_either); if (TMR_INDEX (*expr_p)) r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p, post_p, is_gimple_val, fb_rvalue); + if (TMR_INDEX2 (*expr_p)) + r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p, + post_p, is_gimple_val, fb_rvalue); /* TMR_STEP and TMR_OFFSET are always integer constants. */ ret = MIN (r0, r1); } diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 1dc99aaf8d7..14982ffa849 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2990,11 +2990,10 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue) } else if (TREE_CODE (expr) == TARGET_MEM_REF) { - if (TMR_SYMBOL (expr) - && TMR_BASE (expr) - && !useless_type_conversion_p (sizetype, TREE_TYPE (TMR_BASE (expr)))) + if (!TMR_BASE (expr) + || !is_gimple_mem_ref_addr (TMR_BASE (expr))) { - error ("Non-sizetype base in TARGET_MEM_REF with symbol"); + error ("Invalid address operand in in TARGET_MEM_REF."); return true; } if (!TMR_OFFSET (expr) diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index c60e107f7b1..0bc9f41755a 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -880,19 +880,19 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, case TARGET_MEM_REF: /* Hand back the decl for MEM[&decl, off]. */ - if (TMR_SYMBOL (exp)) + if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR) { - /* Via the variable index or base we can reach the + /* Via the variable index or index2 we can reach the whole object. */ - if (TMR_INDEX (exp) || TMR_BASE (exp)) + if (TMR_INDEX (exp) || TMR_INDEX2 (exp)) { - exp = TREE_OPERAND (TMR_SYMBOL (exp), 0); + exp = TREE_OPERAND (TMR_BASE (exp), 0); bit_offset = 0; maxsize = -1; goto done; } if (integer_zerop (TMR_OFFSET (exp))) - exp = TREE_OPERAND (TMR_SYMBOL (exp), 0); + exp = TREE_OPERAND (TMR_BASE (exp), 0); else { double_int off = mem_ref_offset (exp); @@ -904,7 +904,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, if (double_int_fits_in_shwi_p (off)) { bit_offset = double_int_to_shwi (off); - exp = TREE_OPERAND (TMR_SYMBOL (exp), 0); + exp = TREE_OPERAND (TMR_BASE (exp), 0); } } } @@ -1044,9 +1044,9 @@ get_addr_base_and_unit_offset (tree exp, HOST_WIDE_INT *poffset) case TARGET_MEM_REF: /* Hand back the decl for MEM[&decl, off]. */ - if (TMR_SYMBOL (exp)) + if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR) { - if (TMR_INDEX (exp) || TMR_BASE (exp)) + if (TMR_INDEX (exp) || TMR_INDEX2 (exp)) return NULL_TREE; if (!integer_zerop (TMR_OFFSET (exp))) { @@ -1054,7 +1054,7 @@ get_addr_base_and_unit_offset (tree exp, HOST_WIDE_INT *poffset) gcc_assert (off.high == -1 || off.high == 0); byte_offset += double_int_to_shwi (off); } - exp = TREE_OPERAND (TMR_SYMBOL (exp), 0); + exp = TREE_OPERAND (TMR_BASE (exp), 0); } goto done; diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 3d7859ba6f4..1faa682fbd9 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -2404,8 +2404,8 @@ tree_could_trap_p (tree expr) switch (code) { case TARGET_MEM_REF: - if (TMR_SYMBOL (expr) - && !TMR_INDEX (expr) && !TMR_BASE (expr)) + if (TREE_CODE (TMR_BASE (expr)) == ADDR_EXPR + && !TMR_INDEX (expr) && !TMR_INDEX2 (expr)) return false; return !TREE_THIS_NOTRAP (expr); diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index dbbd06cc6ae..2c697ec500d 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -852,16 +852,22 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, pp_string (buffer, "MEM["); - tmp = TMR_SYMBOL (node); - if (tmp) + if (TREE_CODE (TMR_BASE (node)) == ADDR_EXPR) { pp_string (buffer, sep); sep = ", "; pp_string (buffer, "symbol: "); - dump_generic_node (buffer, TREE_OPERAND (tmp, 0), + dump_generic_node (buffer, TREE_OPERAND (TMR_BASE (node), 0), spc, flags, false); } - tmp = TMR_BASE (node); + else + { + pp_string (buffer, sep); + sep = ", "; + pp_string (buffer, "base: "); + dump_generic_node (buffer, TMR_BASE (node), spc, flags, false); + } + tmp = TMR_INDEX2 (node); if (tmp) { pp_string (buffer, sep); diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c index d642425df3a..99b87bbd198 100644 --- a/gcc/tree-ssa-address.c +++ b/gcc/tree-ssa-address.c @@ -268,17 +268,9 @@ tree_mem_ref_addr (tree type, tree mem_ref) tree addr; tree act_elem; tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref); - tree sym = TMR_SYMBOL (mem_ref), base = TMR_BASE (mem_ref); tree addr_base = NULL_TREE, addr_off = NULL_TREE; - if (sym) - addr_base = fold_convert (type, sym); - else if (base) - { - gcc_assert (POINTER_TYPE_P (TREE_TYPE (base))); - addr_base = fold_convert (type, base); - base = NULL_TREE; - } + addr_base = fold_convert (type, TMR_BASE (mem_ref)); act_elem = TMR_INDEX (mem_ref); if (act_elem) @@ -288,7 +280,7 @@ tree_mem_ref_addr (tree type, tree mem_ref) addr_off = act_elem; } - act_elem = base; + act_elem = TMR_INDEX2 (mem_ref); if (act_elem) { if (addr_off) @@ -307,16 +299,9 @@ tree_mem_ref_addr (tree type, tree mem_ref) } if (addr_off) - { - if (addr_base) - addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off); - else - addr = fold_convert (type, addr_off); - } - else if (addr_base) - addr = addr_base; + addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off); else - addr = build_int_cst (type, 0); + addr = addr_base; return addr; } @@ -344,6 +329,8 @@ valid_mem_ref_p (enum machine_mode mode, addr_space_t as, static tree create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr) { + tree base, index2; + if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr)) return NULL_TREE; @@ -355,23 +342,31 @@ create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr) else addr->offset = build_int_cst (alias_ptr_type, 0); - /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF. */ - if (alias_ptr_type - && (!addr->index || integer_zerop (addr->index)) - && (!addr->base || POINTER_TYPE_P (TREE_TYPE (addr->base)))) + if (addr->symbol) { - tree base; - gcc_assert (!addr->symbol ^ !addr->base); - if (addr->symbol) - base = addr->symbol; - else - base = addr->base; - return fold_build2 (MEM_REF, type, base, addr->offset); + base = addr->symbol; + index2 = addr->base; + } + else if (addr->base + && POINTER_TYPE_P (TREE_TYPE (addr->base))) + { + base = addr->base; + index2 = NULL_TREE; + } + else + { + base = build_int_cst (ptr_type_node, 0); + index2 = addr->base; } + /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF. */ + if (alias_ptr_type + && (!index2 || integer_zerop (index2)) + && (!addr->index || integer_zerop (addr->index))) + return fold_build2 (MEM_REF, type, base, addr->offset); + return build5 (TARGET_MEM_REF, type, - addr->symbol, addr->base, addr->index, - addr->step, addr->offset); + base, addr->offset, addr->index, addr->step, index2); } /* Returns true if OBJ is an object whose address is a link time constant. */ @@ -808,8 +803,22 @@ create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr, void get_address_description (tree op, struct mem_address *addr) { - addr->symbol = TMR_SYMBOL (op); - addr->base = TMR_BASE (op); + if (TREE_CODE (TMR_BASE (op)) == ADDR_EXPR) + { + addr->symbol = TMR_BASE (op); + addr->base = TMR_INDEX2 (op); + } + else + { + addr->symbol = NULL_TREE; + if (TMR_INDEX2 (op)) + { + gcc_assert (integer_zerop (TMR_BASE (op))); + addr->base = TMR_INDEX2 (op); + } + else + addr->base = TMR_BASE (op); + } addr->index = TMR_INDEX (op); addr->step = TMR_STEP (op); addr->offset = TMR_OFFSET (op); @@ -837,7 +846,9 @@ maybe_fold_tmr (tree ref) get_address_description (ref, &addr); - if (addr.base && TREE_CODE (addr.base) == INTEGER_CST) + if (addr.base + && TREE_CODE (addr.base) == INTEGER_CST + && !integer_zerop (addr.base)) { addr.offset = fold_binary_to_constant (PLUS_EXPR, TREE_TYPE (addr.offset), @@ -846,6 +857,28 @@ maybe_fold_tmr (tree ref) changed = true; } + if (addr.symbol + && TREE_CODE (TREE_OPERAND (addr.symbol, 0)) == MEM_REF) + { + addr.offset = fold_binary_to_constant + (PLUS_EXPR, TREE_TYPE (addr.offset), + addr.offset, + TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 1)); + addr.symbol = TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 0); + changed = true; + } + else if (addr.symbol + && handled_component_p (TREE_OPERAND (addr.symbol, 0))) + { + HOST_WIDE_INT offset; + addr.symbol = build_fold_addr_expr + (get_addr_base_and_unit_offset + (TREE_OPERAND (addr.symbol, 0), &offset)); + addr.offset = int_const_binop (PLUS_EXPR, + addr.offset, size_int (offset), 0); + changed = true; + } + if (addr.index && TREE_CODE (addr.index) == INTEGER_CST) { off = addr.index; diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index fe017d7a15e..a9f1c19f7ac 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -670,21 +670,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, tree ptrtype1; HOST_WIDE_INT offset1p = offset1, offset2p = offset2; - if (TREE_CODE (base1) == TARGET_MEM_REF) - { - if (TMR_SYMBOL (base1)) - ptr1 = TMR_SYMBOL (base1); - else if (TMR_BASE (base1)) - { - if (!POINTER_TYPE_P (TREE_TYPE (TMR_BASE (base1)))) - return true; - ptr1 = TMR_BASE (base1); - } - else - return true; - } - else - ptr1 = TREE_OPERAND (base1, 0); + ptr1 = TREE_OPERAND (base1, 0); /* The offset embedded in MEM_REFs can be negative. Bias them so that the resulting offset adjustment is positive. */ @@ -812,37 +798,8 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, tree ptr2; tree ptrtype1, ptrtype2; - if (TREE_CODE (base1) == TARGET_MEM_REF) - { - if (TMR_SYMBOL (base1)) - ptr1 = TMR_SYMBOL (base1); - else if (TMR_BASE (base1)) - { - if (!POINTER_TYPE_P (TREE_TYPE (TMR_BASE (base1)))) - return true; - ptr1 = TMR_BASE (base1); - } - else - return true; - } - else - ptr1 = TREE_OPERAND (base1, 0); - - if (TREE_CODE (base2) == TARGET_MEM_REF) - { - if (TMR_SYMBOL (base2)) - ptr2 = TMR_SYMBOL (base2); - else if (TMR_BASE (base2)) - { - if (!POINTER_TYPE_P (TREE_TYPE (TMR_BASE (base2)))) - return true; - ptr2 = TMR_BASE (base2); - } - else - return true; - } - else - ptr2 = TREE_OPERAND (base2, 0); + ptr1 = TREE_OPERAND (base1, 0); + ptr2 = TREE_OPERAND (base2, 0); /* If both bases are based on pointers they cannot alias if they may not point to the same memory object or if they point to the same object diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 9b5c3583332..715b5a71c07 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -362,13 +362,13 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees, void *data) && (b = TREE_BLOCK (t)) != NULL) TREE_USED (b) = true; - /* Ignore TREE_ORIGINAL for TARGET_MEM_REFS, as well as other - fields that do not contain vars. */ + /* Ignore TMR_OFFSET and TMR_STEP for TARGET_MEM_REFS, as those + fields do not contain vars. */ if (TREE_CODE (t) == TARGET_MEM_REF) { - mark_all_vars_used (&TMR_SYMBOL (t), data); mark_all_vars_used (&TMR_BASE (t), data); mark_all_vars_used (&TMR_INDEX (t), data); + mark_all_vars_used (&TMR_INDEX2 (t), data); *walk_subtrees = 0; return NULL; } diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 477c4d2b260..3e71b5c1963 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -324,6 +324,10 @@ for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data) && !cbck (*addr_p, idx, data)) return false; idx = &TMR_INDEX (*addr_p); + if (*idx + && !cbck (*addr_p, idx, data)) + return false; + idx = &TMR_INDEX2 (*addr_p); if (*idx && !cbck (*addr_p, idx, data)) return false; diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 78bbd8eb296..0a1c44ec964 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -1722,6 +1722,16 @@ find_interesting_uses_address (struct ivopts_data *data, gimple stmt, tree *op_p TMR_BASE (base) = civ->base; step = civ->step; } + if (TMR_INDEX2 (base) + && TREE_CODE (TMR_INDEX2 (base)) == SSA_NAME) + { + civ = get_iv (data, TMR_INDEX2 (base)); + if (!civ) + goto fail; + + TMR_INDEX2 (base) = civ->base; + step = civ->step; + } if (TMR_INDEX (base) && TREE_CODE (TMR_INDEX (base)) == SSA_NAME) { @@ -1778,9 +1788,14 @@ find_interesting_uses_address (struct ivopts_data *data, gimple stmt, tree *op_p ref = &TREE_OPERAND (*ref, 0); if (TREE_CODE (*ref) == MEM_REF) { - tree tem = fold_binary (MEM_REF, TREE_TYPE (*ref), - TREE_OPERAND (*ref, 0), - TREE_OPERAND (*ref, 1)); + tree tem = TREE_OPERAND (*ref, 0); + STRIP_NOPS (tem); + if (tem != TREE_OPERAND (*ref, 0)) + tem = fold_build2 (MEM_REF, TREE_TYPE (*ref), + tem, TREE_OPERAND (*ref, 1)); + else + tem = fold_binary (MEM_REF, TREE_TYPE (*ref), + tem, TREE_OPERAND (*ref, 1)); if (tem) *ref = tem; } diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 90c2460d80e..09f12ef52ba 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -754,9 +754,7 @@ get_tmr_operands (gimple stmt, tree expr, int flags) /* First record the real operands. */ get_expr_operands (stmt, &TMR_BASE (expr), opf_use | (flags & opf_no_vops)); get_expr_operands (stmt, &TMR_INDEX (expr), opf_use | (flags & opf_no_vops)); - - if (TMR_SYMBOL (expr)) - mark_address_taken (TREE_OPERAND (TMR_SYMBOL (expr), 0)); + get_expr_operands (stmt, &TMR_INDEX2 (expr), opf_use | (flags & opf_no_vops)); add_virtual_operand (stmt, flags); } diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index fd3da9e9a20..6e457208b5f 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -2772,8 +2772,10 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, break; case TARGET_MEM_REF: { - pre_expr op0expr; - tree genop0 = NULL_TREE; + pre_expr op0expr, op1expr; + tree genop0 = NULL_TREE, genop1 = NULL_TREE; + vn_reference_op_t nextop = VEC_index (vn_reference_op_s, ref->operands, + ++*operand); tree baseop = create_component_ref_by_pieces_1 (block, ref, operand, stmts, domstmt); if (!baseop) @@ -2786,14 +2788,16 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, if (!genop0) return NULL_TREE; } - if (DECL_P (baseop)) - return build5 (TARGET_MEM_REF, currop->type, - baseop, NULL_TREE, - genop0, currop->op1, currop->op2); - else - return build5 (TARGET_MEM_REF, currop->type, - NULL_TREE, baseop, - genop0, currop->op1, currop->op2); + if (nextop->op0) + { + op1expr = get_or_alloc_expr_for (nextop->op0); + genop1 = find_or_generate_expression (block, op1expr, + stmts, domstmt); + if (!genop1) + return NULL_TREE; + } + return build5 (TARGET_MEM_REF, currop->type, + baseop, currop->op2, genop0, currop->op1, genop1); } break; case ADDR_EXPR: diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index cbf0e25712f..c440a28f413 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -575,11 +575,6 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result) if (TREE_CODE (ref) == TARGET_MEM_REF) { vn_reference_op_s temp; - tree base; - - base = TMR_SYMBOL (ref) ? TMR_SYMBOL (ref) : TMR_BASE (ref); - if (!base) - base = null_pointer_node; memset (&temp, 0, sizeof (temp)); /* We do not care for spurious type qualifications. */ @@ -593,8 +588,15 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result) memset (&temp, 0, sizeof (temp)); temp.type = NULL_TREE; - temp.opcode = TREE_CODE (base); - temp.op0 = base; + temp.opcode = ERROR_MARK; + temp.op0 = TMR_INDEX2 (ref); + temp.off = -1; + VEC_safe_push (vn_reference_op_s, heap, *result, &temp); + + memset (&temp, 0, sizeof (temp)); + temp.type = NULL_TREE; + temp.opcode = TREE_CODE (TMR_BASE (ref)); + temp.op0 = TMR_BASE (ref); temp.off = -1; VEC_safe_push (vn_reference_op_s, heap, *result, &temp); return; diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c index 9deec26b11d..436047b8e93 100644 --- a/gcc/tree-ssa-sink.c +++ b/gcc/tree-ssa-sink.c @@ -191,7 +191,8 @@ is_hidden_global_store (gimple stmt) } else if (INDIRECT_REF_P (lhs) - || TREE_CODE (lhs) == MEM_REF) + || TREE_CODE (lhs) == MEM_REF + || TREE_CODE (lhs) == TARGET_MEM_REF) return ptr_deref_may_alias_global_p (TREE_OPERAND (lhs, 0)); else if (CONSTANT_CLASS_P (lhs)) return true; diff --git a/gcc/tree.c b/gcc/tree.c index 55275fa0a78..4659a105d32 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -3910,7 +3910,7 @@ build_simple_mem_ref_loc (location_t loc, tree ptr) double_int mem_ref_offset (const_tree t) { - tree toff = TREE_CODE (t) == MEM_REF ? TREE_OPERAND (t, 1) : TMR_OFFSET (t); + tree toff = TREE_OPERAND (t, 1); return double_int_sext (tree_to_double_int (toff), TYPE_PRECISION (TREE_TYPE (toff))); } diff --git a/gcc/tree.def b/gcc/tree.def index bd8434aa095..43bdd42ea94 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -952,14 +952,16 @@ DEFTREECODE (WITH_SIZE_EXPR, "with_size_expr", tcc_expression, 2) generated by the builtin targetm.vectorize.mask_for_load_builtin_decl. */ DEFTREECODE (REALIGN_LOAD_EXPR, "realign_load", tcc_expression, 3) -/* Low-level memory addressing. Operands are SYMBOL (address of static or - global variable), BASE (register), INDEX (register), STEP (integer constant), - OFFSET (integer constant). Corresponding address is - SYMBOL + BASE + STEP * INDEX + OFFSET. Only variations and values valid on - the target are allowed. +/* Low-level memory addressing. Operands are BASE (address of static or + global variable or register), OFFSET (integer constant), + INDEX (register), STEP (integer constant), INDEX2 (register), + The corresponding address is BASE + STEP * INDEX + INDEX2 + OFFSET. + Only variations and values valid on the target are allowed. - The type of STEP and INDEX is sizetype. The type of BASE is - sizetype or a pointer type (if SYMBOL is NULL). + The type of STEP, INDEX and INDEX2 is sizetype. + + The type of BASE is a pointer type. If BASE is not an address of + a static or global variable INDEX2 will be NULL. The type of OFFSET is a pointer type and determines TBAA the same as the constant offset operand in MEM_REF. */ diff --git a/gcc/tree.h b/gcc/tree.h index 17eeba7e81c..e667742c2bb 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1632,12 +1632,13 @@ extern void protected_set_expr_location (tree, location_t); #define CASE_HIGH(NODE) TREE_OPERAND (CASE_LABEL_EXPR_CHECK (NODE), 1) #define CASE_LABEL(NODE) TREE_OPERAND (CASE_LABEL_EXPR_CHECK (NODE), 2) -/* The operands of a TARGET_MEM_REF. */ -#define TMR_SYMBOL(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 0)) -#define TMR_BASE(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 1)) +/* The operands of a TARGET_MEM_REF. Operands 0 and 1 have to match + corresponding MEM_REF operands. */ +#define TMR_BASE(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 0)) +#define TMR_OFFSET(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 1)) #define TMR_INDEX(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 2)) #define TMR_STEP(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 3)) -#define TMR_OFFSET(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 4)) +#define TMR_INDEX2(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 4)) /* The operands of a BIND_EXPR. */ #define BIND_EXPR_VARS(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 0))