Commit 03c4c2e0 by Richard Guenther Committed by Richard Biener

re PR tree-optimization/33870 (miscompiles sqlite)

2007-10-27  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/33870
	* tree-ssa-operands.c (add_vars_for_offset): Reduce code
	duplication.  Remove redundant call to access_can_touch_variable.
	(add_vars_for_bitmap): New helper for recursing over MPT contents.
	(add_virtual_operand): Use it.

	* gcc.dg/tree-ssa/alias-15.c: New testcase.
	* gcc.c-torture/execute/pr33870.c: Likewise.

From-SVN: r129675
parent 2bd1ffcd
2007-10-27 Richard Guenther <rguenther@suse.de>
PR tree-optimization/33870
* tree-ssa-operands.c (add_vars_for_offset): Reduce code
duplication. Remove redundant call to access_can_touch_variable.
(add_vars_for_bitmap): New helper for recursing over MPT contents.
(add_virtual_operand): Use it.
2007-10-26 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> 2007-10-26 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR fortran/31608 PR fortran/31608
2007-10-27 Richard Guenther <rguenther@suse.de>
PR tree-optimization/33870
* gcc.dg/tree-ssa/alias-15.c: New testcase.
* gcc.c-torture/execute/pr33870.c: Likewise.
2007-10-26 Jerry DeLisle <jvdelisle@gcc.gnu.org> 2007-10-26 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/33162 PR fortran/33162
extern void abort (void);
typedef struct PgHdr PgHdr;
typedef unsigned char u8;
struct PgHdr {
unsigned int pgno;
PgHdr *pNextHash, *pPrevHash;
PgHdr *pNextFree, *pPrevFree;
PgHdr *pNextAll;
u8 inJournal;
short int nRef;
PgHdr *pDirty, *pPrevDirty;
unsigned int notUsed;
};
static inline PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB)
{
PgHdr result;
PgHdr *pTail;
pTail = &result;
while( pA && pB ){
if( pA->pgno<pB->pgno ){
pTail->pDirty = pA;
pTail = pA;
pA = pA->pDirty;
}else{
pTail->pDirty = pB;
pTail = pB;
pB = pB->pDirty;
}
}
if( pA ){
pTail->pDirty = pA;
}else if( pB ){
pTail->pDirty = pB;
}else{
pTail->pDirty = 0;
}
return result.pDirty;
}
PgHdr * __attribute__((noinline)) sort_pagelist(PgHdr *pIn)
{
PgHdr *a[25], *p;
int i;
__builtin_memset (a, 0, sizeof (a));
while( pIn ){
p = pIn;
pIn = p->pDirty;
p->pDirty = 0;
for(i=0; i<25 -1; i++){
if( a[i]==0 ){
a[i] = p;
break;
}else{
p = merge_pagelist(a[i], p);
a[i] = 0;
}
}
if( i==25 -1 ){
a[i] = merge_pagelist(a[i], p);
}
}
p = a[0];
for(i=1; i<25; i++){
p = merge_pagelist (p, a[i]);
}
return p;
}
int main()
{
PgHdr a[5];
PgHdr *p;
a[0].pgno = 5;
a[0].pDirty = &a[1];
a[1].pgno = 4;
a[1].pDirty = &a[2];
a[2].pgno = 1;
a[2].pDirty = &a[3];
a[3].pgno = 3;
a[3].pDirty = 0;
p = sort_pagelist (&a[0]);
if (p->pDirty == p)
abort ();
return 0;
}
/* { dg-do compile } */
/* { dg-options "-O -fno-early-inlining -fdump-tree-salias-vops-details" } */
struct foo {
int a;
struct X {
int b[4];
} b;
} m;
static inline struct X *wrap(struct X *p) { return p; }
int test2(void)
{
struct X *p = wrap(&m.b);
/* Both memory references need to alias the same SFT. */
return p->b[3] - m.b.b[3];
}
/* { dg-final { scan-tree-dump "SFT.1 created for var m offset 128" "salias" } } */
/* { dg-final { scan-tree-dump-times "VUSE <SFT.1_" 2 "salias" } } */
/* { dg-final { cleanup-tree-dump "salias" } } */
...@@ -1419,55 +1419,57 @@ add_vars_for_offset (tree full_ref, tree var, HOST_WIDE_INT offset, ...@@ -1419,55 +1419,57 @@ add_vars_for_offset (tree full_ref, tree var, HOST_WIDE_INT offset,
} }
else if (TREE_CODE (var) == STRUCT_FIELD_TAG) else if (TREE_CODE (var) == STRUCT_FIELD_TAG)
{ {
if (size == -1) bool added = false;
subvar_t sv = get_subvars_for_var (SFT_PARENT_VAR (var));
for (; sv; sv = sv->next)
{ {
bool added = false; /* Once we hit the end of the parts that could touch,
subvar_t sv = get_subvars_for_var (SFT_PARENT_VAR (var)); stop looking. */
for (; sv; sv = sv->next) if (size != -1
{ && SFT_OFFSET (var) + offset + size <= SFT_OFFSET (sv->var))
if (overlap_subvar (SFT_OFFSET (var) + offset, size, break;
sv->var, NULL) if (overlap_subvar (SFT_OFFSET (var) + offset, size, sv->var, NULL))
&& access_can_touch_variable (full_ref, sv->var,
offset, size))
{
added = true;
if (is_def)
append_vdef (sv->var);
else
append_vuse (sv->var);
}
}
return added;
}
else
{
bool added = false;
subvar_t sv = get_subvars_for_var (SFT_PARENT_VAR (var));
for (; sv; sv = sv->next)
{ {
/* Once we hit the end of the parts that could touch, added = true;
stop looking. */ if (is_def)
if (SFT_OFFSET (var) + offset + size <= SFT_OFFSET (sv->var)) append_vdef (sv->var);
break; else
if (overlap_subvar (SFT_OFFSET (var) + offset, size, append_vuse (sv->var);
sv->var, NULL)
&& access_can_touch_variable (full_ref, sv->var, offset,
size))
{
added = true;
if (is_def)
append_vdef (sv->var);
else
append_vuse (sv->var);
}
} }
return added;
} }
return added;
} }
return false; return false;
} }
/* Add all aliases from ALIASES as virtual operands for the access
FULL_REF at OFFSET and size SIZE. IS_CALL_SITE is true if the
stmt of the reference is a call. IS_DEF is true if we should add
VDEF virtual operands, otherwise we'll add VUSEs. *NONE_ADDED
is set to false once the first virtual operand was added. */
static void
add_vars_for_bitmap (bitmap aliases, tree full_ref,
HOST_WIDE_INT offset, HOST_WIDE_INT size,
bool is_call_site, bool is_def, bool *none_added)
{
bitmap_iterator bi;
unsigned int i;
EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
{
tree al = referenced_var (i);
if (TREE_CODE (al) == MEMORY_PARTITION_TAG)
add_vars_for_bitmap (MPT_SYMBOLS (al), full_ref,
offset, size, is_call_site, is_def, none_added);
else
*none_added &= !add_vars_for_offset (full_ref, al, offset, size,
is_call_site, is_def);
}
}
/* Add VAR to the virtual operands array. FLAGS is as in /* Add VAR to the virtual operands array. FLAGS is as in
get_expr_operands. FULL_REF is a tree that contains the entire get_expr_operands. FULL_REF is a tree that contains the entire
pointer dereference expression, if available, or NULL otherwise. pointer dereference expression, if available, or NULL otherwise.
...@@ -1530,24 +1532,17 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags, ...@@ -1530,24 +1532,17 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
} }
else else
{ {
bitmap_iterator bi; bool none_added = true;
unsigned int i;
tree al;
/* The variable is aliased. Add its aliases to the virtual /* The variable is aliased. Add its aliases to the virtual
operands. */ operands. */
gcc_assert (!bitmap_empty_p (aliases)); gcc_assert (!bitmap_empty_p (aliases));
add_vars_for_bitmap (aliases, full_ref, offset, size,
is_call_site, flags & opf_def, &none_added);
if (flags & opf_def) if (flags & opf_def)
{ {
bool none_added = true;
EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
{
al = referenced_var (i);
none_added &= !add_vars_for_offset (full_ref, al, offset, size,
is_call_site, true);
}
/* If the variable is also an alias tag, add a virtual /* If the variable is also an alias tag, add a virtual
operand for it, otherwise we will miss representing operand for it, otherwise we will miss representing
references to the members of the variable's alias set. references to the members of the variable's alias set.
...@@ -1566,15 +1561,6 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags, ...@@ -1566,15 +1561,6 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
} }
else else
{ {
bool none_added = true;
EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
{
al = referenced_var (i);
none_added &= !add_vars_for_offset (full_ref, al, offset, size,
is_call_site, false);
}
/* Even if no aliases have been added, we still need to /* Even if no aliases have been added, we still need to
establish def-use and use-def chains, lest establish def-use and use-def chains, lest
transformations think that this is not a memory transformations think that this is not a memory
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment