+2010-07-05 Richard Guenther <rguenther@suse.de>
+
+ * tree.c (reference_alias_ptr_type): New function.
+ * tree.h (reference_alias_ptr_type): Declare.
+ * tree-ssa-loop-ivopts.c (copy_ref_info): Restructure to
+ allow non-TARGET_MEM_REF new refs.
+ (rewrite_use_address): Pass old alias pointer type to
+ create_mem_ref.
+ * tree-ssa-address.c (create_mem_ref_raw): Get alias pointer type.
+ Build a MEM_REF instead of a TARGET_MEM_REF if possible.
+ (create_mem_ref): Get alias pointer type. Adjust calls to
+ create_mem_ref_raw.
+ (maybe_fold_tmr): Likewise.
+ * tree-flow.h (create_mem_ref): Adjust prototype.
+
2010-07-05 Jakub Jelinek <jakub@redhat.com>
PR c++/44808
};
struct affine_tree_combination;
-tree create_mem_ref (gimple_stmt_iterator *, tree,
+tree create_mem_ref (gimple_stmt_iterator *, tree, tree,
struct affine_tree_combination *, tree, bool);
rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
void get_address_description (tree, struct mem_address *);
TARGET_MEM_REF. */
static tree
-create_mem_ref_raw (tree type, struct mem_address *addr)
+create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr)
{
if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
return NULL_TREE;
if (addr->offset && integer_zerop (addr->offset))
addr->offset = NULL_TREE;
+ /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF. */
+ if (alias_ptr_type
+ && !addr->index
+ && !addr->step)
+ {
+ tree base, offset;
+ gcc_assert (!addr->symbol ^ !addr->base);
+ if (addr->symbol)
+ base = build_fold_addr_expr (addr->symbol);
+ else
+ base = addr->base;
+ if (addr->offset)
+ offset = fold_convert (alias_ptr_type, addr->offset);
+ else
+ offset = build_int_cst (alias_ptr_type, 0);
+ return fold_build2 (MEM_REF, type, base, offset);
+ }
+
return build6 (TARGET_MEM_REF, type,
addr->symbol, addr->base, addr->index,
addr->step, addr->offset, NULL);
of created memory reference. */
tree
-create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
- tree base_hint, bool speed)
+create_mem_ref (gimple_stmt_iterator *gsi, tree type, tree alias_ptr_type,
+ aff_tree *addr, tree base_hint, bool speed)
{
tree mem_ref, tmp;
tree atype;
addr_to_parts (type, addr, base_hint, &parts, speed);
gimplify_mem_ref_parts (gsi, &parts);
- mem_ref = create_mem_ref_raw (type, &parts);
+ mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
if (mem_ref)
return mem_ref;
true, NULL_TREE, true, GSI_SAME_STMT);
parts.step = NULL_TREE;
- mem_ref = create_mem_ref_raw (type, &parts);
+ mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
if (mem_ref)
return mem_ref;
}
parts.base = tmp;
parts.symbol = NULL_TREE;
- mem_ref = create_mem_ref_raw (type, &parts);
+ mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
if (mem_ref)
return mem_ref;
}
parts.base = parts.index;
parts.index = NULL_TREE;
- mem_ref = create_mem_ref_raw (type, &parts);
+ mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
if (mem_ref)
return mem_ref;
}
parts.offset = NULL_TREE;
- mem_ref = create_mem_ref_raw (type, &parts);
+ mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
if (mem_ref)
return mem_ref;
}
if (!changed)
return NULL_TREE;
- ret = create_mem_ref_raw (TREE_TYPE (ref), &addr);
+ ret = create_mem_ref_raw (TREE_TYPE (ref), NULL_TREE, &addr);
if (!ret)
return NULL_TREE;
static void
copy_ref_info (tree new_ref, tree old_ref)
{
- if (TREE_CODE (old_ref) == TARGET_MEM_REF)
- copy_mem_ref_info (new_ref, old_ref);
- else
- {
- TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
- TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
- TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);
- /* We can transfer points-to information from an old pointer
- or decl base to the new one. */
- if (TMR_BASE (new_ref)
- && TREE_CODE (TMR_BASE (new_ref)) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (TMR_BASE (new_ref)))
- && !SSA_NAME_PTR_INFO (TMR_BASE (new_ref)))
+ tree new_ptr_base = NULL_TREE;
+
+ if (TREE_CODE (old_ref) == TARGET_MEM_REF
+ && TREE_CODE (new_ref) == TARGET_MEM_REF)
+ TMR_ORIGINAL (new_ref) = TMR_ORIGINAL (old_ref);
+ else if (TREE_CODE (new_ref) == TARGET_MEM_REF)
+ TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
+
+ TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
+ TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);
+
+ if (TREE_CODE (new_ref) == TARGET_MEM_REF)
+ new_ptr_base = TMR_BASE (new_ref);
+ else if (TREE_CODE (new_ref) == MEM_REF)
+ new_ptr_base = TREE_OPERAND (new_ref, 0);
+
+ /* We can transfer points-to information from an old pointer
+ or decl base to the new one. */
+ if (new_ptr_base
+ && TREE_CODE (new_ptr_base) == SSA_NAME
+ && POINTER_TYPE_P (TREE_TYPE (new_ptr_base))
+ && !SSA_NAME_PTR_INFO (new_ptr_base))
+ {
+ tree base = get_base_address (old_ref);
+ if ((INDIRECT_REF_P (base)
+ || TREE_CODE (base) == MEM_REF)
+ && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
+ duplicate_ssa_name_ptr_info
+ (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
+ else if (TREE_CODE (base) == VAR_DECL
+ || TREE_CODE (base) == PARM_DECL
+ || TREE_CODE (base) == RESULT_DECL)
{
- tree base = get_base_address (old_ref);
- if ((INDIRECT_REF_P (base)
- || TREE_CODE (base) == MEM_REF)
- && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
- duplicate_ssa_name_ptr_info
- (TMR_BASE (new_ref), SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
- else if (TREE_CODE (base) == VAR_DECL
- || TREE_CODE (base) == PARM_DECL
- || TREE_CODE (base) == RESULT_DECL)
- {
- struct ptr_info_def *pi = get_ptr_info (TMR_BASE (new_ref));
- pt_solution_set_var (&pi->pt, base);
- }
+ struct ptr_info_def *pi = get_ptr_info (new_ptr_base);
+ pt_solution_set_var (&pi->pt, base);
}
}
}
if (cand->iv->base_object)
base_hint = var_at_stmt (data->current_loop, cand, use->stmt);
- ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff, base_hint,
- data->speed);
+ ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p),
+ reference_alias_ptr_type (*use->op_p),
+ &aff, base_hint, data->speed);
copy_ref_info (ref, *use->op_p);
*use->op_p = ref;
}
TYPE_PRECISION (TREE_TYPE (toff)));
}
+/* Return the pointer-type relevant for TBAA purposes from the
+ gimple memory reference tree T. This is the type to be used for
+ the offset operand of MEM_REF or TARGET_MEM_REF replacements of T. */
+
+tree
+reference_alias_ptr_type (const_tree t)
+{
+ const_tree base = t;
+ while (handled_component_p (base))
+ base = TREE_OPERAND (base, 0);
+ if (TREE_CODE (base) == MEM_REF)
+ return TREE_TYPE (TREE_OPERAND (base, 1));
+ else if (TREE_CODE (base) == TARGET_MEM_REF
+ || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
+ return NULL_TREE;
+ else
+ return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (base)));
+}
+
/* Similar except don't specify the TREE_TYPE
and leave the TREE_SIDE_EFFECTS as 0.
It is permissible for arguments to be null,
#define build_simple_mem_ref(T)\
build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
extern double_int mem_ref_offset (const_tree);
+extern tree reference_alias_ptr_type (const_tree);
extern tree constant_boolean_node (int, tree);
extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);