This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Prepare CCP for bit-CCP
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 3 Aug 2010 15:02:17 +0200 (CEST)
- Subject: [PATCH] Prepare CCP for bit-CCP
This prepares CCP to handle bitwise constant values.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Richard.
2010-08-03 Richard Guenther <rguenther@suse.de>
* tree-ssa-ccp.c (get_constant_value): New function.
(get_rhs_assign_op_for_ccp): Remove.
(valueize_op): New function.
(ccp_fold): Use get_constant_value and valueize_op.
(fold_const_aggregate_ref): Likewise.
(ccp_fold_stmt): Likewise.
(visit_assignment): Simplify.
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c.orig 2010-08-02 13:53:56.000000000 +0200
--- gcc/tree-ssa-ccp.c 2010-08-02 14:04:05.000000000 +0200
*************** get_value (tree var)
*** 281,286 ****
--- 281,297 ----
return val;
}
+ /* Return the constant tree value associated with VAR. */
+
+ static inline tree
+ get_constant_value (tree var)
+ {
+ prop_value_t *val = get_value (var);
+ if (val && val->lattice_val == CONSTANT)
+ return val->value;
+ return NULL_TREE;
+ }
+
/* Sets the value associated with VAR to VARYING. */
static inline void
*************** ccp_visit_phi_node (gimple phi)
*** 782,800 ****
return SSA_PROP_NOT_INTERESTING;
}
! /* Get operand number OPNR from the rhs of STMT. Before returning it,
! simplify it to a constant if possible. */
static tree
! get_rhs_assign_op_for_ccp (gimple stmt, int opnr)
{
- tree op = gimple_op (stmt, opnr);
-
if (TREE_CODE (op) == SSA_NAME)
{
! prop_value_t *val = get_value (op);
! if (val->lattice_val == CONSTANT)
! op = get_value (op)->value;
}
return op;
}
--- 793,808 ----
return SSA_PROP_NOT_INTERESTING;
}
! /* Return the constant value for OP or OP otherwise. */
static tree
! valueize_op (tree op)
{
if (TREE_CODE (op) == SSA_NAME)
{
! tree tem = get_constant_value (op);
! if (tem)
! return tem;
}
return op;
}
*************** ccp_fold (gimple stmt)
*** 829,835 ****
{
/* If the RHS is an SSA_NAME, return its known constant value,
if any. */
! return get_value (rhs)->value;
}
/* Handle propagating invariant addresses into address operations.
The folding we do here matches that in tree-ssa-forwprop.c. */
--- 837,843 ----
{
/* If the RHS is an SSA_NAME, return its known constant value,
if any. */
! return get_constant_value (rhs);
}
/* Handle propagating invariant addresses into address operations.
The folding we do here matches that in tree-ssa-forwprop.c. */
*************** ccp_fold (gimple stmt)
*** 842,855 ****
if (TREE_CODE (*base) == MEM_REF
&& TREE_CODE (TREE_OPERAND (*base, 0)) == SSA_NAME)
{
! prop_value_t *val = get_value (TREE_OPERAND (*base, 0));
! if (val->lattice_val == CONSTANT
! && TREE_CODE (val->value) == ADDR_EXPR)
{
tree ret, save = *base;
tree new_base;
new_base = fold_build2 (MEM_REF, TREE_TYPE (*base),
! unshare_expr (val->value),
TREE_OPERAND (*base, 1));
/* We need to return a new tree, not modify the IL
or share parts of it. So play some tricks to
--- 850,863 ----
if (TREE_CODE (*base) == MEM_REF
&& TREE_CODE (TREE_OPERAND (*base, 0)) == SSA_NAME)
{
! tree val = get_constant_value (TREE_OPERAND (*base, 0));
! if (val
! && TREE_CODE (val) == ADDR_EXPR)
{
tree ret, save = *base;
tree new_base;
new_base = fold_build2 (MEM_REF, TREE_TYPE (*base),
! unshare_expr (val),
TREE_OPERAND (*base, 1));
/* We need to return a new tree, not modify the IL
or share parts of it. So play some tricks to
*************** ccp_fold (gimple stmt)
*** 873,881 ****
list = NULL_TREE;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
{
! if (TREE_CODE (val) == SSA_NAME
! && get_value (val)->lattice_val == CONSTANT)
! val = get_value (val)->value;
if (TREE_CODE (val) == INTEGER_CST
|| TREE_CODE (val) == REAL_CST
|| TREE_CODE (val) == FIXED_CST)
--- 881,887 ----
list = NULL_TREE;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
{
! val = valueize_op (val);
if (TREE_CODE (val) == INTEGER_CST
|| TREE_CODE (val) == REAL_CST
|| TREE_CODE (val) == FIXED_CST)
*************** ccp_fold (gimple stmt)
*** 894,914 ****
|| TREE_CODE (rhs) == IMAGPART_EXPR)
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
{
! prop_value_t *val = get_value (TREE_OPERAND (rhs, 0));
! if (val->lattice_val == CONSTANT)
return fold_unary_loc (EXPR_LOCATION (rhs),
! TREE_CODE (rhs),
! TREE_TYPE (rhs), val->value);
}
else if (TREE_CODE (rhs) == MEM_REF
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
{
! prop_value_t *val = get_value (TREE_OPERAND (rhs, 0));
! if (val->lattice_val == CONSTANT
! && TREE_CODE (val->value) == ADDR_EXPR)
{
tree tem = fold_build2 (MEM_REF, TREE_TYPE (rhs),
! unshare_expr (val->value),
TREE_OPERAND (rhs, 1));
if (tem)
rhs = tem;
--- 900,920 ----
|| TREE_CODE (rhs) == IMAGPART_EXPR)
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
{
! tree val = get_constant_value (TREE_OPERAND (rhs, 0));
! if (val)
return fold_unary_loc (EXPR_LOCATION (rhs),
! TREE_CODE (rhs),
! TREE_TYPE (rhs), val);
}
else if (TREE_CODE (rhs) == MEM_REF
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
{
! tree val = get_constant_value (TREE_OPERAND (rhs, 0));
! if (val
! && TREE_CODE (val) == ADDR_EXPR)
{
tree tem = fold_build2 (MEM_REF, TREE_TYPE (rhs),
! unshare_expr (val),
TREE_OPERAND (rhs, 1));
if (tem)
rhs = tem;
*************** ccp_fold (gimple stmt)
*** 927,933 ****
Note that we know the single operand must be a constant,
so this should almost always return a simplified RHS. */
tree lhs = gimple_assign_lhs (stmt);
! tree op0 = get_rhs_assign_op_for_ccp (stmt, 1);
/* Conversions are useless for CCP purposes if they are
value-preserving. Thus the restrictions that
--- 933,939 ----
Note that we know the single operand must be a constant,
so this should almost always return a simplified RHS. */
tree lhs = gimple_assign_lhs (stmt);
! tree op0 = valueize_op (gimple_assign_rhs1 (stmt));
/* Conversions are useless for CCP purposes if they are
value-preserving. Thus the restrictions that
*************** ccp_fold (gimple stmt)
*** 958,965 ****
case GIMPLE_BINARY_RHS:
{
/* Handle binary operators that can appear in GIMPLE form. */
! tree op0 = get_rhs_assign_op_for_ccp (stmt, 1);
! tree op1 = get_rhs_assign_op_for_ccp (stmt, 2);
/* Translate &x + CST into an invariant form suitable for
further propagation. */
--- 964,971 ----
case GIMPLE_BINARY_RHS:
{
/* Handle binary operators that can appear in GIMPLE form. */
! tree op0 = valueize_op (gimple_assign_rhs1 (stmt));
! tree op1 = valueize_op (gimple_assign_rhs2 (stmt));
/* Translate &x + CST into an invariant form suitable for
further propagation. */
*************** ccp_fold (gimple stmt)
*** 980,989 ****
case GIMPLE_TERNARY_RHS:
{
! /* Handle binary operators that can appear in GIMPLE form. */
! tree op0 = get_rhs_assign_op_for_ccp (stmt, 1);
! tree op1 = get_rhs_assign_op_for_ccp (stmt, 2);
! tree op2 = get_rhs_assign_op_for_ccp (stmt, 3);
return fold_ternary_loc (loc, subcode,
gimple_expr_type (stmt), op0, op1, op2);
--- 986,995 ----
case GIMPLE_TERNARY_RHS:
{
! /* Handle ternary operators that can appear in GIMPLE form. */
! tree op0 = valueize_op (gimple_assign_rhs1 (stmt));
! tree op1 = valueize_op (gimple_assign_rhs2 (stmt));
! tree op2 = valueize_op (gimple_assign_rhs3 (stmt));
return fold_ternary_loc (loc, subcode,
gimple_expr_type (stmt), op0, op1, op2);
*************** ccp_fold (gimple stmt)
*** 997,1011 ****
case GIMPLE_CALL:
{
! tree fn = gimple_call_fn (stmt);
! prop_value_t *val;
!
! if (TREE_CODE (fn) == SSA_NAME)
! {
! val = get_value (fn);
! if (val->lattice_val == CONSTANT)
! fn = val->value;
! }
if (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
--- 1003,1009 ----
case GIMPLE_CALL:
{
! tree fn = valueize_op (gimple_call_fn (stmt));
if (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
*************** ccp_fold (gimple stmt)
*** 1014,1028 ****
tree call, retval;
unsigned i;
for (i = 0; i < gimple_call_num_args (stmt); ++i)
! {
! args[i] = gimple_call_arg (stmt, i);
! if (TREE_CODE (args[i]) == SSA_NAME)
! {
! val = get_value (args[i]);
! if (val->lattice_val == CONSTANT)
! args[i] = val->value;
! }
! }
call = build_call_array_loc (loc,
gimple_call_return_type (stmt),
fn, gimple_call_num_args (stmt), args);
--- 1012,1018 ----
tree call, retval;
unsigned i;
for (i = 0; i < gimple_call_num_args (stmt); ++i)
! args[i] = valueize_op (gimple_call_arg (stmt, i));
call = build_call_array_loc (loc,
gimple_call_return_type (stmt),
fn, gimple_call_num_args (stmt), args);
*************** ccp_fold (gimple stmt)
*** 1038,1077 ****
case GIMPLE_COND:
{
/* Handle comparison operators that can appear in GIMPLE form. */
! tree op0 = gimple_cond_lhs (stmt);
! tree op1 = gimple_cond_rhs (stmt);
enum tree_code code = gimple_cond_code (stmt);
-
- /* Simplify the operands down to constants when appropriate. */
- if (TREE_CODE (op0) == SSA_NAME)
- {
- prop_value_t *val = get_value (op0);
- if (val->lattice_val == CONSTANT)
- op0 = val->value;
- }
-
- if (TREE_CODE (op1) == SSA_NAME)
- {
- prop_value_t *val = get_value (op1);
- if (val->lattice_val == CONSTANT)
- op1 = val->value;
- }
-
return fold_binary_loc (loc, code, boolean_type_node, op0, op1);
}
case GIMPLE_SWITCH:
{
! tree rhs = gimple_switch_index (stmt);
!
! if (TREE_CODE (rhs) == SSA_NAME)
! {
! /* If the RHS is an SSA_NAME, return its known constant value,
! if any. */
! return get_value (rhs)->value;
! }
!
! return rhs;
}
default:
--- 1028,1043 ----
case GIMPLE_COND:
{
/* Handle comparison operators that can appear in GIMPLE form. */
! tree op0 = valueize_op (gimple_cond_lhs (stmt));
! tree op1 = valueize_op (gimple_cond_rhs (stmt));
enum tree_code code = gimple_cond_code (stmt);
return fold_binary_loc (loc, code, boolean_type_node, op0, op1);
}
case GIMPLE_SWITCH:
{
! /* Return the constant switch index. */
! return valueize_op (gimple_switch_index (stmt));
}
default:
*************** ccp_fold (gimple stmt)
*** 1086,1095 ****
tree
fold_const_aggregate_ref (tree t)
{
- prop_value_t *value;
tree base, ctor, idx, field;
unsigned HOST_WIDE_INT cnt;
tree cfield, cval;
if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
return get_symbol_constant_value (t);
--- 1052,1061 ----
tree
fold_const_aggregate_ref (tree t)
{
tree base, ctor, idx, field;
unsigned HOST_WIDE_INT cnt;
tree cfield, cval;
+ tree tem;
if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
return get_symbol_constant_value (t);
*************** fold_const_aggregate_ref (tree t)
*** 1149,1158 ****
switch (TREE_CODE (idx))
{
case SSA_NAME:
! if ((value = get_value (idx))
! && value->lattice_val == CONSTANT
! && TREE_CODE (value->value) == INTEGER_CST)
! idx = value->value;
else
return NULL_TREE;
break;
--- 1115,1123 ----
switch (TREE_CODE (idx))
{
case SSA_NAME:
! if ((tem = get_constant_value (idx))
! && TREE_CODE (tem) == INTEGER_CST)
! idx = tem;
else
return NULL_TREE;
break;
*************** fold_const_aggregate_ref (tree t)
*** 1257,1265 ****
/* Get the base object we are accessing. */
base = TREE_OPERAND (t, 0);
if (TREE_CODE (base) == SSA_NAME
! && (value = get_value (base))
! && value->lattice_val == CONSTANT)
! base = value->value;
if (TREE_CODE (base) != ADDR_EXPR)
return NULL_TREE;
base = TREE_OPERAND (base, 0);
--- 1222,1229 ----
/* Get the base object we are accessing. */
base = TREE_OPERAND (t, 0);
if (TREE_CODE (base) == SSA_NAME
! && (tem = get_constant_value (base)))
! base = tem;
if (TREE_CODE (base) != ADDR_EXPR)
return NULL_TREE;
base = TREE_OPERAND (base, 0);
*************** ccp_fold_stmt (gimple_stmt_iterator *gsi
*** 1477,1483 ****
case GIMPLE_CALL:
{
tree lhs = gimple_call_lhs (stmt);
! prop_value_t *val;
tree argt;
bool changed = false;
unsigned i;
--- 1441,1447 ----
case GIMPLE_CALL:
{
tree lhs = gimple_call_lhs (stmt);
! tree val;
tree argt;
bool changed = false;
unsigned i;
*************** ccp_fold_stmt (gimple_stmt_iterator *gsi
*** 1487,1496 ****
type issues. */
if (lhs
&& TREE_CODE (lhs) == SSA_NAME
! && (val = get_value (lhs))
! && val->lattice_val == CONSTANT)
{
! tree new_rhs = unshare_expr (val->value);
bool res;
if (!useless_type_conversion_p (TREE_TYPE (lhs),
TREE_TYPE (new_rhs)))
--- 1451,1459 ----
type issues. */
if (lhs
&& TREE_CODE (lhs) == SSA_NAME
! && (val = get_constant_value (lhs)))
{
! tree new_rhs = unshare_expr (val);
bool res;
if (!useless_type_conversion_p (TREE_TYPE (lhs),
TREE_TYPE (new_rhs)))
*************** ccp_fold_stmt (gimple_stmt_iterator *gsi
*** 1510,1522 ****
{
tree arg = gimple_call_arg (stmt, i);
if (TREE_CODE (arg) == SSA_NAME
! && (val = get_value (arg))
! && val->lattice_val == CONSTANT
&& useless_type_conversion_p
(TYPE_MAIN_VARIANT (TREE_VALUE (argt)),
! TYPE_MAIN_VARIANT (TREE_TYPE (val->value))))
{
! gimple_call_set_arg (stmt, i, unshare_expr (val->value));
changed = true;
}
}
--- 1473,1484 ----
{
tree arg = gimple_call_arg (stmt, i);
if (TREE_CODE (arg) == SSA_NAME
! && (val = get_constant_value (arg))
&& useless_type_conversion_p
(TYPE_MAIN_VARIANT (TREE_VALUE (argt)),
! TYPE_MAIN_VARIANT (TREE_TYPE (val))))
{
! gimple_call_set_arg (stmt, i, unshare_expr (val));
changed = true;
}
}
*************** ccp_fold_stmt (gimple_stmt_iterator *gsi
*** 1527,1542 ****
case GIMPLE_ASSIGN:
{
tree lhs = gimple_assign_lhs (stmt);
! prop_value_t *val;
/* If we have a load that turned out to be constant replace it
as we cannot propagate into all uses in all cases. */
if (gimple_assign_single_p (stmt)
&& TREE_CODE (lhs) == SSA_NAME
! && (val = get_value (lhs))
! && val->lattice_val == CONSTANT)
{
! tree rhs = unshare_expr (val->value);
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
gimple_assign_set_rhs_from_tree (gsi, rhs);
--- 1489,1503 ----
case GIMPLE_ASSIGN:
{
tree lhs = gimple_assign_lhs (stmt);
! tree val;
/* If we have a load that turned out to be constant replace it
as we cannot propagate into all uses in all cases. */
if (gimple_assign_single_p (stmt)
&& TREE_CODE (lhs) == SSA_NAME
! && (val = get_constant_value (lhs)))
{
! tree rhs = unshare_expr (val);
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
gimple_assign_set_rhs_from_tree (gsi, rhs);
*************** visit_assignment (gimple stmt, tree *out
*** 1569,1587 ****
gcc_assert (gimple_code (stmt) != GIMPLE_CALL
|| gimple_call_lhs (stmt) != NULL_TREE);
! if (gimple_assign_copy_p (stmt))
! {
! tree rhs = gimple_assign_rhs1 (stmt);
!
! if (TREE_CODE (rhs) == SSA_NAME)
! {
! /* For a simple copy operation, we copy the lattice values. */
! prop_value_t *nval = get_value (rhs);
! val = *nval;
! }
! else
! val = evaluate_stmt (stmt);
! }
else
/* Evaluate the statement, which could be
either a GIMPLE_ASSIGN or a GIMPLE_CALL. */
--- 1530,1539 ----
gcc_assert (gimple_code (stmt) != GIMPLE_CALL
|| gimple_call_lhs (stmt) != NULL_TREE);
! if (gimple_assign_single_p (stmt)
! && gimple_assign_rhs_code (stmt) == SSA_NAME)
! /* For a simple copy operation, we copy the lattice values. */
! val = *get_value (gimple_assign_rhs1 (stmt));
else
/* Evaluate the statement, which could be
either a GIMPLE_ASSIGN or a GIMPLE_CALL. */