mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-20 11:00:57 +08:00
re PR middle-end/38151 (structures with _Complex arguments are not passed correctly)
2008-11-25 Richard Guenther <rguenther@suse.de> PR middle-end/38151 PR middle-end/38236 * tree-ssa-alias.c (struct alias_info): Remove written_vars. Remove dereferenced_ptrs_store and dereferenced_ptrs_load in favor of dereferenced_ptrs. (init_alias_info): Adjust. (delete_alias_info): Likewise. (compute_flow_insensitive_aliasing): Properly include all aliased variables. (update_alias_info_1): Use dereferenced_ptrs. (setup_pointers_and_addressables): Likewise. (get_smt_for): Honor ref-all pointers and pointers with known alias set properly. * config/i386/i386.c (ix86_gimplify_va_arg): Use ref-all pointers. * gcc.c-torture/execute/pr38151.c: New testcase. * gcc.c-torture/execute/pr38236.c: Likewise. From-SVN: r142189
This commit is contained in:
parent
abb370e461
commit
b0ff8d7af5
@ -1,3 +1,20 @@
|
||||
2008-11-25 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/38151
|
||||
PR middle-end/38236
|
||||
* tree-ssa-alias.c (struct alias_info): Remove written_vars.
|
||||
Remove dereferenced_ptrs_store and dereferenced_ptrs_load
|
||||
in favor of dereferenced_ptrs.
|
||||
(init_alias_info): Adjust.
|
||||
(delete_alias_info): Likewise.
|
||||
(compute_flow_insensitive_aliasing): Properly
|
||||
include all aliased variables.
|
||||
(update_alias_info_1): Use dereferenced_ptrs.
|
||||
(setup_pointers_and_addressables): Likewise.
|
||||
(get_smt_for): Honor ref-all pointers and pointers with known alias
|
||||
set properly.
|
||||
* config/i386/i386.c (ix86_gimplify_va_arg): Use ref-all pointers.
|
||||
|
||||
2008-11-25 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/38254
|
||||
|
@ -6753,6 +6753,8 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
|
||||
enum machine_mode mode = GET_MODE (reg);
|
||||
tree piece_type = lang_hooks.types.type_for_mode (mode, 1);
|
||||
tree addr_type = build_pointer_type (piece_type);
|
||||
tree daddr_type = build_pointer_type_for_mode (piece_type,
|
||||
ptr_mode, true);
|
||||
tree src_addr, src;
|
||||
int src_offset;
|
||||
tree dest_addr, dest;
|
||||
@ -6772,8 +6774,8 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
|
||||
size_int (src_offset));
|
||||
src = build_va_arg_indirect_ref (src_addr);
|
||||
|
||||
dest_addr = fold_convert (addr_type, addr);
|
||||
dest_addr = fold_build2 (POINTER_PLUS_EXPR, addr_type, dest_addr,
|
||||
dest_addr = fold_convert (daddr_type, addr);
|
||||
dest_addr = fold_build2 (POINTER_PLUS_EXPR, daddr_type, dest_addr,
|
||||
size_int (INTVAL (XEXP (slot, 1))));
|
||||
dest = build_va_arg_indirect_ref (dest_addr);
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
2008-11-25 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/38151
|
||||
PR middle-end/38236
|
||||
* gcc.c-torture/execute/pr38151.c: New testcase.
|
||||
* gcc.c-torture/execute/pr38236.c: Likewise.
|
||||
|
||||
2008-11-24 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||
|
||||
* g++.dg/eh/weak1.C: Don't xfail hppa*64*-*-*.
|
||||
|
46
gcc/testsuite/gcc.c-torture/execute/pr38151.c
Normal file
46
gcc/testsuite/gcc.c-torture/execute/pr38151.c
Normal file
@ -0,0 +1,46 @@
|
||||
void abort (void);
|
||||
|
||||
struct S2848
|
||||
{
|
||||
unsigned int a;
|
||||
_Complex int b;
|
||||
struct
|
||||
{
|
||||
} __attribute__ ((aligned)) c;
|
||||
};
|
||||
|
||||
struct S2848 s2848;
|
||||
|
||||
int fails;
|
||||
|
||||
void __attribute__((noinline))
|
||||
check2848va (int z, ...)
|
||||
{
|
||||
struct S2848 arg;
|
||||
__builtin_va_list ap;
|
||||
|
||||
__builtin_va_start (ap, z);
|
||||
|
||||
arg = __builtin_va_arg (ap, struct S2848);
|
||||
|
||||
if (s2848.a != arg.a)
|
||||
++fails;
|
||||
if (s2848.b != arg.b)
|
||||
++fails;
|
||||
|
||||
__builtin_va_end (ap);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
s2848.a = 4027477739U;
|
||||
s2848.b = (723419448 + -218144346 * __extension__ 1i);
|
||||
|
||||
check2848va (1, s2848);
|
||||
|
||||
if (fails)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
22
gcc/testsuite/gcc.c-torture/execute/pr38236.c
Normal file
22
gcc/testsuite/gcc.c-torture/execute/pr38236.c
Normal file
@ -0,0 +1,22 @@
|
||||
struct X { int i; };
|
||||
|
||||
int __attribute__((noinline))
|
||||
foo (struct X *p, int *q, int a, int b)
|
||||
{
|
||||
struct X x, y;
|
||||
if (a)
|
||||
p = &x;
|
||||
if (b)
|
||||
q = &x.i;
|
||||
else
|
||||
q = &y.i;
|
||||
*q = 1;
|
||||
return p->i;
|
||||
}
|
||||
extern void abort (void);
|
||||
int main()
|
||||
{
|
||||
if (foo((void *)0, (void *)0, 1, 1) != 1)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
@ -188,15 +188,8 @@ struct alias_info
|
||||
struct alias_map_d **pointers;
|
||||
size_t num_pointers;
|
||||
|
||||
/* Variables that have been written to directly (i.e., not through a
|
||||
pointer dereference). */
|
||||
struct pointer_set_t *written_vars;
|
||||
|
||||
/* Pointers that have been used in an indirect store operation. */
|
||||
struct pointer_set_t *dereferenced_ptrs_store;
|
||||
|
||||
/* Pointers that have been used in an indirect load operation. */
|
||||
struct pointer_set_t *dereferenced_ptrs_load;
|
||||
/* Pointers that have been used in an indirect load/store operation. */
|
||||
struct pointer_set_t *dereferenced_ptrs;
|
||||
};
|
||||
|
||||
|
||||
@ -2073,9 +2066,7 @@ init_alias_info (void)
|
||||
ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
|
||||
sbitmap_zero (ai->ssa_names_visited);
|
||||
ai->processed_ptrs = VEC_alloc (tree, heap, 50);
|
||||
ai->written_vars = pointer_set_create ();
|
||||
ai->dereferenced_ptrs_store = pointer_set_create ();
|
||||
ai->dereferenced_ptrs_load = pointer_set_create ();
|
||||
ai->dereferenced_ptrs = pointer_set_create ();
|
||||
|
||||
/* Clear out all memory reference stats. */
|
||||
init_mem_ref_stats ();
|
||||
@ -2123,9 +2114,7 @@ delete_alias_info (struct alias_info *ai)
|
||||
free (ai->pointers[i]);
|
||||
free (ai->pointers);
|
||||
|
||||
pointer_set_destroy (ai->written_vars);
|
||||
pointer_set_destroy (ai->dereferenced_ptrs_store);
|
||||
pointer_set_destroy (ai->dereferenced_ptrs_load);
|
||||
pointer_set_destroy (ai->dereferenced_ptrs);
|
||||
free (ai);
|
||||
|
||||
delete_mem_ref_stats (cfun);
|
||||
@ -2361,23 +2350,18 @@ compute_flow_insensitive_aliasing (struct alias_info *ai)
|
||||
{
|
||||
struct alias_map_d *v_map;
|
||||
var_ann_t v_ann;
|
||||
bool tag_stored_p, var_stored_p;
|
||||
|
||||
v_map = ai->addressable_vars[j];
|
||||
var = v_map->var;
|
||||
v_ann = var_ann (var);
|
||||
|
||||
/* Skip memory tags and variables that have never been
|
||||
written to. We also need to check if the variables are
|
||||
call-clobbered because they may be overwritten by
|
||||
function calls. */
|
||||
tag_stored_p = pointer_set_contains (ai->written_vars, tag)
|
||||
|| is_call_clobbered (tag);
|
||||
var_stored_p = pointer_set_contains (ai->written_vars, var)
|
||||
|| is_call_clobbered (var);
|
||||
if (!tag_stored_p && !var_stored_p)
|
||||
continue;
|
||||
|
||||
/* We used to skip variables that have never been written to
|
||||
if the memory tag has been never written to directly (or
|
||||
either of them were call clobbered). This is not enough
|
||||
though, as this misses writes through the tags aliases.
|
||||
So, for correctness we need to include any aliased
|
||||
variable here. */
|
||||
|
||||
if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
|
||||
{
|
||||
/* Add VAR to TAG's may-aliases set. */
|
||||
@ -2618,13 +2602,8 @@ update_alias_info_1 (gimple stmt, struct alias_info *ai)
|
||||
/* ??? For always executed direct dereferences we can
|
||||
apply TBAA-pruning to their escape set. */
|
||||
|
||||
/* If this is a store operation, mark OP as being
|
||||
dereferenced to store, otherwise mark it as being
|
||||
dereferenced to load. */
|
||||
if (num_stores > 0)
|
||||
pointer_set_insert (ai->dereferenced_ptrs_store, var);
|
||||
else
|
||||
pointer_set_insert (ai->dereferenced_ptrs_load, var);
|
||||
/* Mark OP as being dereferenced. */
|
||||
pointer_set_insert (ai->dereferenced_ptrs, var);
|
||||
|
||||
/* Update the frequency estimate for all the dereferences of
|
||||
pointer OP. */
|
||||
@ -2649,7 +2628,7 @@ update_alias_info_1 (gimple stmt, struct alias_info *ai)
|
||||
if (is_gimple_call (stmt)
|
||||
|| stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
|
||||
{
|
||||
pointer_set_insert (ai->dereferenced_ptrs_store, var);
|
||||
pointer_set_insert (ai->dereferenced_ptrs, var);
|
||||
pi->memory_tag_needed = 1;
|
||||
}
|
||||
}
|
||||
@ -2667,17 +2646,6 @@ update_alias_info_1 (gimple stmt, struct alias_info *ai)
|
||||
|
||||
mem_ref_stats->num_mem_stmts++;
|
||||
|
||||
/* Add all decls written to to the list of written variables. */
|
||||
if (gimple_has_lhs (stmt)
|
||||
&& TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME)
|
||||
{
|
||||
tree lhs = gimple_get_lhs (stmt);
|
||||
while (handled_component_p (lhs))
|
||||
lhs = TREE_OPERAND (lhs, 0);
|
||||
if (DECL_P (lhs))
|
||||
pointer_set_insert (ai->written_vars, lhs);
|
||||
}
|
||||
|
||||
/* Notice that we only update memory reference stats for symbols
|
||||
loaded and stored by the statement if the statement does not
|
||||
contain pointer dereferences and it is not a call/asm site.
|
||||
@ -2770,7 +2738,7 @@ setup_pointers_and_addressables (struct alias_info *ai)
|
||||
/* Since we don't keep track of volatile variables, assume that
|
||||
these pointers are used in indirect store operations. */
|
||||
if (TREE_THIS_VOLATILE (var))
|
||||
pointer_set_insert (ai->dereferenced_ptrs_store, var);
|
||||
pointer_set_insert (ai->dereferenced_ptrs, var);
|
||||
|
||||
num_pointers++;
|
||||
}
|
||||
@ -2845,8 +2813,7 @@ setup_pointers_and_addressables (struct alias_info *ai)
|
||||
array and create a symbol memory tag for them. */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (var)))
|
||||
{
|
||||
if ((pointer_set_contains (ai->dereferenced_ptrs_store, var)
|
||||
|| pointer_set_contains (ai->dereferenced_ptrs_load, var)))
|
||||
if (pointer_set_contains (ai->dereferenced_ptrs, var))
|
||||
{
|
||||
tree tag, old_tag;
|
||||
var_ann_t t_ann;
|
||||
@ -2872,11 +2839,6 @@ setup_pointers_and_addressables (struct alias_info *ai)
|
||||
|
||||
/* Associate the tag with pointer VAR. */
|
||||
set_symbol_mem_tag (var, tag);
|
||||
|
||||
/* If pointer VAR has been used in a store operation,
|
||||
then its memory tag must be marked as written-to. */
|
||||
if (pointer_set_contains (ai->dereferenced_ptrs_store, var))
|
||||
pointer_set_insert (ai->written_vars, tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3298,7 +3260,22 @@ get_smt_for (tree ptr, struct alias_info *ai)
|
||||
size_t i;
|
||||
tree tag;
|
||||
tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
|
||||
alias_set_type tag_set = get_alias_set (tag_type);
|
||||
alias_set_type tag_set;
|
||||
|
||||
/* Get the alias set to be used for the pointed-to memory. If that
|
||||
differs from what we would get from looking at the type adjust
|
||||
the tag_type to void to make sure we get a proper alias set from
|
||||
just looking at the SMT we create. */
|
||||
tag_set = get_alias_set (tag_type);
|
||||
if (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (ptr))
|
||||
/* This is overly conservative but we do not want to assign
|
||||
restrict alias sets here (which if they are not assigned
|
||||
are -2 but still "known"). */
|
||||
|| DECL_POINTER_ALIAS_SET_KNOWN_P (ptr))
|
||||
{
|
||||
tag_set = 0;
|
||||
tag_type = void_type_node;
|
||||
}
|
||||
|
||||
/* To avoid creating unnecessary memory tags, only create one memory tag
|
||||
per alias set class. Note that it may be tempting to group
|
||||
@ -3329,7 +3306,8 @@ get_smt_for (tree ptr, struct alias_info *ai)
|
||||
artificial variable representing the memory location
|
||||
pointed-to by PTR. */
|
||||
tag = symbol_mem_tag (ptr);
|
||||
if (tag == NULL_TREE)
|
||||
if (tag == NULL_TREE
|
||||
|| tag_set != get_alias_set (tag))
|
||||
tag = create_memory_tag (tag_type, true);
|
||||
|
||||
/* Add PTR to the POINTERS array. Note that we are not interested in
|
||||
|
Loading…
x
Reference in New Issue
Block a user