This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] New middle-end memory model (final)
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Mark Mitchell <mark at codesourcery dot com>
- Date: Wed, 20 May 2009 12:36:12 +0200 (CEST)
- Subject: [PATCH] New middle-end memory model (final)
This is the final version of the patch, removing some more dead code
regarding to TBAA pruning of points-to sets and the flow-insensitive
alias warning code using points-to information.
I have tested the effects of the patch on SPEC2006 scores for x86_64
and found its effects to be in the noise. The patch fixes the
placement-new related tramp3d miscompile that got exposed recently
again.
Bootstrapped and tested on x86_64-unknown-linux-gnu. I need approval
for the C++ parts.
Ok for trunk?
Thanks,
Richard.
2009-05-20 Richard Guenther <rguenther@suse.de>
PR middle-end/38964
* alias.c (write_dependence_p): Do not use TBAA for answering
anti-dependence or output-dependence.
* tree-ssa-structalias.c (set_uids_in_ptset): Remove TBAA pruning
code.
(emit_pointer_definition): Remove.
(emit_alias_warning): Likewise.
(find_what_var_points_to): Remove TBAA pruning code.
(find_what_p_points_to): Likewise. Do not warn about strict-aliasing
violations.
(compute_points_to_sets): Remove code computing the set of
dereferenced pointers.
* tree-data-ref.c (dr_may_alias_p): Properly use the split
oracle for querying anti and output dependencies.
* tree-ssa-alias.c (refs_may_alias_p_1): Add argument specifying
if TBAA may be applied.
(refs_anti_dependent_p): New function.
(refs_output_dependent_p): Likewise.
* tree-ssa-alias.h (refs_anti_dependent_p): Declare.
(refs_output_dependent_p): Likewise.
* doc/tree-ssa.texi (Memory model): New section.
testsuite/
* g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C: XFAIL.
* gcc.dg/Wstrict-aliasing-converted-assigned.c: Likewise.
* gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c: Likewise.
* doc/c-tree.texi (CHANGE_DYNAMIC_TYPE_EXPR): Remove.
* doc/gimple.texi (GIMPLE_CHANGE_DYNAMIC_TYPE): Remove.
* cfgexpand.c (expand_gimple_basic_block): Do not handle
GIMPLE_CHANGE_DYNAMIC_TYPE or CHANGE_DYNAMIC_TYPE_EXPR.
* expr.c (expand_expr_real_1): Likewise.
* gimple-low.c (lower_stmt): Likewise.
* gimple-pretty-print.c (dump_gimple_stmt): Likewise.
(dump_gimple_cdt): Remove.
* gimple.c (gss_for_code): Do not handle GIMPLE_CHANGE_DYNAMIC_TYPE.
(gimple_size): Likewise.
(walk_gimple_op): Likewise.
(is_gimple_stmt): Likewise.
(walk_stmt_load_store_addr_ops): Likewise.
(gimple_build_cdt): Remove.
* gimple.def (GIMPLE_CHANGE_DYNAMIC_TYPE): Remove.
* gimple.h (gimple_cdt_new_type): Remove.
(gimple_cdt_new_type_ptr): Likewise.
(gimple_cdt_set_new_type): Likewise.
(gimple_cdt_location): Likewise.
(gimple_cdt_location_ptr): Likewise.
(gimple_cdt_set_location): Likewise.
* gimplify.c (gimplify_expr): Do not handle CHANGE_DYNAMIC_TYPE_EXPR.
* tree-cfg.c (remove_useless_stmts_1): Do not handle
GIMPLE_CHANGE_DYNAMIC_TYPE.
(verify_types_in_gimple_stmt): Likewise.
* tree-inline.c (estimate_num_insns): Likewise.
(expand_call_inline): Do not copy DECL_NO_TBAA_P.
(copy_decl_to_var): Likewise.
(copy_result_decl_to_var): Likewise.
* tree-pretty-print.c (dump_generic_node): Do not handle
CHANGE_DYNAMIC_TYPE_EXPR.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
* tree-ssa-operands.c (get_expr_operands): Likewise.
* tree-ssa-structalias.c (struct variable_info): Remove
no_tbaa_pruning member.
(new_var_info): Do not set it based on DECL_NO_TBAA_P.
(unify_nodes): Do not copy it.
(find_func_aliases): Do not handle GIMPLE_CHANGE_DYNAMIC_TYPE.
(dump_solution_for_var): Do not dump no_tbaa_pruning state.
(set_uids_in_ptset): Do not check it.
(find_what_var_points_to): Likewise.
(compute_tbaa_pruning): Remove.
(compute_points_to_sets): Do not call it.
* tree.c (walk_tree_1): Do not handle CHANGE_DYNAMIC_TYPE_EXPR.
* tree.def (CHANGE_DYNAMIC_TYPE_EXPR): Remove.
* tree.h (CHANGE_DYNAMIC_TYPE_NEW_TYPE): Remove.
(CHANGE_DYNAMIC_TYPE_LOCATION): Likewise.
(DECL_NO_TBAA_P): Likewise.
(struct tree_decl_common): Move no_tbaa_flag to unused flags section.
* omp-low.c (copy_var_decl): Do not copy DECL_NO_TBAA_P.
(expand_omp_atomic_pipeline): Do not set it.
* print-tree.c (print_node): Do not dump it.
* tree-ssa-copyrename.c (copy_rename_partition_coalesce): Remove
redundant check.
cp/
* init.c (avoid_placement_new_aliasing): Remove.
(build_new_1): Do not call it.
Index: gcc/alias.c
===================================================================
*** gcc/alias.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/alias.c 2009-05-20 11:23:40.000000000 +0200
*************** write_dependence_p (const_rtx mem, const
*** 2373,2381 ****
|| MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
return 1;
- if (DIFFERENT_ALIAS_SETS_P (x, mem))
- return 0;
-
/* A read from read-only memory can't conflict with read-write memory. */
if (!writep && MEM_READONLY_P (mem))
return 0;
--- 2373,2378 ----
Index: gcc/cp/init.c
===================================================================
*** gcc/cp/init.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/cp/init.c 2009-05-20 11:23:40.000000000 +0200
*************** build_raw_new_expr (tree placement, tree
*** 1724,1778 ****
return new_expr;
}
- /* Make sure that there are no aliasing issues with T, a placement new
- expression applied to PLACEMENT, by recording the change in dynamic
- type. If placement new is inlined, as it is with libstdc++, and if
- the type of the placement new differs from the type of the
- placement location itself, then alias analysis may think it is OK
- to interchange writes to the location from before the placement new
- and from after the placement new. We have to prevent type-based
- alias analysis from applying. PLACEMENT may be NULL, which means
- that we couldn't capture it in a temporary variable, in which case
- we use a memory clobber. */
-
- static tree
- avoid_placement_new_aliasing (tree t, tree placement)
- {
- tree type_change;
-
- if (processing_template_decl)
- return t;
-
- /* If we are not using type based aliasing, we don't have to do
- anything. */
- if (!flag_strict_aliasing)
- return t;
-
- /* If we have a pointer and a location, record the change in dynamic
- type. Otherwise we need a general memory clobber. */
- if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
- && placement != NULL_TREE
- && TREE_CODE (TREE_TYPE (placement)) == POINTER_TYPE)
- type_change = build_stmt (CHANGE_DYNAMIC_TYPE_EXPR,
- TREE_TYPE (t),
- placement);
- else
- {
- /* Build a memory clobber. */
- type_change = build_stmt (ASM_EXPR,
- build_string (0, ""),
- NULL_TREE,
- NULL_TREE,
- tree_cons (NULL_TREE,
- build_string (6, "memory"),
- NULL_TREE));
-
- ASM_VOLATILE_P (type_change) = 1;
- }
-
- return build2 (COMPOUND_EXPR, TREE_TYPE (t), type_change, t);
- }
-
/* Generate code for a new-expression, including calling the "operator
new" function, initializing the object, and, if an exception occurs
during construction, cleaning up. The arguments are as for
--- 1724,1729 ----
*************** build_new_1 (tree placement, tree type,
*** 1998,2009 ****
/* In the simple case, we can stop now. */
pointer_type = build_pointer_type (type);
if (!cookie_size && !is_initialized)
! {
! rval = build_nop (pointer_type, alloc_call);
! if (placement != NULL)
! rval = avoid_placement_new_aliasing (rval, placement_expr);
! return rval;
! }
/* Store the result of the allocation call in a variable so that we can
use it more than once. */
--- 1949,1955 ----
/* In the simple case, we can stop now. */
pointer_type = build_pointer_type (type);
if (!cookie_size && !is_initialized)
! return build_nop (pointer_type, alloc_call);
/* Store the result of the allocation call in a variable so that we can
use it more than once. */
*************** build_new_1 (tree placement, tree type,
*** 2283,2291 ****
/* A new-expression is never an lvalue. */
gcc_assert (!lvalue_p (rval));
- if (placement != NULL)
- rval = avoid_placement_new_aliasing (rval, placement_expr);
-
return rval;
}
--- 2229,2234 ----
Index: gcc/cfgexpand.c
===================================================================
*** gcc/cfgexpand.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/cfgexpand.c 2009-05-20 11:23:40.000000000 +0200
*************** expand_gimple_basic_block (basic_block b
*** 2100,2106 ****
return new_bb;
}
}
! else if (gimple_code (stmt) != GIMPLE_CHANGE_DYNAMIC_TYPE)
{
def_operand_p def_p;
tree stmt_tree;
--- 2100,2106 ----
return new_bb;
}
}
! else
{
def_operand_p def_p;
tree stmt_tree;
Index: gcc/doc/c-tree.texi
===================================================================
*** gcc/doc/c-tree.texi.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/doc/c-tree.texi 2009-05-20 11:23:40.000000000 +0200
*************** This macro returns the attributes on the
*** 1995,2001 ****
@tindex TARGET_EXPR
@tindex AGGR_INIT_EXPR
@tindex VA_ARG_EXPR
- @tindex CHANGE_DYNAMIC_TYPE_EXPR
@tindex OMP_PARALLEL
@tindex OMP_FOR
@tindex OMP_SECTIONS
--- 1995,2000 ----
*************** mechanism. It represents expressions li
*** 2708,2720 ****
Its @code{TREE_TYPE} yields the tree representation for @code{type} and
its sole argument yields the representation for @code{ap}.
- @item CHANGE_DYNAMIC_TYPE_EXPR
- Indicates the special aliasing required by C++ placement new. It has
- two operands: a type and a location. It means that the dynamic type
- of the location is changing to be the specified type. The alias
- analysis code takes this into account when doing type based alias
- analysis.
-
@item OMP_PARALLEL
Represents @code{#pragma omp parallel [clause1 @dots{} clauseN]}. It
--- 2707,2712 ----
Index: gcc/doc/gimple.texi
===================================================================
*** gcc/doc/gimple.texi.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/doc/gimple.texi 2009-05-20 11:23:40.000000000 +0200
*************** union gimple_statement_d
*** 332,345 ****
The following table briefly describes the GIMPLE instruction set.
! @multitable {@code{GIMPLE_CHANGE_DYNAMIC_TYPE}} {High GIMPLE} {Low GIMPLE}
@item Instruction @tab High GIMPLE @tab Low GIMPLE
@item @code{GIMPLE_ASM} @tab x @tab x
@item @code{GIMPLE_ASSIGN} @tab x @tab x
@item @code{GIMPLE_BIND} @tab x @tab
@item @code{GIMPLE_CALL} @tab x @tab x
@item @code{GIMPLE_CATCH} @tab x @tab
- @item @code{GIMPLE_CHANGE_DYNAMIC_TYPE} @tab x @tab x
@item @code{GIMPLE_COND} @tab x @tab x
@item @code{GIMPLE_EH_FILTER} @tab x @tab
@item @code{GIMPLE_GOTO} @tab x @tab x
--- 332,344 ----
The following table briefly describes the GIMPLE instruction set.
! @multitable {@code{GIMPLE_OMP_SECTIONS_SWITCH}} {High GIMPLE} {Low GIMPLE}
@item Instruction @tab High GIMPLE @tab Low GIMPLE
@item @code{GIMPLE_ASM} @tab x @tab x
@item @code{GIMPLE_ASSIGN} @tab x @tab x
@item @code{GIMPLE_BIND} @tab x @tab
@item @code{GIMPLE_CALL} @tab x @tab x
@item @code{GIMPLE_CATCH} @tab x @tab
@item @code{GIMPLE_COND} @tab x @tab x
@item @code{GIMPLE_EH_FILTER} @tab x @tab
@item @code{GIMPLE_GOTO} @tab x @tab x
*************** Return a deep copy of statement @code{ST
*** 885,891 ****
* @code{GIMPLE_BIND}::
* @code{GIMPLE_CALL}::
* @code{GIMPLE_CATCH}::
- * @code{GIMPLE_CHANGE_DYNAMIC_TYPE}::
* @code{GIMPLE_COND}::
* @code{GIMPLE_EH_FILTER}::
* @code{GIMPLE_LABEL}::
--- 884,889 ----
*************** Set @code{T} to be the set of types hand
*** 1295,1339 ****
Set @code{HANDLER} to be the body of @code{GIMPLE_CATCH} @code{G}.
@end deftypefn
- @node @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
- @subsection @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
- @cindex @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
-
- @deftypefn {GIMPLE function} gimple gimple_build_cdt (tree type, tree ptr)
- Build a @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement. @code{TYPE} is the new
- type for the location @code{PTR}.
- @end deftypefn
-
- @deftypefn {GIMPLE function} tree gimple_cdt_new_type (gimple g)
- Return the new type set by @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement
- @code{G}.
- @end deftypefn
-
- @deftypefn {GIMPLE function} tree *gimple_cdt_new_type_ptr (gimple g)
- Return a pointer to the new type set by
- @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}.
- @end deftypefn
-
- @deftypefn {GIMPLE function} void gimple_cdt_set_new_type (gimple g, tree new_type)
- Set @code{NEW_TYPE} to be the type returned by
- @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}.
- @end deftypefn
-
- @deftypefn {GIMPLE function} tree gimple_cdt_location (gimple g)
- Return the location affected by @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
- statement @code{G}.
- @end deftypefn
-
- @deftypefn {GIMPLE function} tree *gimple_cdt_location_ptr (gimple g)
- Return a pointer to the location affected by
- @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}.
- @end deftypefn
-
- @deftypefn {GIMPLE function} void gimple_cdt_set_location (gimple g, tree ptr)
- Set @code{PTR} to be the location affected by @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
- statement @code{G}.
- @end deftypefn
-
@node @code{GIMPLE_COND}
@subsection @code{GIMPLE_COND}
--- 1293,1298 ----
Index: gcc/expr.c
===================================================================
*** gcc/expr.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/expr.c 2009-05-20 11:23:40.000000000 +0200
*************** expand_expr_real_1 (tree exp, rtx target
*** 9298,9310 ****
/* Lowered by gimplify.c. */
gcc_unreachable ();
- case CHANGE_DYNAMIC_TYPE_EXPR:
- /* This is ignored at the RTL level. The tree level set
- DECL_POINTER_ALIAS_SET of any variable to be 0, which is
- overkill for the RTL layer but is all that we can
- represent. */
- return const0_rtx;
-
case EXC_PTR_EXPR:
return get_exception_pointer ();
--- 9298,9303 ----
Index: gcc/gimple-low.c
===================================================================
*** gcc/gimple-low.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/gimple-low.c 2009-05-20 11:23:40.000000000 +0200
*************** lower_stmt (gimple_stmt_iterator *gsi, s
*** 368,374 ****
case GIMPLE_PREDICT:
case GIMPLE_LABEL:
case GIMPLE_SWITCH:
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
case GIMPLE_OMP_FOR:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SECTIONS_SWITCH:
--- 368,373 ----
Index: gcc/gimple-pretty-print.c
===================================================================
*** gcc/gimple-pretty-print.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/gimple-pretty-print.c 2009-05-20 11:23:40.000000000 +0200
*************** dump_gimple_omp_atomic_store (pretty_pri
*** 1324,1350 ****
}
}
- /* Dump a GIMPLE_CHANGE_DYNAMIC_TYPE statement GS. BUFFER, SPC and
- FLAGS are as in dump_gimple_stmt. */
-
- static void
- dump_gimple_cdt (pretty_printer *buffer, gimple gs, int spc, int flags)
- {
- if (flags & TDF_RAW)
- dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T>", gs,
- gimple_cdt_new_type (gs), gimple_cdt_location (gs));
- else
- {
- pp_string (buffer, "<<<change_dynamic_type (");
- dump_generic_node (buffer, gimple_cdt_new_type (gs), spc + 2, flags,
- false);
- pp_string (buffer, ") ");
- dump_generic_node (buffer, gimple_cdt_location (gs), spc + 2, flags,
- false);
- pp_string (buffer, ")>>>");
- }
- }
-
/* Dump all the memory operands for statement GS. BUFFER, SPC and
FLAGS are as in dump_gimple_stmt. */
--- 1324,1329 ----
*************** dump_gimple_stmt (pretty_printer *buffer
*** 1508,1517 ****
dump_gimple_omp_critical (buffer, gs, spc, flags);
break;
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- dump_gimple_cdt (buffer, gs, spc, flags);
- break;
-
case GIMPLE_CATCH:
dump_gimple_catch (buffer, gs, spc, flags);
break;
--- 1487,1492 ----
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/gimple.c 2009-05-20 11:23:40.000000000 +0200
*************** gss_for_code (enum gimple_code code)
*** 102,108 ****
case GIMPLE_COND:
case GIMPLE_GOTO:
case GIMPLE_LABEL:
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
case GIMPLE_SWITCH: return GSS_WITH_OPS;
case GIMPLE_ASM: return GSS_ASM;
case GIMPLE_BIND: return GSS_BIND;
--- 102,107 ----
*************** gimple_size (enum gimple_code code)
*** 190,197 ****
return sizeof (struct gimple_statement_omp_atomic_store);
case GIMPLE_WITH_CLEANUP_EXPR:
return sizeof (struct gimple_statement_wce);
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- return sizeof (struct gimple_statement_with_ops);
case GIMPLE_PREDICT:
return sizeof (struct gimple_statement_base);
default:
--- 189,194 ----
*************** gimple_build_omp_single (gimple_seq body
*** 1042,1061 ****
}
- /* Build a GIMPLE_CHANGE_DYNAMIC_TYPE statement. TYPE is the new type
- for the location PTR. */
-
- gimple
- gimple_build_cdt (tree type, tree ptr)
- {
- gimple p = gimple_build_with_ops (GIMPLE_CHANGE_DYNAMIC_TYPE, ERROR_MARK, 2);
- gimple_cdt_set_new_type (p, type);
- gimple_cdt_set_location (p, ptr);
-
- return p;
- }
-
-
/* Build a GIMPLE_OMP_ATOMIC_LOAD statement. */
gimple
--- 1039,1044 ----
*************** walk_gimple_op (gimple stmt, walk_tree_f
*** 1460,1475 ****
return ret;
break;
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- ret = walk_tree (gimple_cdt_location_ptr (stmt), callback_op, wi, pset);
- if (ret)
- return ret;
-
- ret = walk_tree (gimple_cdt_new_type_ptr (stmt), callback_op, wi, pset);
- if (ret)
- return ret;
- break;
-
case GIMPLE_ASM:
ret = walk_gimple_asm (stmt, callback_op, wi);
if (ret)
--- 1443,1448 ----
*************** is_gimple_stmt (tree t)
*** 2749,2755 ****
case TRY_FINALLY_EXPR:
case EH_FILTER_EXPR:
case CATCH_EXPR:
- case CHANGE_DYNAMIC_TYPE_EXPR:
case ASM_EXPR:
case RESX_EXPR:
case STATEMENT_LIST:
--- 2722,2727 ----
*************** walk_stmt_load_store_addr_ops (gimple st
*** 3254,3261 ****
}
else if (visit_addr
&& (is_gimple_assign (stmt)
! || gimple_code (stmt) == GIMPLE_COND
! || gimple_code (stmt) == GIMPLE_CHANGE_DYNAMIC_TYPE))
{
for (i = 0; i < gimple_num_ops (stmt); ++i)
if (gimple_op (stmt, i)
--- 3226,3232 ----
}
else if (visit_addr
&& (is_gimple_assign (stmt)
! || gimple_code (stmt) == GIMPLE_COND))
{
for (i = 0; i < gimple_num_ops (stmt); ++i)
if (gimple_op (stmt, i)
Index: gcc/gimple.def
===================================================================
*** gcc/gimple.def.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/gimple.def 2009-05-20 11:23:40.000000000 +0200
*************** DEFGSCODE(GIMPLE_LABEL, "gimple_label",
*** 78,94 ****
They must be CASE_LABEL_EXPR nodes. */
DEFGSCODE(GIMPLE_SWITCH, "gimple_switch", struct gimple_statement_with_ops)
- /* GIMPLE_CHANGE_DYNAMIC_TYPE indicates a change in the dynamic type
- of a memory location. This has no value and generates no
- executable code. It is only used for type based alias analysis.
- This is generated by C++ placement new and it's a direct
- translation from CHANGE_DYNAMIC_TYPE_EXPR. The first operand
- (gimple_cdt_new_type) is the new type. The second operand
- (gimple_cdt_location) is the location (pointer) whose type is being
- changed. */
- DEFGSCODE(GIMPLE_CHANGE_DYNAMIC_TYPE, "gimple_change_dynamic_type",
- struct gimple_statement_with_ops)
-
/* IMPORTANT.
Do not rearrange the codes between GIMPLE_ASSIGN and GIMPLE_RETURN.
--- 78,83 ----
Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/gimple.h 2009-05-20 11:23:40.000000000 +0200
*************** gimple_nop_p (const_gimple g)
*** 4106,4174 ****
}
- /* Return the new type set by GIMPLE_CHANGE_DYNAMIC_TYPE statement GS. */
-
- static inline tree
- gimple_cdt_new_type (gimple gs)
- {
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- return gimple_op (gs, 1);
- }
-
- /* Return a pointer to the new type set by GIMPLE_CHANGE_DYNAMIC_TYPE
- statement GS. */
-
- static inline tree *
- gimple_cdt_new_type_ptr (gimple gs)
- {
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- return gimple_op_ptr (gs, 1);
- }
-
- /* Set NEW_TYPE to be the type returned by GIMPLE_CHANGE_DYNAMIC_TYPE
- statement GS. */
-
- static inline void
- gimple_cdt_set_new_type (gimple gs, tree new_type)
- {
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- gcc_assert (TREE_CODE_CLASS (TREE_CODE (new_type)) == tcc_type);
- gimple_set_op (gs, 1, new_type);
- }
-
-
- /* Return the location affected by GIMPLE_CHANGE_DYNAMIC_TYPE statement GS. */
-
- static inline tree
- gimple_cdt_location (gimple gs)
- {
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- return gimple_op (gs, 0);
- }
-
-
- /* Return a pointer to the location affected by GIMPLE_CHANGE_DYNAMIC_TYPE
- statement GS. */
-
- static inline tree *
- gimple_cdt_location_ptr (gimple gs)
- {
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- return gimple_op_ptr (gs, 0);
- }
-
-
- /* Set PTR to be the location affected by GIMPLE_CHANGE_DYNAMIC_TYPE
- statement GS. */
-
- static inline void
- gimple_cdt_set_location (gimple gs, tree ptr)
- {
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- gimple_set_op (gs, 0, ptr);
- }
-
-
/* Return the predictor of GIMPLE_PREDICT statement GS. */
static inline enum br_predictor
--- 4106,4111 ----
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/gimplify.c 2009-05-20 11:23:40.000000000 +0200
*************** gimplify_expr (tree *expr_p, gimple_seq
*** 6838,6856 ****
break;
}
- case CHANGE_DYNAMIC_TYPE_EXPR:
- {
- gimple cdt;
-
- ret = gimplify_expr (&CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p),
- pre_p, post_p, is_gimple_reg, fb_lvalue);
- cdt = gimple_build_cdt (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*expr_p),
- CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p));
- gimplify_seq_add_stmt (pre_p, cdt);
- ret = GS_ALL_DONE;
- }
- break;
-
case OBJ_TYPE_REF:
{
enum gimplify_status r0, r1;
--- 6838,6843 ----
Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-cfg.c 2009-05-20 11:23:40.000000000 +0200
*************** remove_useless_stmts_1 (gimple_stmt_iter
*** 2045,2062 ****
}
break;
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- /* If we do not optimize remove GIMPLE_CHANGE_DYNAMIC_TYPE as
- expansion is confused about them and we only remove them
- during alias computation otherwise. */
- if (!optimize)
- {
- data->last_was_goto = false;
- gsi_remove (gsi, false);
- break;
- }
- /* Fallthru. */
-
default:
data->last_was_goto = false;
gsi_next (gsi);
--- 2045,2050 ----
*************** verify_types_in_gimple_stmt (gimple stmt
*** 4038,4047 ****
case GIMPLE_ASM:
return false;
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- return (!is_gimple_val (gimple_cdt_location (stmt))
- || !POINTER_TYPE_P (TREE_TYPE (gimple_cdt_location (stmt))));
-
case GIMPLE_PHI:
return verify_gimple_phi (stmt);
--- 4026,4031 ----
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-inline.c 2009-05-20 11:23:40.000000000 +0200
*************** estimate_num_insns (gimple stmt, eni_wei
*** 3072,3078 ****
case GIMPLE_NOP:
case GIMPLE_PHI:
case GIMPLE_RETURN:
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
case GIMPLE_PREDICT:
return 0;
--- 3072,3077 ----
*************** expand_call_inline (basic_block bb, gimp
*** 3429,3441 ****
/* Declare the return variable for the function. */
retvar = declare_return_variable (id, return_slot, modify_dest, &use_retvar);
- if (DECL_IS_OPERATOR_NEW (fn))
- {
- gcc_assert (TREE_CODE (retvar) == VAR_DECL
- && POINTER_TYPE_P (TREE_TYPE (retvar)));
- DECL_NO_TBAA_P (retvar) = 1;
- }
-
/* Add local vars in this inlined callee to caller. */
t_step = id->src_cfun->local_decls;
for (; t_step; t_step = TREE_CHAIN (t_step))
--- 3428,3433 ----
*************** copy_decl_to_var (tree decl, copy_body_d
*** 4192,4198 ****
TREE_READONLY (copy) = TREE_READONLY (decl);
TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
- DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (decl);
return copy_decl_for_dup_finish (id, decl, copy);
}
--- 4184,4189 ----
*************** copy_result_decl_to_var (tree decl, copy
*** 4219,4225 ****
{
TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
- DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (decl);
}
return copy_decl_for_dup_finish (id, decl, copy);
--- 4210,4215 ----
Index: gcc/tree-pretty-print.c
===================================================================
*** gcc/tree-pretty-print.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-pretty-print.c 2009-05-20 11:23:40.000000000 +0200
*************** dump_generic_node (pretty_printer *buffe
*** 1569,1585 ****
is_expr = false;
break;
- case CHANGE_DYNAMIC_TYPE_EXPR:
- pp_string (buffer, "<<<change_dynamic_type (");
- dump_generic_node (buffer, CHANGE_DYNAMIC_TYPE_NEW_TYPE (node), spc + 2,
- flags, false);
- pp_string (buffer, ") ");
- dump_generic_node (buffer, CHANGE_DYNAMIC_TYPE_LOCATION (node), spc + 2,
- flags, false);
- pp_string (buffer, ")>>>");
- is_expr = false;
- break;
-
case LABEL_EXPR:
op0 = TREE_OPERAND (node, 0);
/* If this is for break or continue, don't bother printing it. */
--- 1569,1574 ----
Index: gcc/tree-ssa-dce.c
===================================================================
*** gcc/tree-ssa-dce.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-ssa-dce.c 2009-05-20 11:23:40.000000000 +0200
*************** mark_stmt_if_obviously_necessary (gimple
*** 295,301 ****
case GIMPLE_ASM:
case GIMPLE_RESX:
case GIMPLE_RETURN:
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
mark_stmt_necessary (stmt, true);
return;
--- 295,300 ----
Index: gcc/tree-ssa-operands.c
===================================================================
*** gcc/tree-ssa-operands.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-ssa-operands.c 2009-05-20 11:23:40.000000000 +0200
*************** get_expr_operands (gimple stmt, tree *ex
*** 1009,1017 ****
return;
}
- case CHANGE_DYNAMIC_TYPE_EXPR:
- gcc_unreachable ();
-
case FUNCTION_DECL:
case LABEL_DECL:
case CONST_DECL:
--- 1009,1014 ----
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-ssa-structalias.c 2009-05-20 11:23:40.000000000 +0200
*************** struct variable_info
*** 226,235 ****
/* True if this is a heap variable. */
unsigned int is_heap_var:1;
- /* True if we may not use TBAA to prune references to this
- variable. This is used for C++ placement new. */
- unsigned int no_tbaa_pruning : 1;
-
/* True if this field may contain pointers. */
unsigned int may_have_pointers : 1;
--- 226,231 ----
*************** static varinfo_t
*** 360,366 ****
new_var_info (tree t, unsigned int id, const char *name)
{
varinfo_t ret = (varinfo_t) pool_alloc (variable_info_pool);
- tree var;
ret->id = id;
ret->name = name;
--- 356,361 ----
*************** new_var_info (tree t, unsigned int id, c
*** 371,382 ****
ret->is_unknown_size_var = false;
ret->is_full_var = false;
ret->may_have_pointers = true;
- var = t;
- if (TREE_CODE (var) == SSA_NAME)
- var = SSA_NAME_VAR (var);
- ret->no_tbaa_pruning = (DECL_P (var)
- && POINTER_TYPE_P (TREE_TYPE (var))
- && DECL_NO_TBAA_P (var));
ret->solution = BITMAP_ALLOC (&pta_obstack);
ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
ret->next = NULL;
--- 366,371 ----
*************** unify_nodes (constraint_graph_t graph, u
*** 1425,1433 ****
merge_graph_nodes (graph, to, from);
merge_node_constraints (graph, to, from);
- if (get_varinfo (from)->no_tbaa_pruning)
- get_varinfo (to)->no_tbaa_pruning = true;
-
/* Mark TO as changed if FROM was changed. If TO was already marked
as changed, decrease the changed count. */
--- 1414,1419 ----
*************** find_func_aliases (gimple origt)
*** 3725,3738 ****
}
}
}
- else if (gimple_code (t) == GIMPLE_CHANGE_DYNAMIC_TYPE)
- {
- unsigned int j;
-
- get_constraint_for (gimple_cdt_location (t), &lhsc);
- for (j = 0; VEC_iterate (ce_s, lhsc, j, c); ++j)
- get_varinfo (c->var)->no_tbaa_pruning = true;
- }
stmt_escape_type = is_escape_site (t);
if (stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
--- 3711,3716 ----
*************** dump_solution_for_var (FILE *file, unsig
*** 4444,4453 ****
{
fprintf (file, "%s ", get_varinfo (i)->name);
}
! fprintf (file, "}");
! if (vi->no_tbaa_pruning)
! fprintf (file, " no-tbaa-pruning");
! fprintf (file, "\n");
}
}
--- 4422,4428 ----
{
fprintf (file, "%s ", get_varinfo (i)->name);
}
! fprintf (file, "}\n");
}
}
*************** shared_bitmap_add (bitmap pt_vars)
*** 4628,4646 ****
}
! /* Set bits in INTO corresponding to the variable uids in solution set FROM.
! If MEM_ALIAS_SET is not zero, we also use type based alias analysis to
! prune the points-to sets with this alias-set.
! Returns the number of pruned variables and updates the vars_contains_global
! member of *PT . */
!
! static unsigned
! set_uids_in_ptset (bitmap into, bitmap from,
! alias_set_type mem_alias_set, struct pt_solution *pt)
{
unsigned int i;
bitmap_iterator bi;
- unsigned pruned = 0;
EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
{
--- 4603,4615 ----
}
! /* Set bits in INTO corresponding to the variable uids in solution set FROM. */
!
! static void
! set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
{
unsigned int i;
bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
{
*************** set_uids_in_ptset (bitmap into, bitmap f
*** 4655,4676 ****
|| TREE_CODE (vi->decl) == PARM_DECL
|| TREE_CODE (vi->decl) == RESULT_DECL)
{
- /* Don't type prune artificial vars or points-to sets
- for pointers that have not been dereferenced or with
- type-based pruning disabled. */
- if (!vi->is_artificial_var
- && !vi->no_tbaa_pruning
- && mem_alias_set != 0)
- {
- alias_set_type var_alias_set = get_alias_set (vi->decl);
- if (mem_alias_set != var_alias_set
- && !alias_set_subset_of (mem_alias_set, var_alias_set))
- {
- ++pruned;
- continue;
- }
- }
-
/* Add the decl to the points-to set. Note that the points-to
set contains global variables. */
bitmap_set_bit (into, DECL_UID (vi->decl));
--- 4624,4629 ----
*************** set_uids_in_ptset (bitmap into, bitmap f
*** 4678,4790 ****
pt->vars_contains_global = true;
}
}
-
- return pruned;
}
static bool have_alias_info = false;
! /* Emit a note for the pointer initialization point DEF. */
static void
! emit_pointer_definition (tree ptr, bitmap visited)
{
! gimple def = SSA_NAME_DEF_STMT (ptr);
! if (gimple_code (def) == GIMPLE_PHI)
! {
! use_operand_p argp;
! ssa_op_iter oi;
!
! FOR_EACH_PHI_ARG (argp, def, oi, SSA_OP_USE)
! {
! tree arg = USE_FROM_PTR (argp);
! if (TREE_CODE (arg) == SSA_NAME)
! {
! if (bitmap_set_bit (visited, SSA_NAME_VERSION (arg)))
! emit_pointer_definition (arg, visited);
! }
! else
! inform (0, "initialized from %qE", arg);
! }
! }
! else if (!gimple_nop_p (def))
! inform (gimple_location (def), "initialized from here");
! }
!
! /* Emit a strict aliasing warning for dereferencing the pointer PTR. */
!
! static void
! emit_alias_warning (tree ptr)
! {
! gimple use;
! imm_use_iterator ui;
! bool warned = false;
!
! FOR_EACH_IMM_USE_STMT (use, ui, ptr)
! {
! tree deref = NULL_TREE;
!
! if (gimple_has_lhs (use))
! {
! tree lhs = get_base_address (gimple_get_lhs (use));
! if (lhs
! && INDIRECT_REF_P (lhs)
! && TREE_OPERAND (lhs, 0) == ptr)
! deref = lhs;
! }
! if (gimple_assign_single_p (use))
! {
! tree rhs = get_base_address (gimple_assign_rhs1 (use));
! if (rhs
! && INDIRECT_REF_P (rhs)
! && TREE_OPERAND (rhs, 0) == ptr)
! deref = rhs;
! }
! else if (is_gimple_call (use))
! {
! unsigned i;
! for (i = 0; i < gimple_call_num_args (use); ++i)
! {
! tree op = get_base_address (gimple_call_arg (use, i));
! if (op
! && INDIRECT_REF_P (op)
! && TREE_OPERAND (op, 0) == ptr)
! deref = op;
! }
! }
! if (deref
! && !TREE_NO_WARNING (deref))
! {
! TREE_NO_WARNING (deref) = 1;
! warned |= warning_at (gimple_location (use), OPT_Wstrict_aliasing,
! "dereferencing pointer %qD does break "
! "strict-aliasing rules", SSA_NAME_VAR (ptr));
! }
! }
! if (warned)
! {
! bitmap visited = BITMAP_ALLOC (NULL);
! emit_pointer_definition (ptr, visited);
! BITMAP_FREE (visited);
! }
! }
!
! /* Compute the points-to solution *PT for the variable VI.
! Prunes the points-to set based on TBAA rules if DO_TBAA_PRUNING
! is true. Returns the number of TBAA pruned variables from the
! points-to set. */
!
! static unsigned int
! find_what_var_points_to (varinfo_t vi, struct pt_solution *pt,
! bool do_tbaa_pruning)
! {
! unsigned int i, pruned;
bitmap_iterator bi;
bitmap finished_solution;
bitmap result;
tree ptr = vi->decl;
- alias_set_type mem_alias_set;
memset (pt, 0, sizeof (struct pt_solution));
--- 4631,4651 ----
pt->vars_contains_global = true;
}
}
}
static bool have_alias_info = false;
! /* Compute the points-to solution *PT for the variable VI. */
static void
! find_what_var_points_to (varinfo_t vi, struct pt_solution *pt)
{
! unsigned int i;
bitmap_iterator bi;
bitmap finished_solution;
bitmap result;
tree ptr = vi->decl;
memset (pt, 0, sizeof (struct pt_solution));
*************** find_what_var_points_to (varinfo_t vi, s
*** 4821,4827 ****
/* Instead of doing extra work, simply do not create
elaborate points-to information for pt_anything pointers. */
if (pt->anything)
! return 0;
/* Share the final set of variables when possible. */
finished_solution = BITMAP_GGC_ALLOC ();
--- 4682,4688 ----
/* Instead of doing extra work, simply do not create
elaborate points-to information for pt_anything pointers. */
if (pt->anything)
! return;
/* Share the final set of variables when possible. */
finished_solution = BITMAP_GGC_ALLOC ();
*************** find_what_var_points_to (varinfo_t vi, s
*** 4830,4844 ****
if (TREE_CODE (ptr) == SSA_NAME)
ptr = SSA_NAME_VAR (ptr);
! /* If the pointer decl is marked that no TBAA is to be applied,
! do not do tbaa pruning. */
! if (!do_tbaa_pruning
! || DECL_NO_TBAA_P (ptr))
! mem_alias_set = 0;
! else
! mem_alias_set = get_deref_alias_set (ptr);
! pruned = set_uids_in_ptset (finished_solution, vi->solution,
! mem_alias_set, pt);
result = shared_bitmap_lookup (finished_solution);
if (!result)
{
--- 4691,4697 ----
if (TREE_CODE (ptr) == SSA_NAME)
ptr = SSA_NAME_VAR (ptr);
! set_uids_in_ptset (finished_solution, vi->solution, pt);
result = shared_bitmap_lookup (finished_solution);
if (!result)
{
*************** find_what_var_points_to (varinfo_t vi, s
*** 4850,4867 ****
pt->vars = result;
bitmap_clear (finished_solution);
}
-
- return pruned;
}
! /* Given a pointer variable P, fill in its points-to set. Apply
! type-based pruning if IS_DEREFERENCED is true. */
static void
! find_what_p_points_to (tree p, bool is_dereferenced)
{
struct ptr_info_def *pi;
- unsigned int pruned;
tree lookup_p = p;
varinfo_t vi;
--- 4703,4716 ----
pt->vars = result;
bitmap_clear (finished_solution);
}
}
! /* Given a pointer variable P, fill in its points-to set. */
static void
! find_what_p_points_to (tree p)
{
struct ptr_info_def *pi;
tree lookup_p = p;
varinfo_t vi;
*************** find_what_p_points_to (tree p, bool is_d
*** 4877,4899 ****
return;
pi = get_ptr_info (p);
! pruned = find_what_var_points_to (vi, &pi->pt, is_dereferenced);
!
! if (!(pi->pt.anything || pi->pt.nonlocal || pi->pt.escaped)
! && bitmap_empty_p (pi->pt.vars)
! && pruned > 0
! && is_dereferenced
! && warn_strict_aliasing > 0
! && !SSA_NAME_IS_DEFAULT_DEF (p))
! {
! if (dump_file && dump_flags & TDF_DETAILS)
! {
! fprintf (dump_file, "alias warning for ");
! print_generic_expr (dump_file, p, 0);
! fprintf (dump_file, "\n");
! }
! emit_alias_warning (p);
! }
}
--- 4726,4732 ----
return;
pi = get_ptr_info (p);
! find_what_var_points_to (vi, &pi->pt);
}
*************** remove_preds_and_fake_succs (constraint_
*** 5372,5510 ****
bitmap_obstack_release (&predbitmap_obstack);
}
- /* Compute the set of variables we can't TBAA prune. */
-
- static void
- compute_tbaa_pruning (void)
- {
- unsigned int size = VEC_length (varinfo_t, varmap);
- unsigned int i;
- bool any;
-
- changed_count = 0;
- changed = sbitmap_alloc (size);
- sbitmap_zero (changed);
-
- /* Mark all initial no_tbaa_pruning nodes as changed. */
- any = false;
- for (i = 0; i < size; ++i)
- {
- varinfo_t ivi = get_varinfo (i);
-
- if (find (i) == i && ivi->no_tbaa_pruning)
- {
- any = true;
- if ((graph->succs[i] && !bitmap_empty_p (graph->succs[i]))
- || VEC_length (constraint_t, graph->complex[i]) > 0)
- {
- SET_BIT (changed, i);
- ++changed_count;
- }
- }
- }
-
- while (changed_count > 0)
- {
- struct topo_info *ti = init_topo_info ();
- ++stats.iterations;
-
- compute_topo_order (graph, ti);
-
- while (VEC_length (unsigned, ti->topo_order) != 0)
- {
- bitmap_iterator bi;
-
- i = VEC_pop (unsigned, ti->topo_order);
-
- /* If this variable is not a representative, skip it. */
- if (find (i) != i)
- continue;
-
- /* If the node has changed, we need to process the complex
- constraints and outgoing edges again. */
- if (TEST_BIT (changed, i))
- {
- unsigned int j;
- constraint_t c;
- VEC(constraint_t,heap) *complex = graph->complex[i];
-
- RESET_BIT (changed, i);
- --changed_count;
-
- /* Process the complex copy constraints. */
- for (j = 0; VEC_iterate (constraint_t, complex, j, c); ++j)
- {
- if (c->lhs.type == SCALAR && c->rhs.type == SCALAR)
- {
- varinfo_t lhsvi = get_varinfo (find (c->lhs.var));
-
- if (!lhsvi->no_tbaa_pruning)
- {
- lhsvi->no_tbaa_pruning = true;
- if (!TEST_BIT (changed, lhsvi->id))
- {
- SET_BIT (changed, lhsvi->id);
- ++changed_count;
- }
- }
- }
- }
-
- /* Propagate to all successors. */
- EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i], 0, j, bi)
- {
- unsigned int to = find (j);
- varinfo_t tovi = get_varinfo (to);
-
- /* Don't propagate to ourselves. */
- if (to == i)
- continue;
-
- if (!tovi->no_tbaa_pruning)
- {
- tovi->no_tbaa_pruning = true;
- if (!TEST_BIT (changed, to))
- {
- SET_BIT (changed, to);
- ++changed_count;
- }
- }
- }
- }
- }
-
- free_topo_info (ti);
- }
-
- sbitmap_free (changed);
-
- if (any)
- {
- for (i = 0; i < size; ++i)
- {
- varinfo_t ivi = get_varinfo (i);
- varinfo_t ivip = get_varinfo (find (i));
-
- if (ivip->no_tbaa_pruning)
- {
- tree var = ivi->decl;
-
- if (TREE_CODE (var) == SSA_NAME)
- var = SSA_NAME_VAR (var);
-
- if (POINTER_TYPE_P (TREE_TYPE (var)))
- {
- DECL_NO_TBAA_P (var) = 1;
-
- /* Tell the RTL layer that this pointer can alias
- anything. */
- DECL_POINTER_ALIAS_SET (var) = 0;
- }
- }
- }
- }
- }
-
/* Initialize the heapvar for statement mapping. */
static void
--- 5205,5210 ----
*************** compute_points_to_sets (void)
*** 5534,5540 ****
struct scc_info *si;
basic_block bb;
unsigned i;
- sbitmap dereferenced_ptrs;
timevar_push (TV_TREE_PTA);
--- 5234,5239 ----
*************** compute_points_to_sets (void)
*** 5543,5553 ****
intra_create_variable_infos ();
- /* A bitmap of SSA_NAME pointers that are dereferenced. This is
- used to track which points-to sets may be TBAA pruned. */
- dereferenced_ptrs = sbitmap_alloc (num_ssa_names);
- sbitmap_zero (dereferenced_ptrs);
-
/* Now walk all statements and derive aliases. */
FOR_EACH_BB (bb)
{
--- 5242,5247 ----
*************** compute_points_to_sets (void)
*** 5564,5594 ****
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
- use_operand_p use_p;
- ssa_op_iter iter;
-
- /* Mark dereferenced pointers. This is used by TBAA pruning
- of the points-to sets and the alias warning machinery. */
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
- {
- unsigned num_uses, num_loads, num_stores;
- tree op = USE_FROM_PTR (use_p);
-
- if (!POINTER_TYPE_P (TREE_TYPE (op)))
- continue;
-
- /* Determine whether OP is a dereferenced pointer. */
- count_uses_and_derefs (op, stmt,
- &num_uses, &num_loads, &num_stores);
- if (num_loads + num_stores > 0)
- SET_BIT (dereferenced_ptrs, SSA_NAME_VERSION (op));
- }
find_func_aliases (stmt);
}
}
-
if (dump_file)
{
fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n");
--- 5258,5268 ----
*************** compute_points_to_sets (void)
*** 5642,5656 ****
solve_graph (graph);
- compute_tbaa_pruning ();
-
if (dump_file)
dump_sa_points_to_info (dump_file);
/* Compute the points-to sets for ESCAPED and CALLUSED used for
call-clobber analysis. */
! find_what_var_points_to (var_escaped, &cfun->gimple_df->escaped, false);
! find_what_var_points_to (var_callused, &cfun->gimple_df->callused, false);
/* Make sure the ESCAPED solution (which is used as placeholder in
other solutions) does not reference itself. This simplifies
--- 5316,5328 ----
solve_graph (graph);
if (dump_file)
dump_sa_points_to_info (dump_file);
/* Compute the points-to sets for ESCAPED and CALLUSED used for
call-clobber analysis. */
! find_what_var_points_to (var_escaped, &cfun->gimple_df->escaped);
! find_what_var_points_to (var_callused, &cfun->gimple_df->callused);
/* Make sure the ESCAPED solution (which is used as placeholder in
other solutions) does not reference itself. This simplifies
*************** compute_points_to_sets (void)
*** 5663,5671 ****
tree ptr = ssa_name (i);
if (ptr
&& POINTER_TYPE_P (TREE_TYPE (ptr)))
! find_what_p_points_to (ptr, TEST_BIT (dereferenced_ptrs, i));
}
- sbitmap_free (dereferenced_ptrs);
timevar_pop (TV_TREE_PTA);
--- 5335,5342 ----
tree ptr = ssa_name (i);
if (ptr
&& POINTER_TYPE_P (TREE_TYPE (ptr)))
! find_what_p_points_to (ptr);
}
timevar_pop (TV_TREE_PTA);
Index: gcc/tree.c
===================================================================
*** gcc/tree.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree.c 2009-05-20 11:23:40.000000000 +0200
*************** walk_tree_1 (tree *tp, walk_tree_fn func
*** 8887,8896 ****
WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len));
}
- case CHANGE_DYNAMIC_TYPE_EXPR:
- WALK_SUBTREE (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*tp));
- WALK_SUBTREE_TAIL (CHANGE_DYNAMIC_TYPE_LOCATION (*tp));
-
case DECL_EXPR:
/* If this is a TYPE_DECL, walk into the fields of the type that it's
defining. We only want to walk into these fields of a type in this
--- 8887,8892 ----
Index: gcc/tree.def
===================================================================
*** gcc/tree.def.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree.def 2009-05-20 11:23:40.000000000 +0200
*************** DEFTREECODE (CATCH_EXPR, "catch_expr", t
*** 913,927 ****
expanding. */
DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", tcc_statement, 2)
- /* Indicates a change in the dynamic type of a memory location. This
- has no value and generates no executable code. It is only used for
- type based alias analysis. This is generated by C++ placement new.
- CHANGE_DYNAMIC_TYPE_NEW_TYPE, the first operand, is the new type.
- CHANGE_DYNAMIC_TYPE_LOCATION, the second operand, is the location
- whose type is being changed. */
- DEFTREECODE (CHANGE_DYNAMIC_TYPE_EXPR, "change_dynamic_type_expr",
- tcc_statement, 2)
-
/* Node used for describing a property that is known at compile
time. */
DEFTREECODE (SCEV_KNOWN, "scev_known", tcc_expression, 0)
--- 913,918 ----
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree.h 2009-05-20 11:23:40.000000000 +0200
*************** extern void protected_set_expr_location
*** 1648,1659 ****
#define EH_FILTER_MUST_NOT_THROW(NODE) \
(EH_FILTER_EXPR_CHECK (NODE)->base.static_flag)
- /* CHANGE_DYNAMIC_TYPE_EXPR accessors. */
- #define CHANGE_DYNAMIC_TYPE_NEW_TYPE(NODE) \
- TREE_OPERAND (CHANGE_DYNAMIC_TYPE_EXPR_CHECK (NODE), 0)
- #define CHANGE_DYNAMIC_TYPE_LOCATION(NODE) \
- TREE_OPERAND (CHANGE_DYNAMIC_TYPE_EXPR_CHECK (NODE), 1)
-
/* OBJ_TYPE_REF accessors. */
#define OBJ_TYPE_REF_EXPR(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 0)
#define OBJ_TYPE_REF_OBJECT(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 1)
--- 1648,1653 ----
*************** struct GTY(()) tree_decl_minimal {
*** 2605,2615 ****
#define DECL_GIMPLE_REG_P(DECL) \
DECL_COMMON_CHECK (DECL)->decl_common.gimple_reg_flag
- /* For a DECL with pointer type, this is set if Type Based Alias
- Analysis should not be applied to this DECL. */
- #define DECL_NO_TBAA_P(DECL) \
- DECL_COMMON_CHECK (DECL)->decl_common.no_tbaa_flag
-
struct GTY(()) tree_decl_common {
struct tree_decl_minimal common;
tree size;
--- 2599,2604 ----
*************** struct GTY(()) tree_decl_common {
*** 2649,2660 ****
/* Logically, these two would go in a theoretical base shared by var and
parm decl. */
unsigned gimple_reg_flag : 1;
- /* In a DECL with pointer type, set if no TBAA should be done. */
- unsigned no_tbaa_flag : 1;
/* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_BY_REFERENCE. */
unsigned decl_by_reference_flag : 1;
/* Padding so that 'off_align' can be on a 32-bit boundary. */
! unsigned decl_common_unused : 1;
/* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
unsigned int off_align : 8;
--- 2638,2647 ----
/* Logically, these two would go in a theoretical base shared by var and
parm decl. */
unsigned gimple_reg_flag : 1;
/* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_BY_REFERENCE. */
unsigned decl_by_reference_flag : 1;
/* Padding so that 'off_align' can be on a 32-bit boundary. */
! unsigned decl_common_unused : 2;
/* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
unsigned int off_align : 8;
Index: gcc/omp-low.c
===================================================================
*** gcc/omp-low.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/omp-low.c 2009-05-20 11:23:40.000000000 +0200
*************** copy_var_decl (tree var, tree name, tree
*** 812,818 ****
TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
- DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
DECL_CONTEXT (copy) = DECL_CONTEXT (var);
--- 812,817 ----
*************** expand_omp_atomic_pipeline (basic_block
*** 5010,5016 ****
false, NULL_TREE, true, GSI_SAME_STMT);
stmt = gimple_build_assign (iaddr, iaddr_val);
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
- DECL_NO_TBAA_P (iaddr) = 1;
DECL_POINTER_ALIAS_SET (iaddr) = 0;
loadedi = create_tmp_var (itype, NULL);
if (gimple_in_ssa_p (cfun))
--- 5009,5014 ----
Index: gcc/print-tree.c
===================================================================
*** gcc/print-tree.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/print-tree.c 2009-05-20 11:23:40.000000000 +0200
*************** print_node (FILE *file, const char *pref
*** 425,432 ****
fputs (" virtual", file);
if (DECL_PRESERVE_P (node))
fputs (" preserve", file);
- if (DECL_NO_TBAA_P (node))
- fputs (" no-tbaa", file);
if (DECL_LANG_FLAG_0 (node))
fputs (" decl_0", file);
if (DECL_LANG_FLAG_1 (node))
--- 425,430 ----
Index: gcc/tree-ssa-copyrename.c
===================================================================
*** gcc/tree-ssa-copyrename.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-ssa-copyrename.c 2009-05-20 11:23:40.000000000 +0200
*************** copy_rename_partition_coalesce (var_map
*** 233,252 ****
return false;
}
- /* Don't coalesce if the aliasing sets of the types are different. */
- if (POINTER_TYPE_P (TREE_TYPE (root1))
- && POINTER_TYPE_P (TREE_TYPE (root2))
- && ((get_alias_set (TREE_TYPE (TREE_TYPE (root1)))
- != get_alias_set (TREE_TYPE (TREE_TYPE (root2))))
- || (DECL_P (root1) && DECL_P (root2)
- && DECL_NO_TBAA_P (root1) != DECL_NO_TBAA_P (root2))))
- {
- if (debug)
- fprintf (debug, " : 2 different aliasing sets. No coalesce.\n");
- return false;
- }
-
-
/* Merge the two partitions. */
p3 = partition_union (map->var_partition, p1, p2);
--- 233,238 ----
Index: gcc/tree-data-ref.c
===================================================================
*** gcc/tree-data-ref.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-data-ref.c 2009-05-20 11:23:40.000000000 +0200
*************** dr_may_alias_p (const struct data_refere
*** 1223,1229 ****
return false;
/* Query the alias oracle. */
! if (!refs_may_alias_p (DR_REF (a), DR_REF (b)))
return false;
if (!addr_a || !addr_b)
--- 1223,1239 ----
return false;
/* Query the alias oracle. */
! if (!DR_IS_READ (a) && !DR_IS_READ (b))
! {
! if (!refs_output_dependent_p (DR_REF (a), DR_REF (b)))
! return false;
! }
! else if (DR_IS_READ (a) && !DR_IS_READ (b))
! {
! if (!refs_anti_dependent_p (DR_REF (a), DR_REF (b)))
! return false;
! }
! else if (!refs_may_alias_p (DR_REF (a), DR_REF (b)))
return false;
if (!addr_a || !addr_b)
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-ssa-alias.c 2009-05-20 11:23:40.000000000 +0200
*************** ptr_deref_may_alias_global_p (tree ptr)
*** 155,164 ****
if (!pi)
return true;
return pt_solution_includes_global (&pi->pt);
}
! /* Return true if dereferencing PTR may alias DECL. */
static bool
ptr_deref_may_alias_decl_p (tree ptr, tree decl)
--- 155,167 ----
if (!pi)
return true;
+ /* ??? This does not use TBAA to prune globals ptr may not access. */
return pt_solution_includes_global (&pi->pt);
}
! /* Return true if dereferencing PTR may alias DECL.
! The caller is responsible for applying TBAA to see if PTR
! may access DECL at all. */
static bool
ptr_deref_may_alias_decl_p (tree ptr, tree decl)
*************** ptr_deref_may_alias_decl_p (tree ptr, tr
*** 190,196 ****
return pt_solution_includes (&pi->pt, decl);
}
! /* Return true if dereferenced PTR1 and PTR2 may alias. */
static bool
ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
--- 193,201 ----
return pt_solution_includes (&pi->pt, decl);
}
! /* Return true if dereferenced PTR1 and PTR2 may alias.
! The caller is responsible for applying TBAA to see if accesses
! through PTR1 and PTR2 may conflict at all. */
static bool
ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
*************** ptr_derefs_may_alias_p (tree ptr1, tree
*** 222,227 ****
--- 227,234 ----
if (!pi1 || !pi2)
return true;
+ /* ??? This does not use TBAA to prune decls from the intersection
+ that not both pointers may access. */
return pt_solutions_intersect (&pi1->pt, &pi2->pt);
}
*************** indirect_refs_may_alias_p (tree ref1, tr
*** 653,665 ****
/* Return true, if the two memory references REF1 and REF2 may alias. */
static bool
! refs_may_alias_p_1 (tree ref1, tree ref2)
{
tree base1, base2;
HOST_WIDE_INT offset1 = 0, offset2 = 0;
HOST_WIDE_INT size1 = -1, size2 = -1;
HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
bool var1_p, var2_p, ind1_p, ind2_p;
gcc_assert ((SSA_VAR_P (ref1)
|| handled_component_p (ref1)
--- 660,673 ----
/* Return true, if the two memory references REF1 and REF2 may alias. */
static bool
! refs_may_alias_p_1 (tree ref1, tree ref2, bool tbaa_p)
{
tree base1, base2;
HOST_WIDE_INT offset1 = 0, offset2 = 0;
HOST_WIDE_INT size1 = -1, size2 = -1;
HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
bool var1_p, var2_p, ind1_p, ind2_p;
+ alias_set_type set;
gcc_assert ((SSA_VAR_P (ref1)
|| handled_component_p (ref1)
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 694,700 ****
base2, offset2, max_size2);
/* First defer to TBAA if possible. */
! if (flag_strict_aliasing
&& !alias_sets_conflict_p (get_alias_set (ref1), get_alias_set (ref2)))
return false;
--- 702,709 ----
base2, offset2, max_size2);
/* First defer to TBAA if possible. */
! if (tbaa_p
! && flag_strict_aliasing
&& !alias_sets_conflict_p (get_alias_set (ref1), get_alias_set (ref2)))
return false;
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 708,728 ****
/* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */
ind1_p = INDIRECT_REF_P (base1);
ind2_p = INDIRECT_REF_P (base2);
if (var1_p && ind2_p)
return indirect_ref_may_alias_decl_p (ref2, TREE_OPERAND (base2, 0),
! offset2, max_size2, -1,
ref1, base1,
! offset1, max_size1, -1);
else if (ind1_p && var2_p)
return indirect_ref_may_alias_decl_p (ref1, TREE_OPERAND (base1, 0),
! offset1, max_size1, -1,
ref2, base2,
! offset2, max_size2, -1);
else if (ind1_p && ind2_p)
return indirect_refs_may_alias_p (ref1, TREE_OPERAND (base1, 0),
! offset1, max_size1, -1,
ref2, TREE_OPERAND (base2, 0),
! offset2, max_size2, -1);
gcc_unreachable ();
}
--- 717,738 ----
/* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */
ind1_p = INDIRECT_REF_P (base1);
ind2_p = INDIRECT_REF_P (base2);
+ set = tbaa_p ? -1 : 0;
if (var1_p && ind2_p)
return indirect_ref_may_alias_decl_p (ref2, TREE_OPERAND (base2, 0),
! offset2, max_size2, set,
ref1, base1,
! offset1, max_size1, set);
else if (ind1_p && var2_p)
return indirect_ref_may_alias_decl_p (ref1, TREE_OPERAND (base1, 0),
! offset1, max_size1, set,
ref2, base2,
! offset2, max_size2, set);
else if (ind1_p && ind2_p)
return indirect_refs_may_alias_p (ref1, TREE_OPERAND (base1, 0),
! offset1, max_size1, set,
ref2, TREE_OPERAND (base2, 0),
! offset2, max_size2, set);
gcc_unreachable ();
}
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 730,736 ****
bool
refs_may_alias_p (tree ref1, tree ref2)
{
! bool res = refs_may_alias_p_1 (ref1, ref2);
if (res)
++alias_stats.refs_may_alias_p_may_alias;
else
--- 740,746 ----
bool
refs_may_alias_p (tree ref1, tree ref2)
{
! bool res = refs_may_alias_p_1 (ref1, ref2, true);
if (res)
++alias_stats.refs_may_alias_p_may_alias;
else
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 738,743 ****
--- 748,770 ----
return res;
}
+ /* Returns true if there is a anti-dependence for the STORE that
+ executes after the LOAD. */
+
+ bool
+ refs_anti_dependent_p (tree load, tree store)
+ {
+ return refs_may_alias_p_1 (load, store, false);
+ }
+
+ /* Returns true if there is a output dependence for the stores
+ STORE1 and STORE2. */
+
+ bool
+ refs_output_dependent_p (tree store1, tree store2)
+ {
+ return refs_may_alias_p_1 (store1, store2, false);
+ }
/* If the call CALL may use the memory reference REF return true,
otherwise return false. */
Index: gcc/tree-ssa-alias.h
===================================================================
*** gcc/tree-ssa-alias.h.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/tree-ssa-alias.h 2009-05-20 11:23:40.000000000 +0200
*************** struct GTY(()) pt_solution
*** 78,83 ****
--- 78,85 ----
extern enum escape_type is_escape_site (gimple);
extern bool ptr_deref_may_alias_global_p (tree);
extern bool refs_may_alias_p (tree, tree);
+ extern bool refs_anti_dependent_p (tree, tree);
+ extern bool refs_output_dependent_p (tree, tree);
extern bool ref_maybe_used_by_stmt_p (gimple, tree);
extern bool stmt_may_clobber_ref_p (gimple, tree);
extern void *walk_non_aliased_vuses (tree, tree,
Index: gcc/doc/tree-ssa.texi
===================================================================
*** gcc/doc/tree-ssa.texi.orig 2009-05-20 11:21:42.000000000 +0200
--- gcc/doc/tree-ssa.texi 2009-05-20 11:23:40.000000000 +0200
*************** passes for GIMPLE@.
*** 41,46 ****
--- 41,47 ----
* SSA Operands:: SSA names referenced by GIMPLE statements.
* SSA:: Static Single Assignment representation.
* Alias analysis:: Representing aliased loads and stores.
+ * Memory model:: Memory model used by the middle-end.
@end menu
@node Annotations
*************** providing its aliasing VDEF. The walk s
*** 892,894 ****
--- 893,923 ----
@end enumerate
+
+ @node Memory model
+ @section Memory model
+ @cindex memory model
+
+ The memory model used by the middle-end models that of the C/C++
+ languages. The middle-end has the notion of an effective type
+ of a memory region which is used for type-based alias analysis.
+
+ The following is a refinement of ISO C99 6.5/6, clarifying the block copy case
+ to follow common sense and extending the concept of a dynamic effective
+ type to objects with a declared type as required for C++.
+
+ @smallexample
+ The effective type of an object for an access to its stored value is
+ the declared type of the object or the effective type determined by
+ a previous store to it. If a value is stored into an object through
+ an lvalue having a type that is not a character type, then the
+ type of the lvalue becomes the effective type of the object for that
+ access and for subsequent accesses that do not modify the stored value.
+ If a value is copied into an object using @code{memcpy} or @code{memmove},
+ or is copied as an array of character type, then the effective type
+ of the modified object for that access and for subsequent accesses that
+ do not modify the value is undetermined. For all other accesses to an
+ object, the effective type of the object is simply the type of the
+ lvalue used for the access.
+ @end smallexample
+
Index: gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C
===================================================================
*** gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C.orig 2008-12-04 16:47:36.000000000 +0100
--- gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C 2009-05-20 12:28:18.000000000 +0200
***************
*** 4,11 ****
int foo() {
int x;
! float& q = reinterpret_cast<float&> (x); /* { dg-message "initialized" } */
! q = 1.0; /* { dg-warning "does break strict-aliasing" } */
return x;
}
--- 4,11 ----
int foo() {
int x;
! float& q = reinterpret_cast<float&> (x); /* { dg-message "initialized" "" { xfail *-*-* } } */
! q = 1.0; /* { dg-warning "does break strict-aliasing" "" { xfail *-*-* } } */
return x;
}
Index: gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c
===================================================================
*** gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c.orig 2008-12-05 12:55:11.000000000 +0100
--- gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c 2009-05-20 12:29:29.000000000 +0200
*************** int foo()
*** 9,13 ****
return i;
}
! /* { dg-message "does break strict-aliasing" "" { target { *-*-* && lp64 } } 8 } */
! /* { dg-message "initialized" "" { target { *-*-* && lp64 } } 8 } */
--- 9,13 ----
return i;
}
! /* { dg-message "does break strict-aliasing" "" { target { *-*-* && lp64 } xfail *-*-* } 8 } */
! /* { dg-message "initialized" "" { target { *-*-* && lp64 } xfail *-*-* } 8 } */
Index: gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c
===================================================================
*** gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c.orig 2008-12-04 16:47:36.000000000 +0100
--- gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c 2009-05-20 12:30:22.000000000 +0200
*************** int foo() {
*** 11,22 ****
float* r;
if (flag) {
! q = (float*) &x; /* { dg-message "initialized" } */
} else {
! q = (float*) &y; /* { dg-message "initialized" } */
}
! *q = 1.0; /* { dg-warning "does break strict-aliasing" } */
return x;
--- 11,22 ----
float* r;
if (flag) {
! q = (float*) &x; /* { dg-message "initialized" "" { xfail *-*-* } } */
} else {
! q = (float*) &y; /* { dg-message "initialized" "" { xfail *-*-* } } */
}
! *q = 1.0; /* { dg-warning "does break strict-aliasing" "" { xfail *-*-* } } */
return x;