+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>
* config/arm/arm.md (mulsidi3, umulsidi3, mulsi3_highpart)
==>
&array[L]
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
canonicalize_addr_expr (tree *expr_p)
{
tree expr = *expr_p;
- tree ctype = TREE_TYPE (expr);
tree addr_expr = TREE_OPERAND (expr, 0);
- tree atype = TREE_TYPE (addr_expr);
- tree dctype, datype, ddatype, otype, obj_expr;
+ tree datype, ddatype, pddatype;
- /* Both cast and addr_expr types should be pointers. */
- if (!POINTER_TYPE_P (ctype) || !POINTER_TYPE_P (atype))
+ /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
+ if (!POINTER_TYPE_P (TREE_TYPE (expr))
+ || TREE_CODE (addr_expr) != ADDR_EXPR)
return;
/* 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)
return;
- /* Both cast and addr_expr types should address the same object type. */
- dctype = TREE_TYPE (ctype);
+ /* The pointer to element type shall be trivially convertible to
+ the expression pointer type. */
ddatype = TREE_TYPE (datype);
- if (!useless_type_conversion_p (dctype, ddatype))
- return;
-
- /* 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))
+ pddatype = build_pointer_type (ddatype);
+ if (!useless_type_conversion_p (pddatype, ddatype))
return;
/* The lower bound and element sizes must be constant. */
- if (!TYPE_SIZE_UNIT (dctype)
- || TREE_CODE (TYPE_SIZE_UNIT (dctype)) != INTEGER_CST
+ if (!TYPE_SIZE_UNIT (ddatype)
+ || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
|| !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
|| TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
return;
/* 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)),
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
+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>
PR fortran/33253
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-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
early optimizations. */
c[i] = 1;
}
-/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop2" } } */
-/* { dg-final { cleanup-tree-dump "forwprop?" } } */
-
-
+/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" } } */
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */
/* { 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
early optimizations. */
c[i] = 1;
}
-/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop2" } } */
+/* { dg-final { scan-tree-dump "t\\\[i.*\\\] = 1;" "forwprop1" } } */
/* { dg-final { cleanup-tree-dump "forwprop?" } } */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-forwprop" } */
+/* { dg-options "-O2 -fdump-tree-forwprop1" } */
struct A { int i; };
int
return locp->i;
}
-/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop2" } } */
-/* { dg-final { cleanup-tree-dump "forwprop?" } } */
+/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop1" } } */
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */
--- /dev/null
+/* { 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" } } */
if (quals & TYPE_QUAL_CONST)
pp_string (buffer, " const");
- else if (quals & TYPE_QUAL_VOLATILE)
- pp_string (buffer, "volatile");
- else if (quals & TYPE_QUAL_RESTRICT)
+ if (quals & TYPE_QUAL_VOLATILE)
+ pp_string (buffer, " volatile");
+ if (quals & TYPE_QUAL_RESTRICT)
pp_string (buffer, " restrict");
if (TYPE_REF_CAN_ALIAS_ALL (node))
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
- /* 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 ");
+ {
+ unsigned int quals = TYPE_QUALS (node);
- if (TYPE_NAME (node))
- dump_generic_node (buffer, TYPE_NAME (node), spc, flags, false);
- else
- print_struct_decl (buffer, node, spc, flags);
- break;
+ if (quals & TYPE_QUAL_CONST)
+ pp_string (buffer, "const ");
+ if (quals & TYPE_QUAL_VOLATILE)
+ pp_string (buffer, "volatile ");
+
+ /* 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:
NIY;
/* Make sure to possibly truncate late after offsetting. */
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);
}
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);
result = forward_propagate_addr_expr_1 (name, rhs, use_stmt,