Commit 04d86531 by Richard Guenther Committed by Richard Biener

re PR tree-optimization/33291 (a+=2; a+=2 not simplified to a+=4; with -O3 …

re PR tree-optimization/33291 (a+=2; a+=2  not simplified to  a+=4;  with -O3   (ok with gcc-4.2.1))

2007-09-04  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/33291
	* tree-pretty-print.c (dump_generic_node): Dump all
	qualifiers for pointer types, not only first.  Dump
	qualifiers for aggregate types as well.
	* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Always
	use the canonical type for building ARRAY_REFs.
	* gimplify.c (canonicalize_addr_expr): Clean up.  The
	correct validness check is compatibility of the pointer
	types.  Always use the canonical type for building
	ARRAY_REFs and ADDR_EXPRs.
	* tree-ssa-forwprop.c (forward_propagate_addr_expr): Revert
	change that disabled propagation of ADDR_EXPRs into statements
	with volatile ops.

	* gcc.dg/volatile2.c: New testcase.
	* gcc.dg/pr32721.c: Adjust volatile reference pattern.
	* gcc.dg/tree-ssa/forwprop-1.c: Remove xfail.
	* gcc.dg/tree-ssa/forwprop-2.c: Likewise.
	* gcc.dg/tree-ssa/pr17141-1.c: Likewise.

From-SVN: r128068
parent fc7a6a0d
2007-09-04 Richard Guenther <rguenther@suse.de>
PR tree-optimization/33291
* tree-pretty-print.c (dump_generic_node): Dump all
qualifiers for pointer types, not only first. Dump
qualifiers for aggregate types as well.
* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Always
use the canonical type for building ARRAY_REFs.
* gimplify.c (canonicalize_addr_expr): Clean up. The
correct validness check is compatibility of the pointer
types. Always use the canonical type for building
ARRAY_REFs and ADDR_EXPRs.
* tree-ssa-forwprop.c (forward_propagate_addr_expr): Revert
change that disabled propagation of ADDR_EXPRs into statements
with volatile ops.
2007-09-03 Zack Weinberg <zack@codesourcery.com> 2007-09-03 Zack Weinberg <zack@codesourcery.com>
* config/arm/arm.md (mulsidi3, umulsidi3, mulsi3_highpart) * config/arm/arm.md (mulsidi3, umulsidi3, mulsi3_highpart)
......
...@@ -1572,50 +1572,46 @@ canonicalize_component_ref (tree *expr_p) ...@@ -1572,50 +1572,46 @@ canonicalize_component_ref (tree *expr_p)
==> ==>
&array[L] &array[L]
where L is the lower bound. For simplicity, only do this for constant where L is the lower bound. For simplicity, only do this for constant
lower bound. */ lower bound.
The constraint is that the type of &array[L] is trivially convertible
to T *. */
static void static void
canonicalize_addr_expr (tree *expr_p) canonicalize_addr_expr (tree *expr_p)
{ {
tree expr = *expr_p; tree expr = *expr_p;
tree ctype = TREE_TYPE (expr);
tree addr_expr = TREE_OPERAND (expr, 0); tree addr_expr = TREE_OPERAND (expr, 0);
tree atype = TREE_TYPE (addr_expr); tree datype, ddatype, pddatype;
tree dctype, datype, ddatype, otype, obj_expr;
/* Both cast and addr_expr types should be pointers. */ /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
if (!POINTER_TYPE_P (ctype) || !POINTER_TYPE_P (atype)) if (!POINTER_TYPE_P (TREE_TYPE (expr))
|| TREE_CODE (addr_expr) != ADDR_EXPR)
return; return;
/* The addr_expr type should be a pointer to an array. */ /* The addr_expr type should be a pointer to an array. */
datype = TREE_TYPE (atype); datype = TREE_TYPE (TREE_TYPE (addr_expr));
if (TREE_CODE (datype) != ARRAY_TYPE) if (TREE_CODE (datype) != ARRAY_TYPE)
return; return;
/* Both cast and addr_expr types should address the same object type. */ /* The pointer to element type shall be trivially convertible to
dctype = TREE_TYPE (ctype); the expression pointer type. */
ddatype = TREE_TYPE (datype); ddatype = TREE_TYPE (datype);
if (!useless_type_conversion_p (dctype, ddatype)) pddatype = build_pointer_type (ddatype);
return; if (!useless_type_conversion_p (pddatype, ddatype))
/* The addr_expr and the object type should match. */
obj_expr = TREE_OPERAND (addr_expr, 0);
otype = TREE_TYPE (obj_expr);
if (!useless_type_conversion_p (datype, otype))
return; return;
/* The lower bound and element sizes must be constant. */ /* The lower bound and element sizes must be constant. */
if (!TYPE_SIZE_UNIT (dctype) if (!TYPE_SIZE_UNIT (ddatype)
|| TREE_CODE (TYPE_SIZE_UNIT (dctype)) != INTEGER_CST || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
|| !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype)) || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
|| TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST) || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
return; return;
/* All checks succeeded. Build a new node to merge the cast. */ /* All checks succeeded. Build a new node to merge the cast. */
*expr_p = build4 (ARRAY_REF, dctype, obj_expr, *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
TYPE_MIN_VALUE (TYPE_DOMAIN (datype)), TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
*expr_p = build1 (ADDR_EXPR, ctype, *expr_p); *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
} }
/* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions
......
2007-09-04 Richard Guenther <rguenther@suse.de>
PR tree-optimization/33291
* gcc.dg/volatile2.c: New testcase.
* gcc.dg/pr32721.c: Adjust volatile reference pattern.
* gcc.dg/tree-ssa/forwprop-1.c: Remove xfail.
* gcc.dg/tree-ssa/forwprop-2.c: Likewise.
* gcc.dg/tree-ssa/pr17141-1.c: Likewise.
2007-09-03 Jerry DeLisle <jvdelisle@gcc.gnu.org> 2007-09-03 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/33253 PR fortran/33253
...@@ -14,5 +14,5 @@ spinlock1 = &spinlock[1]; ...@@ -14,5 +14,5 @@ spinlock1 = &spinlock[1];
while (*spinlock0); while (*spinlock0);
} }
/* { dg-final { scan-tree-dump "={v} spinlock.0." "optimized" } } */ /* { dg-final { scan-tree-dump "={v} \\*spinlock0" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-forwprop" } */ /* { dg-options "-O2 -fdump-tree-forwprop1" } */
/* We should be able to optimize this to b->t[i] = 1 during /* We should be able to optimize this to b->t[i] = 1 during
early optimizations. */ early optimizations. */
...@@ -15,8 +15,5 @@ void f(struct a * b, __SIZE_TYPE__ i) ...@@ -15,8 +15,5 @@ void f(struct a * b, __SIZE_TYPE__ i)
c[i] = 1; c[i] = 1;
} }
/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" } } */
/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop2" } } */ /* { dg-final { cleanup-tree-dump "forwprop1" } } */
/* { dg-final { cleanup-tree-dump "forwprop?" } } */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-forwprop" } */ /* { dg-options "-O2 -fdump-tree-forwprop1" } */
/* We should be able to optimize this to b->t[i] = 1 during /* We should be able to optimize this to b->t[i] = 1 during
early optimizations. */ early optimizations. */
...@@ -17,6 +17,5 @@ void f(__SIZE_TYPE__ i) ...@@ -17,6 +17,5 @@ void f(__SIZE_TYPE__ i)
c[i] = 1; c[i] = 1;
} }
/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" } } */
/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop2" } } */
/* { dg-final { cleanup-tree-dump "forwprop?" } } */ /* { dg-final { cleanup-tree-dump "forwprop?" } } */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-forwprop" } */ /* { dg-options "-O2 -fdump-tree-forwprop1" } */
struct A { int i; }; struct A { int i; };
int int
...@@ -11,6 +11,5 @@ foo(struct A *locp, int str) ...@@ -11,6 +11,5 @@ foo(struct A *locp, int str)
return locp->i; return locp->i;
} }
/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop1" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump "locp.*->i =" "forwprop1" } } */
/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop2" } } */ /* { dg-final { cleanup-tree-dump "forwprop1" } } */
/* { dg-final { cleanup-tree-dump "forwprop?" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple -fdump-tree-optimized" } */
struct GTeth_desc
{
unsigned ed_cmdsts;
};
struct GTeth_softc
{
struct GTeth_desc txq_desc[32];
};
void foo(struct GTeth_softc *sc)
{
/* Verify that we retain the cast to (volatile struct GTeth_desc *)
after gimplification and that we keep the volatileness on the
store until after optimization. */
volatile struct GTeth_desc *p = &sc->txq_desc[0];
p->ed_cmdsts = 0;
}
/* { dg-final { scan-tree-dump "\\(volatile struct GTeth_desc \\*\\) D" "gimple" } } */
/* { dg-final { scan-tree-dump "{v}" "optimized" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
...@@ -622,9 +622,9 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, ...@@ -622,9 +622,9 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
if (quals & TYPE_QUAL_CONST) if (quals & TYPE_QUAL_CONST)
pp_string (buffer, " const"); pp_string (buffer, " const");
else if (quals & TYPE_QUAL_VOLATILE) if (quals & TYPE_QUAL_VOLATILE)
pp_string (buffer, "volatile"); pp_string (buffer, " volatile");
else if (quals & TYPE_QUAL_RESTRICT) if (quals & TYPE_QUAL_RESTRICT)
pp_string (buffer, " restrict"); pp_string (buffer, " restrict");
if (TYPE_REF_CAN_ALIAS_ALL (node)) if (TYPE_REF_CAN_ALIAS_ALL (node))
...@@ -718,17 +718,26 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, ...@@ -718,17 +718,26 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case RECORD_TYPE: case RECORD_TYPE:
case UNION_TYPE: case UNION_TYPE:
case QUAL_UNION_TYPE: case QUAL_UNION_TYPE:
/* Print the name of the structure. */ {
if (TREE_CODE (node) == RECORD_TYPE) unsigned int quals = TYPE_QUALS (node);
pp_string (buffer, "struct ");
else if (TREE_CODE (node) == UNION_TYPE)
pp_string (buffer, "union ");
if (TYPE_NAME (node)) if (quals & TYPE_QUAL_CONST)
dump_generic_node (buffer, TYPE_NAME (node), spc, flags, false); pp_string (buffer, "const ");
else if (quals & TYPE_QUAL_VOLATILE)
print_struct_decl (buffer, node, spc, flags); pp_string (buffer, "volatile ");
break;
/* Print the name of the structure. */
if (TREE_CODE (node) == RECORD_TYPE)
pp_string (buffer, "struct ");
else if (TREE_CODE (node) == UNION_TYPE)
pp_string (buffer, "union ");
if (TYPE_NAME (node))
dump_generic_node (buffer, TYPE_NAME (node), spc, flags, false);
else
print_struct_decl (buffer, node, spc, flags);
break;
}
case LANG_TYPE: case LANG_TYPE:
NIY; NIY;
......
...@@ -1644,7 +1644,7 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type) ...@@ -1644,7 +1644,7 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
/* Make sure to possibly truncate late after offsetting. */ /* Make sure to possibly truncate late after offsetting. */
idx = fold_convert (idx_type, idx); idx = fold_convert (idx_type, idx);
return build4 (ARRAY_REF, orig_type, base, idx, NULL_TREE, NULL_TREE); return build4 (ARRAY_REF, elt_type, base, idx, NULL_TREE, NULL_TREE);
} }
......
...@@ -717,13 +717,6 @@ forward_propagate_addr_expr (tree name, tree rhs) ...@@ -717,13 +717,6 @@ forward_propagate_addr_expr (tree name, tree rhs)
continue; continue;
} }
/* If the use_stmt has side-effects, don't propagate into it. */
if (stmt_ann (use_stmt)->has_volatile_ops)
{
all = false;
continue;
}
push_stmt_changes (&use_stmt); push_stmt_changes (&use_stmt);
result = forward_propagate_addr_expr_1 (name, rhs, use_stmt, result = forward_propagate_addr_expr_1 (name, rhs, use_stmt,
......
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