This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR14841 and PR15838
- From: Steven Bosscher <stevenb at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: dnovillo at redhat dot com
- Date: Tue, 31 Aug 2004 18:10:39 +0200
- Subject: [PATCH] PR14841 and PR15838
- Organization: SUSE Labs
Hi,
We failed to catch turn loads from const struct and const array
initializers into constants. We'd catch them later in expr.c
during expand, but of course we can better do this in SSA CCP
because it exposes more optimization opportunities for all the
other tree optimizers.
Bootstrapped and tested on AMD64. OK?
Gr.
Steven
PR tree-optimization/14841
PR tree-optimization/15838
* tree-ssa-ccp.c (try_extract_const_array_ref): New function to
extract a constant from a constant array initializer.
(try_extract_const_component_ref): Likewise for const struct
initializers.
(evaluate_stmt): Use them.
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-ccp.c,v
retrieving revision 2.35
diff -c -3 -p -r2.35 tree-ssa-ccp.c
*** tree-ssa-ccp.c 29 Aug 2004 15:42:42 -0000 2.35
--- tree-ssa-ccp.c 31 Aug 2004 15:05:05 -0000
*************** ccp_finalize (void)
*** 622,628 ****
}
-
/* Compute the meet operator between VAL1 and VAL2:
any M UNDEFINED = any
--- 622,627 ----
*************** ccp_fold (tree stmt)
*** 957,962 ****
--- 956,1022 ----
}
+ /* Return the tree representing the element referenced by T.
+ T must be an ARRAY_REF to a constant array with a constant index. */
+
+ static tree
+ try_extract_const_array_ref (tree t)
+ {
+ value *value;
+ tree var = TREE_OPERAND (t, 0);
+ tree idx = TREE_OPERAND (t, 1);
+ tree array = DECL_INITIAL (var);
+
+ if (TREE_CODE (idx) == SSA_NAME
+ && (value = get_value (idx))
+ && value->lattice_val == CONSTANT
+ && TREE_CODE (value->const_val) == INTEGER_CST)
+ idx = value->const_val;
+
+ if (TREE_CODE (idx) == INTEGER_CST
+ && compare_tree_int (idx, list_length (CONSTRUCTOR_ELTS (array))) < 0)
+ {
+ /* Try to extract the referenced element. */
+ tree elt;
+ HOST_WIDE_INT i;
+
+ for (elt = CONSTRUCTOR_ELTS (array), i = TREE_INT_CST_LOW (idx);
+ elt != 0 && i != 0;
+ i--, elt = TREE_CHAIN (elt))
+ /* Find that element. */ ;
+
+ if (elt)
+ return TREE_VALUE (elt);
+ }
+
+ return NULL_TREE;
+ }
+
+
+ /* Return the tree representing the element referenced by T.
+ T must be a COMPONENT_REF to a constant struct. */
+
+ static tree
+ try_extract_const_component_ref (tree t)
+ {
+ tree var = TREE_OPERAND (t, 0);
+ tree field = TREE_OPERAND (t, 1);
+ tree constructor = DECL_INITIAL (var);
+ tree elt;
+
+ for (elt = CONSTRUCTOR_ELTS (constructor);
+ elt;
+ elt = TREE_CHAIN (elt))
+ {
+ if (TREE_CODE (TREE_PURPOSE (elt)) == FIELD_DECL
+ && fields_compatible_p (TREE_PURPOSE (elt), field))
+ return TREE_VALUE (elt);
+ }
+
+ return NULL_TREE;
+ }
+
+
/* Evaluate statement STMT. */
static value
*************** evaluate_stmt (tree stmt)
*** 970,983 ****
to fold the statement to determine the constant value. */
if (likelyvalue == CONSTANT)
simplified = ccp_fold (stmt);
- /* If the statement is likely to have a VARYING result, then do not
- bother folding the statement. */
- else if (likelyvalue == VARYING)
- simplified = get_rhs (stmt);
- /* Otherwise the statement is likely to have an UNDEFINED value and
- there will be nothing to do. */
else
! simplified = NULL_TREE;
if (simplified && is_gimple_min_invariant (simplified))
{
--- 1030,1071 ----
to fold the statement to determine the constant value. */
if (likelyvalue == CONSTANT)
simplified = ccp_fold (stmt);
else
! {
! tree var, rhs = get_rhs (stmt);
!
! /* If the statement is likely to have a VARYING result, then do not
! bother folding the statement. */
! if (likelyvalue == VARYING)
! simplified = rhs;
!
! /* If the statement is a load from a constant array with a constant
! index, or from a const struct, try to extract the referenced
! constant. */
! else if (((TREE_CODE (rhs) == ARRAY_REF
! && TREE_CODE (var = TREE_OPERAND (rhs, 0)) == VAR_DECL
! && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
! || (TREE_CODE (rhs) == COMPONENT_REF
! && TREE_CODE (var = TREE_OPERAND (rhs, 0)) == VAR_DECL
! && TREE_CODE (TREE_TYPE (var)) == RECORD_TYPE
! && TREE_CODE (TREE_OPERAND (rhs, 1)) == FIELD_DECL))
! && TREE_READONLY (var)
! && DECL_INITIAL (var)
! && TREE_CODE (DECL_INITIAL (var)) == CONSTRUCTOR
! && ! TREE_SIDE_EFFECTS (DECL_INITIAL (var)))
! {
! if (TREE_CODE (rhs) == ARRAY_REF)
! /* try_extract_const_{array,component}_ref return NULL_TREE
! if a constant could not be extacted. */
! simplified = try_extract_const_array_ref (rhs);
! else
! simplified = try_extract_const_component_ref (rhs);
! }
! else
! /* Otherwise the statement is likely to have an UNDEFINED value and
! there will be nothing to do. */
! simplified = NULL_TREE;
! }
if (simplified && is_gimple_min_invariant (simplified))
{