This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix C++ strict-aliasing issues with memcpy folding
On Tue, 2 Feb 2010, Gabriel Dos Reis wrote:
> >> ah, but that transformation to plain assignment is middle-end
> >> gimmicks, not C++ source-level constructs. ?I think the middle-end
> >> should probably annotate that transformation (probably as
> >> a VIEW_CONVERT_EXPR?) since the standard explicitly says that one can
> >> move valid objects around with memcpy() (for objects of POD type.)
> >> And surely the library should use memcpy() to copy objects with
> >> statically ambiguous type.
> >>
> >> Does the annotation idea makes sense to the middle-end?
> >
> > Yes. ?I was playing with that during the weekend and have some
> > prototype patch that I need to clean up a bit.
>
> That would be fantastic.
Current prototype attached. It bootstraps and tests fine (well,
before some cleanup done) but still has some minor regressions.
The idea is to continue to fold memcpys into assignments (and thus
the frontends should use memcpy when they mean it). To retain
the alias-set zeroness of the folded assignments we do the copy
in char[] type. Encoding this using TARGET_MEM_REFs:
MEM[symbol: j] = MEM[symbol: i];
where TREE_TYPE of the MEMs is char[4]. If later nothing takes
the address of j anymore we re-write the symbols into SSA form
like:
j_7 = VIEW_CONVERT_EXPR<int>(MEM[symbol: i]);
I don't consider the patch appropriate for 4.5.
As the memcpy folding bug isn't a regression and we have a workaround
for libstdc++ in place I consider not fixing the bug for 4.5.
Thanks,
Richard.
FAIL: gcc.dg/memcpy-1.c scan-tree-dump-times optimized "nasty_local\\." 0
SRA (and get_ref_base_and_extent) need to handle
MEM[symbol: nasty_local] = MEM[symbol: a];
D.1958_1 = nasty_local.a;
but SRA build-ref-for-offset has to be careful to build alias-set
zero references to a.
FAIL: gfortran.dg/array_memcpy_4.f90 -O scan-tree-dump-times original "d = " 1
The frontend should directly emit assignments with array type
as it probably knows that using alias-set zero memcpy is not needed.
As with Ada char_type_node doesn't have alias-set zero, so we do
not fold.
FAIL: gcc.dg/tree-prof/stringop-1.c scan-tree-dump optimized "a.0. = "
FAIL: gcc.dg/tree-prof/stringop-1.c scan-tree-dump optimized "= b.0."
Dump needs adjustment
FAIL: gcc.target/i386/memcpy-1.c scan-assembler-not test
FAIL: gfortran.dg/scalarize_parameter_array_1.f90 -O1 execution test
FAIL: libgomp.fortran/character1.f90 -O1 execution test
2010-01-31 Richard Guenther <rguenther@suse.de>
PR middle-end/42834
* tree-ssa.c (execute_update_addresses_taken): Rewrite
TARGET_MEM_REFs into plain assignments if we want to
rename its symbol.
* tree-flow.h (symbol_marked_for_renaming): Declare.
* tree-into-ssa.c (symbol_marked_for_renaming): Export.
* gimple.c (is_gimple_addressable): TARGET_MEM_REFs are
addressable.
(is_gimple_address): Likewise.
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Handle
wrapped TARGET_MEM_REFs.
(visit_reference_op_store): Enter converted TARGET_MEM_REFs
into the tables.
* alias.c (get_alias_set): Use TMR_ORIGINAL only if it
is available.
* builtins.c (fold_builtin_memory_op): Make sure to use
alias-set zero for copies by using TARGET_MEM_REFs of char[]
type.
* tree-ssa-operands.c (get_tmr_operands): Mark TMR_SYMBOL
addressable only if it cannot be rewritten into SSA form.
* tree-ssa-alias.c (refs_may_alias_p_1): Adjust bailout for
TARGET_MEM_REFs.
* tree-eh.c (tree_could_trap_p): Handle NULL TMR_ORIGINAL.
* gimplify.c (gimplify_expr): Handle DECL_VALUE_EXPR
modifications when gimplifying TARGET_MEM_REF.
* tree-nested.c (convert_local_reference_op): Handle TARGET_MEM_REF.
* gcc.dg/pr42834.c: New testcase.
* gcc.c-torture/compile/20100131-1.c: Likewise.
* g++.dg/torture/pr42834.C: Likewise.
Index: gcc/tree-ssa.c
===================================================================
*** gcc/tree-ssa.c.orig 2010-02-02 13:15:12.000000000 +0100
--- gcc/tree-ssa.c 2010-02-02 15:11:25.000000000 +0100
*************** execute_update_addresses_taken (bool do_
*** 1933,1945 ****
{
tree lhs = gimple_get_lhs (stmt);
- /* We may not rewrite TMR_SYMBOL to SSA. */
- if (lhs && TREE_CODE (lhs) == TARGET_MEM_REF
- && TMR_SYMBOL (lhs))
- bitmap_set_bit (not_reg_needs, DECL_UID (TMR_SYMBOL (lhs)));
-
/* A plain decl does not need it set. */
! else if (lhs && handled_component_p (lhs))
{
var = get_base_address (lhs);
if (DECL_P (var))
--- 1933,1940 ----
{
tree lhs = gimple_get_lhs (stmt);
/* A plain decl does not need it set. */
! if (lhs && handled_component_p (lhs))
{
var = get_base_address (lhs);
if (DECL_P (var))
*************** execute_update_addresses_taken (bool do_
*** 2021,2026 ****
--- 2016,2075 ----
{
gimple stmt = gsi_stmt (gsi);
+ /* Re-write TARGET_MEM_REFs of symbols we want to
+ rewrite into SSA form. */
+ if (gimple_assign_single_p (stmt))
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+ tree rhs, *rhsp = gimple_assign_rhs1_ptr (stmt);
+ tree sym;
+
+ /* We shouldn't have any fancy wrapping of
+ component-refs on the LHS, but look through
+ VIEW_CONVERT_EXPRs as that is easy. */
+ while (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
+ lhs = TREE_OPERAND (lhs, 0);
+ if (TREE_CODE (lhs) == TARGET_MEM_REF
+ && (sym = TMR_SYMBOL (lhs))
+ && !TREE_ADDRESSABLE (sym)
+ && symbol_marked_for_renaming (sym))
+ lhs = sym;
+ else
+ lhs = gimple_assign_lhs (stmt);
+
+ /* We can have fancy wrappings on the RHS though. */
+ while (handled_component_p (*rhsp))
+ rhsp = &TREE_OPERAND (*rhsp, 0);
+ if (TREE_CODE (*rhsp) == TARGET_MEM_REF
+ && (sym = TMR_SYMBOL (*rhsp))
+ && !TREE_ADDRESSABLE (sym)
+ && symbol_marked_for_renaming (sym))
+ {
+ if (!useless_type_conversion_p (TREE_TYPE (*rhsp),
+ TREE_TYPE (sym)))
+ *rhsp = build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (*rhsp), sym);
+ else
+ *rhsp = sym;
+ }
+
+ rhs = gimple_assign_rhs1 (stmt);
+ if (gimple_assign_lhs (stmt) != lhs
+ && !useless_type_conversion_p (TREE_TYPE (lhs),
+ TREE_TYPE (rhs)))
+ rhs = fold_build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (lhs), rhs);
+
+ if (gimple_assign_lhs (stmt) != lhs)
+ gimple_assign_set_lhs (stmt, lhs);
+
+ if (gimple_assign_rhs1 (stmt) != rhs)
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ gimple_assign_set_rhs_from_tree (&gsi, rhs);
+ }
+ }
+
if (gimple_references_memory_p (stmt)
|| is_gimple_debug (stmt))
update_stmt (stmt);
Index: gcc/tree-into-ssa.c
===================================================================
*** gcc/tree-into-ssa.c.orig 2010-02-02 13:15:10.000000000 +0100
--- gcc/tree-into-ssa.c 2010-02-02 14:12:45.000000000 +0100
*************** set_livein_block (tree var, basic_block
*** 561,567 ****
/* Return true if symbol SYM is marked for renaming. */
! static inline bool
symbol_marked_for_renaming (tree sym)
{
return bitmap_bit_p (SYMS_TO_RENAME (cfun), DECL_UID (sym));
--- 561,567 ----
/* Return true if symbol SYM is marked for renaming. */
! bool
symbol_marked_for_renaming (tree sym)
{
return bitmap_bit_p (SYMS_TO_RENAME (cfun), DECL_UID (sym));
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig 2010-02-02 13:15:12.000000000 +0100
--- gcc/gimple.c 2010-02-02 13:46:27.000000000 +0100
*************** is_gimple_condexpr (tree t)
*** 2523,2529 ****
bool
is_gimple_addressable (tree t)
{
! return (is_gimple_id (t) || handled_component_p (t) || INDIRECT_REF_P (t));
}
/* Return true if T is a valid gimple constant. */
--- 2523,2530 ----
bool
is_gimple_addressable (tree t)
{
! return (is_gimple_id (t) || handled_component_p (t)
! || INDIRECT_REF_P (t) || TREE_CODE (t) == TARGET_MEM_REF);
}
/* Return true if T is a valid gimple constant. */
*************** is_gimple_address (const_tree t)
*** 2564,2569 ****
--- 2565,2571 ----
return false;
op = TREE_OPERAND (t, 0);
+ /* ??? Why does this not simpl return is_gimple_addressable (op)? */
while (handled_component_p (op))
{
if ((TREE_CODE (op) == ARRAY_REF
*************** is_gimple_address (const_tree t)
*** 2574,2580 ****
op = TREE_OPERAND (op, 0);
}
! if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op))
return true;
switch (TREE_CODE (op))
--- 2576,2583 ----
op = TREE_OPERAND (op, 0);
}
! if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op)
! || TREE_CODE (op) == TARGET_MEM_REF)
return true;
switch (TREE_CODE (op))
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig 2010-02-02 12:43:58.000000000 +0100
--- gcc/tree-ssa-sccvn.c 2010-02-02 13:46:27.000000000 +0100
*************** copy_reference_ops_from_ref (tree ref, V
*** 597,602 ****
--- 597,622 ----
case REALPART_EXPR:
case VIEW_CONVERT_EXPR:
break;
+ case TARGET_MEM_REF:
+ {
+ tree base;
+
+ base = TMR_SYMBOL (ref) ? TMR_SYMBOL (ref) : TMR_BASE (ref);
+ if (!base)
+ base = build_int_cst (ptr_type_node, 0);
+
+ temp.op0 = TMR_INDEX (ref);
+ temp.op1 = TMR_STEP (ref);
+ temp.op2 = TMR_OFFSET (ref);
+ VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+
+ memset (&temp, 0, sizeof (temp));
+ temp.type = NULL_TREE;
+ temp.opcode = TREE_CODE (base);
+ temp.op0 = base;
+ temp.op1 = TMR_ORIGINAL (ref);
+ break;
+ }
default:
gcc_unreachable ();
}
*************** visit_reference_op_store (tree lhs, tree
*** 2130,2136 ****
changed |= set_ssa_val_to (vdef, vdef);
}
! /* Do not insert structure copies into the tables. */
if (is_gimple_min_invariant (op)
|| is_gimple_reg (op))
vn_reference_insert (lhs, op, vdef);
--- 2150,2159 ----
changed |= set_ssa_val_to (vdef, vdef);
}
! /* Do not insert structure copies into the tables, but record
! aggregate VIEW_CONVERT_EXPRs of registers. */
! if (TREE_CODE (op) == VIEW_CONVERT_EXPR)
! op = TREE_OPERAND (op, 0);
if (is_gimple_min_invariant (op)
|| is_gimple_reg (op))
vn_reference_insert (lhs, op, vdef);
Index: gcc/alias.c
===================================================================
*** gcc/alias.c.orig 2010-02-02 12:43:58.000000000 +0100
--- gcc/alias.c 2010-02-02 13:46:27.000000000 +0100
*************** get_alias_set (tree t)
*** 649,656 ****
if (set != -1)
return set;
! /* Retrieve the original memory reference if needed. */
! if (TREE_CODE (t) == TARGET_MEM_REF)
t = TMR_ORIGINAL (t);
/* First see if the actual object referenced is an INDIRECT_REF from a
--- 649,657 ----
if (set != -1)
return set;
! /* Retrieve the original memory reference if needed and available. */
! if (TREE_CODE (t) == TARGET_MEM_REF
! && TMR_ORIGINAL (t))
t = TMR_ORIGINAL (t);
/* First see if the actual object referenced is an INDIRECT_REF from a
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c.orig 2010-02-02 12:43:58.000000000 +0100
--- gcc/builtins.c 2010-02-02 13:46:27.000000000 +0100
*************** fold_builtin_memory_op (location_t loc,
*** 8160,8165 ****
--- 8160,8166 ----
{
tree srctype, desttype;
int src_align, dest_align;
+ tree cpytype;
if (endp == 3)
{
*************** fold_builtin_memory_op (location_t loc,
*** 8303,8308 ****
--- 8304,8312 ----
if (!ignore)
dest = builtin_save_expr (dest);
+ /* ??? With the current code using TARGET_MEM_REF we can relax
+ a lot of the following checks as we only need a valid
+ base symbol and constant offset. */
srcvar = NULL_TREE;
if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
{
*************** fold_builtin_memory_op (location_t loc,
*** 8336,8399 ****
if (srcvar == NULL_TREE && destvar == NULL_TREE)
return NULL_TREE;
if (srcvar == NULL_TREE)
{
tree srcptype;
if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
return NULL_TREE;
! srctype = build_qualified_type (desttype, 0);
! if (src_align < (int) TYPE_ALIGN (srctype))
{
! if (AGGREGATE_TYPE_P (srctype)
! || SLOW_UNALIGNED_ACCESS (TYPE_MODE (srctype), src_align))
! return NULL_TREE;
! srctype = build_variant_type_copy (srctype);
! TYPE_ALIGN (srctype) = src_align;
! TYPE_USER_ALIGN (srctype) = 1;
! TYPE_PACKED (srctype) = 1;
}
! srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true);
! src = fold_convert_loc (loc, srcptype, src);
! srcvar = build_fold_indirect_ref_loc (loc, src);
}
! else if (destvar == NULL_TREE)
{
tree destptype;
if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
return NULL_TREE;
! desttype = build_qualified_type (srctype, 0);
! if (dest_align < (int) TYPE_ALIGN (desttype))
{
! if (AGGREGATE_TYPE_P (desttype)
! || SLOW_UNALIGNED_ACCESS (TYPE_MODE (desttype), dest_align))
! return NULL_TREE;
! desttype = build_variant_type_copy (desttype);
! TYPE_ALIGN (desttype) = dest_align;
! TYPE_USER_ALIGN (desttype) = 1;
! TYPE_PACKED (desttype) = 1;
}
! destptype = build_pointer_type_for_mode (desttype, ptr_mode, true);
! dest = fold_convert_loc (loc, destptype, dest);
! destvar = build_fold_indirect_ref_loc (loc, dest);
}
! if (srctype == desttype
! || (gimple_in_ssa_p (cfun)
! && useless_type_conversion_p (desttype, srctype)))
! expr = srcvar;
! else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
! || POINTER_TYPE_P (TREE_TYPE (srcvar)))
! && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
! || POINTER_TYPE_P (TREE_TYPE (destvar))))
! expr = fold_convert_loc (loc, TREE_TYPE (destvar), srcvar);
! else
! expr = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
! TREE_TYPE (destvar), srcvar);
! expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
}
if (ignore)
--- 8340,8430 ----
if (srcvar == NULL_TREE && destvar == NULL_TREE)
return NULL_TREE;
+ if (integer_onep (len))
+ cpytype = char_type_node;
+ else
+ {
+ cpytype = build_index_type (size_int (TREE_INT_CST_LOW (len) - 1));
+ cpytype = build_array_type (char_type_node, cpytype);
+ }
+ /* ??? Need a middle-end byte type with guaranteed alias-set zero.
+ Neither Fortran nor Ada currently pass the following check. */
+ if (get_alias_set (cpytype) != 0)
+ return NULL_TREE;
+
if (srcvar == NULL_TREE)
{
tree srcptype;
if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
return NULL_TREE;
! srcptype = build_pointer_type_for_mode (cpytype, ptr_mode, true);
! src = fold_convert_loc (loc, srcptype, src);
! srcvar = build_fold_indirect_ref_loc (loc, src);
! }
! else
! {
! HOST_WIDE_INT offset = 0;
! HOST_WIDE_INT size = -1;
! HOST_WIDE_INT maxsize = -1;
! tree base = srcvar;
!
! if (handled_component_p (base))
{
! base = get_ref_base_and_extent (base, &offset, &size, &maxsize);
! /* If the start address is variable bail out.
! ??? We can use srcvar itself if len == 1 and srcvar is a
! reference of the same size and with alias-set zero.
! ??? We could also use get_inner_reference here and put
! the variable offset into TMR_INDEX with a TMR_STEP of one. */
! if (size != maxsize
! || maxsize == -1)
! return NULL_TREE;
}
!
! srcvar = build6 (TARGET_MEM_REF, cpytype,
! base, NULL_TREE, NULL_TREE, NULL_TREE,
! offset != 0
! ? size_int (offset / BITS_PER_UNIT) : NULL_TREE,
! NULL_TREE);
}
!
! if (destvar == NULL_TREE)
{
tree destptype;
if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
return NULL_TREE;
! destptype = build_pointer_type_for_mode (cpytype, ptr_mode, true);
! dest = fold_convert_loc (loc, destptype, dest);
! destvar = build_fold_indirect_ref_loc (loc, dest);
! }
! else
! {
! HOST_WIDE_INT offset = 0;
! HOST_WIDE_INT size = -1;
! HOST_WIDE_INT maxsize = -1;
! tree base = destvar;
!
! if (handled_component_p (base))
{
! base = get_ref_base_and_extent (base, &offset, &size, &maxsize);
! /* If the start address is variable bail out. */
! if (size != maxsize
! || maxsize == -1)
! return NULL_TREE;
}
!
! destvar = build6 (TARGET_MEM_REF, cpytype,
! base, NULL_TREE, NULL_TREE, NULL_TREE,
! offset != 0
! ? size_int (offset / BITS_PER_UNIT) : NULL_TREE,
! NULL_TREE);
}
! expr = build2 (MODIFY_EXPR, void_type_node, destvar, srcvar);
}
if (ignore)
Index: gcc/tree-ssa-operands.c
===================================================================
*** gcc/tree-ssa-operands.c.orig 2010-02-02 12:43:58.000000000 +0100
--- gcc/tree-ssa-operands.c 2010-02-02 13:46:27.000000000 +0100
*************** get_tmr_operands (gimple stmt, tree expr
*** 736,742 ****
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 (TMR_SYMBOL (expr));
add_virtual_operand (stmt, flags);
--- 736,747 ----
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)
! && !(is_gimple_reg_type (TREE_TYPE (TMR_SYMBOL (expr)))
! && !TMR_INDEX (expr)
! && !TMR_OFFSET (expr)
! && tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (expr)),
! DECL_SIZE (TMR_SYMBOL (expr)))))
mark_address_taken (TMR_SYMBOL (expr));
add_virtual_operand (stmt, flags);
Index: gcc/testsuite/gcc.dg/pr42834.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/pr42834.c 2010-02-02 13:46:27.000000000 +0100
***************
*** 0 ****
--- 1,21 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-optimized-vops" } */
+
+ void bar (int *);
+ int foo(int i)
+ {
+ int j, k, l;
+ __builtin_memcpy (&j, &i, 4);
+ __builtin_memcpy (&k, &i, 4);
+ __builtin_memcpy (&l, &k, 4);
+ bar (&k);
+ return j + k + l;
+ }
+
+ /* All memcpy calls should be folded away. Two VDEFs should
+ remain, that for the store into k which has its address taken
+ and that for the call to bar. */
+
+ /* { dg-final { scan-tree-dump-times "memcpy" 0 "optimized" } } */
+ /* { dg-final { scan-tree-dump-times "VDEF" 2 "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig 2010-02-02 13:15:12.000000000 +0100
--- gcc/tree-ssa-alias.c 2010-02-02 13:46:27.000000000 +0100
*************** refs_may_alias_p_1 (ao_ref *ref1, ao_ref
*** 828,835 ****
/* If one reference is a TARGET_MEM_REF weird things are allowed. Still
TBAA disambiguation based on the access type is possible, so bail
out only after that check. */
! if ((ref1->ref && TREE_CODE (ref1->ref) == TARGET_MEM_REF)
! || (ref2->ref && TREE_CODE (ref2->ref) == TARGET_MEM_REF))
return true;
/* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */
--- 828,835 ----
/* If one reference is a TARGET_MEM_REF weird things are allowed. Still
TBAA disambiguation based on the access type is possible, so bail
out only after that check. */
! if (TREE_CODE (base1) == TARGET_MEM_REF
! || TREE_CODE (base2) == TARGET_MEM_REF)
return true;
/* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */
Index: gcc/testsuite/gcc.c-torture/compile/20100131-1.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/20100131-1.c 2010-02-02 13:46:27.000000000 +0100
***************
*** 0 ****
--- 1,16 ----
+ typedef struct rtx_def *rtx;
+ struct rtx_def {
+ int code;
+ };
+ struct obstack {
+ char *next_free;
+ };
+ static struct obstack obstack;
+ static void gen_insn (rtx insn)
+ {
+ __builtin_memcpy (obstack.next_free, &insn, sizeof (rtx));
+ }
+ void foo (rtx desc)
+ {
+ gen_insn (desc);
+ }
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c.orig 2010-02-02 12:43:58.000000000 +0100
--- gcc/gimplify.c 2010-02-02 13:46:27.000000000 +0100
*************** gimplify_expr (tree *expr_p, gimple_seq
*** 6732,6740 ****
enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
if (TMR_SYMBOL (*expr_p))
! r0 = gimplify_expr (&TMR_SYMBOL (*expr_p), pre_p,
! post_p, is_gimple_lvalue, fb_either);
! else if (TMR_BASE (*expr_p))
r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
post_p, is_gimple_val, fb_either);
if (TMR_INDEX (*expr_p))
--- 6732,6766 ----
enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
if (TMR_SYMBOL (*expr_p))
! {
! r0 = gimplify_expr (&TMR_SYMBOL (*expr_p), pre_p,
! post_p, is_gimple_lvalue, fb_either);
! /* Via DECL_VALUE_EXPR we can end up gimplifying
! TMR_SYMBOL into a non-symbol. Move it to TMR_BASE
! or adjust the offset in that case. */
! if (handled_component_p (TMR_SYMBOL (*expr_p)))
! {
! tree base;
! HOST_WIDE_INT offset, size, max_size;
! base = get_ref_base_and_extent (TMR_SYMBOL (*expr_p),
! &offset, &size, &max_size);
! TMR_SYMBOL (*expr_p) = base;
! if (!TMR_OFFSET (*expr_p) && offset != 0)
! TMR_OFFSET (*expr_p) = size_int (offset / BITS_PER_UNIT);
! else if (offset != 0)
! TMR_OFFSET (*expr_p)
! = size_binop_loc (UNKNOWN_LOCATION, PLUS_EXPR,
! TMR_OFFSET (*expr_p),
! size_int (offset / BITS_PER_UNIT));
! }
! if (INDIRECT_REF_P (TMR_SYMBOL (*expr_p)))
! {
! gcc_assert (!TMR_BASE (*expr_p));
! TMR_BASE (*expr_p) = TREE_OPERAND (TMR_SYMBOL (*expr_p), 0);
! TMR_SYMBOL (*expr_p) = NULL_TREE;
! }
! }
! if (TMR_BASE (*expr_p))
r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
post_p, is_gimple_val, fb_either);
if (TMR_INDEX (*expr_p))
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c.orig 2010-02-02 12:43:58.000000000 +0100
--- gcc/tree-eh.c 2010-02-02 13:46:27.000000000 +0100
*************** tree_could_trap_p (tree expr)
*** 2371,2376 ****
--- 2371,2378 ----
/* For TARGET_MEM_REFs use the information based on the original
reference. */
expr = TMR_ORIGINAL (expr);
+ if (!expr)
+ return false;
code = TREE_CODE (expr);
goto restart;
Index: gcc/tree-nested.c
===================================================================
*** gcc/tree-nested.c.orig 2010-02-02 12:43:58.000000000 +0100
--- gcc/tree-nested.c 2010-02-02 13:46:27.000000000 +0100
*************** convert_local_reference_op (tree *tp, in
*** 1499,1504 ****
--- 1499,1535 ----
wi->val_only = save_val_only;
break;
+ case TARGET_MEM_REF:
+ save_val_only = wi->val_only;
+ wi->val_only = false;
+ if (TMR_SYMBOL (t))
+ {
+ walk_tree (&TMR_SYMBOL (t), convert_local_reference_op, wi, NULL);
+ if (handled_component_p (TMR_SYMBOL (t)))
+ {
+ tree base;
+ HOST_WIDE_INT offset, size, max_size;
+ base = get_ref_base_and_extent (TMR_SYMBOL (t),
+ &offset, &size, &max_size);
+ TMR_SYMBOL (t) = base;
+ if (!TMR_OFFSET (t) && offset != 0)
+ TMR_OFFSET (t) = size_int (offset / BITS_PER_UNIT);
+ else if (offset != 0)
+ TMR_OFFSET (t)
+ = size_binop_loc (UNKNOWN_LOCATION, PLUS_EXPR,
+ TMR_OFFSET (t),
+ size_int (offset / BITS_PER_UNIT));
+ }
+ }
+ wi->val_only = true;
+ wi->is_lhs = false;
+ if (TMR_BASE (t))
+ walk_tree (&TMR_BASE (t), convert_local_reference_op, wi, NULL);
+ if (TMR_INDEX (t))
+ walk_tree (&TMR_INDEX (t), convert_local_reference_op, wi, NULL);
+ wi->val_only = save_val_only;
+ break;
+
case VIEW_CONVERT_EXPR:
/* Just request to look at the subtrees, leaving val_only and lhs
untouched. This might actually be for !val_only + lhs, in which
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h.orig 2010-02-02 13:15:12.000000000 +0100
--- gcc/tree-flow.h 2010-02-02 14:11:01.000000000 +0100
*************** void release_ssa_name_after_update_ssa (
*** 599,604 ****
--- 599,605 ----
void compute_global_livein (bitmap, bitmap);
void mark_sym_for_renaming (tree);
void mark_set_for_renaming (bitmap);
+ bool symbol_marked_for_renaming (tree);
tree get_current_def (tree);
void set_current_def (tree, tree);
Index: gcc/testsuite/g++.dg/torture/pr42834.C
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/g++.dg/torture/pr42834.C 2010-02-02 14:22:56.000000000 +0100
***************
*** 0 ****
--- 1,16 ----
+ // { dg-do run }
+
+ int main()
+ {
+ if (sizeof(int) == sizeof(float))
+ {
+ int i = 0;
+ float f = 1.0;
+ int *p = (int *)&f;
+ __builtin_memcpy (&i, p, 4);
+ if (*(float *)&i != 1.0)
+ __builtin_abort ();
+ }
+ return 0;
+ }
+