This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] ccp changes
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Cc: dnovillo at redhat dot com
- Date: Wed, 8 Nov 2006 14:46:24 +0100
- Subject: [patch] ccp changes
Hello,
this patch contains some fixes and cleanups to ccp, initially motivated
by PR 29738 (which it also fixes, as a side effect):
1) Store-ccp puts UNKNOWN_VAL value in the lattice. However, there does
not seem to be any reason for that -- if the values of virtual
operands at entry are initialized to VARYING and the remaining virtual
ssa names to UNDEFINED, everything works just fine. This patch
removes UNKNOWN_VAL.
2) likely_value returns VARYING whenever there is a VARYING operand in
the statement; this is different from what the comment before it
claims, and it also is wrong (or at least overly conservative) --
e.g., 0 * VARYING = 0, so we do not want to give up immediatelly when
one of the operands is VARYING. This patch makes likely_value
behave as described in the comment (i.e., return UNDEFINED if there
is at least one undefined operand, CONSTANT if there are no operands
or at least one of the operands is constant, and VARYING otherwise).
3) In ccp_initialize, if a phi node has VARYING argument, we mark it
as DONT_SIMULATE_AGAIN. This is wrong, since we do not know whether
the corresponding edge will be executable or not. The patch removes
the code responsible for this.
Bootstrapped & regtested on i686 and x86_64.
Zdenek
PR tree-optimization/29738
* tree-ssa-ccp.c: Remove UNKNOWN_VAL from comments.
(ccp_lattice_t): Remove UNKNOWN_VAL.
(dump_lattice_value, ccp_lattice_meet, ccp_visit_phi_node):
Do not handle UNKNOWN_VAL.
(get_default_value): Set initial value of virtual operands to
VARYING.
(get_value): Always use get_default_value on uninitialized
operands.
(set_value_varying, surely_varying_stmt_p): New functions.
(set_lattice_value): Do not pass argument to get_value.
Do not handle UNKNOWN_VAL.
(likely_value): Follow the semantics described in the comment.
(ccp_initialize): Use surely_varying_stmt_p. Do not mark
phi nodes DONT_SIMULATE_AGAIN.
(ccp_fold): Do not pass argument to get_value.
(fold_const_aggregate_ref, visit_assignment): Ditto. Do not
handle UNKNOWN_VAL.
* gcc.dg/tree-ssa/ssa-ccp-14.c: New test.
Index: testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c (revision 0)
--- testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c (revision 0)
***************
*** 0 ****
--- 1,21 ----
+ /* PR tree-optimization/29738. We used not to realize that "i" can never
+ become nonzero. */
+
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-optimized" } */
+
+ int i;
+
+ void foo (void);
+ void bar (void)
+ {
+ int j;
+ i = 0;
+ for (j = 0; j < 10000; j++)
+ if (i)
+ foo ();
+ }
+
+ /* Everything except for the "i = 0" assignment should get removed. */
+ /* { dg-final { scan-tree-dump-times "if" 0 "optimized"} } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: tree-ssa-ccp.c
===================================================================
*** tree-ssa-ccp.c (revision 118542)
--- tree-ssa-ccp.c (working copy)
*************** Software Foundation, 51 Franklin Street,
*** 29,36 ****
with SSA names. Given an SSA name V_i, it may take one of the
following values:
! UNINITIALIZED -> This is the default starting value. V_i
! has not been processed yet.
UNDEFINED -> V_i is a local variable whose definition
has not been processed yet. Therefore we
--- 29,41 ----
with SSA names. Given an SSA name V_i, it may take one of the
following values:
! UNINITIALIZED -> the initial state of the value. This value
! is replaced with a correct initial value
! the first time the value is used, so the
! rest of the pass does not need to care about
! it. Using this value simplifies initialization
! of the pass, and prevents us from needlessly
! scanning statements that are never reached.
UNDEFINED -> V_i is a local variable whose definition
has not been processed yet. Therefore we
*************** Software Foundation, 51 Franklin Street,
*** 143,153 ****
it would be wrong to replace the load from 'a.b' with '2', because
'2' had been stored into a.a.
! To support STORE-CCP, it is necessary to add a new value to the
! constant propagation lattice. When evaluating a load for a memory
! reference we can no longer assume a value of UNDEFINED if we
! haven't seen a preceding store to the same memory location.
! Consider, for instance global variables:
int A;
--- 148,155 ----
it would be wrong to replace the load from 'a.b' with '2', because
'2' had been stored into a.a.
! Note that the initial value of virtual operands is VARYING, not
! UNDEFINED. Consider, for instance global variables:
int A;
*************** Software Foundation, 51 Franklin Street,
*** 165,174 ****
The value of A_2 cannot be assumed to be UNDEFINED, as it may have
been defined outside of foo. If we were to assume it UNDEFINED, we
! would erroneously optimize the above into 'return 3;'. Therefore,
! when doing STORE-CCP, we introduce a fifth lattice value
! (UNKNOWN_VAL), which overrides any other value when computing the
! meet operation in PHI nodes.
Though STORE-CCP is not too expensive, it does have to do more work
than regular CCP, so it is only enabled at -O2. Both regular CCP
--- 167,173 ----
The value of A_2 cannot be assumed to be UNDEFINED, as it may have
been defined outside of foo. If we were to assume it UNDEFINED, we
! would erroneously optimize the above into 'return 3;'.
Though STORE-CCP is not too expensive, it does have to do more work
than regular CCP, so it is only enabled at -O2. Both regular CCP
*************** Software Foundation, 51 Franklin Street,
*** 214,222 ****
/* Possible lattice values. */
typedef enum
{
! UNINITIALIZED = 0,
UNDEFINED,
- UNKNOWN_VAL,
CONSTANT,
VARYING
} ccp_lattice_t;
--- 213,220 ----
/* Possible lattice values. */
typedef enum
{
! UNINITIALIZED,
UNDEFINED,
CONSTANT,
VARYING
} ccp_lattice_t;
*************** dump_lattice_value (FILE *outf, const ch
*** 248,256 ****
case VARYING:
fprintf (outf, "%sVARYING", prefix);
break;
- case UNKNOWN_VAL:
- fprintf (outf, "%sUNKNOWN_VAL", prefix);
- break;
case CONSTANT:
fprintf (outf, "%sCONSTANT ", prefix);
print_generic_expr (outf, val.value, dump_flags);
--- 246,251 ----
*************** ccp_decl_initial_min_invariant (tree t)
*** 317,332 ****
4- Variables defined by statements other than assignments and PHI
nodes are considered VARYING.
! 5- Variables that are not GIMPLE registers are considered
! UNKNOWN_VAL, which is really a stronger version of UNDEFINED.
! It's used to avoid the short circuit evaluation implied by
! UNDEFINED in ccp_lattice_meet. */
static prop_value_t
get_default_value (tree var)
{
tree sym = SSA_NAME_VAR (var);
! prop_value_t val = { UNINITIALIZED, NULL_TREE, NULL_TREE };
if (!do_store_ccp && !is_gimple_reg (var))
{
--- 312,328 ----
4- Variables defined by statements other than assignments and PHI
nodes are considered VARYING.
! 5- Initial values of variables that are not GIMPLE registers are
! considered VARYING. */
static prop_value_t
get_default_value (tree var)
{
tree sym = SSA_NAME_VAR (var);
! prop_value_t val;
!
! val.value = NULL_TREE;
! val.mem_ref = NULL_TREE;
if (!do_store_ccp && !is_gimple_reg (var))
{
*************** get_default_value (tree var)
*** 360,374 ****
{
/* Variables defined by an empty statement are those used
before being initialized. If VAR is a local variable, we
! can assume initially that it is UNDEFINED. If we are
! doing STORE-CCP, function arguments and non-register
! variables are initially UNKNOWN_VAL, because we cannot
! discard the value incoming from outside of this function
! (see ccp_lattice_meet for details). */
if (is_gimple_reg (sym) && TREE_CODE (sym) != PARM_DECL)
val.lattice_val = UNDEFINED;
- else if (do_store_ccp)
- val.lattice_val = UNKNOWN_VAL;
else
val.lattice_val = VARYING;
}
--- 356,365 ----
{
/* Variables defined by an empty statement are those used
before being initialized. If VAR is a local variable, we
! can assume initially that it is UNDEFINED, otherwise we must
! consider it VARYING. */
if (is_gimple_reg (sym) && TREE_CODE (sym) != PARM_DECL)
val.lattice_val = UNDEFINED;
else
val.lattice_val = VARYING;
}
*************** get_default_value (tree var)
*** 376,384 ****
|| TREE_CODE (stmt) == PHI_NODE)
{
/* Any other variable defined by an assignment or a PHI node
! is considered UNDEFINED (or UNKNOWN_VAL if VAR is not a
! GIMPLE register). */
! val.lattice_val = is_gimple_reg (sym) ? UNDEFINED : UNKNOWN_VAL;
}
else
{
--- 367,374 ----
|| TREE_CODE (stmt) == PHI_NODE)
{
/* Any other variable defined by an assignment or a PHI node
! is considered UNDEFINED. */
! val.lattice_val = UNDEFINED;
}
else
{
*************** get_default_value (tree var)
*** 391,410 ****
}
! /* Get the constant value associated with variable VAR. If
! MAY_USE_DEFAULT_P is true, call get_default_value on variables that
! have the lattice value UNINITIALIZED. */
! static prop_value_t *
! get_value (tree var, bool may_use_default_p)
{
prop_value_t *val = &const_val[SSA_NAME_VERSION (var)];
! if (may_use_default_p && val->lattice_val == UNINITIALIZED)
*val = get_default_value (var);
return val;
}
/* Set the value for variable VAR to NEW_VAL. Return true if the new
value is different from VAR's previous value. */
--- 381,410 ----
}
! /* Get the constant value associated with variable VAR. */
! static inline prop_value_t *
! get_value (tree var)
{
prop_value_t *val = &const_val[SSA_NAME_VERSION (var)];
!
! if (val->lattice_val == UNINITIALIZED)
*val = get_default_value (var);
return val;
}
+ /* Sets the value associated with VAR to VARYING. */
+
+ static inline void
+ set_value_varying (tree var)
+ {
+ prop_value_t *val = &const_val[SSA_NAME_VERSION (var)];
+
+ val->lattice_val = VARYING;
+ val->value = NULL_TREE;
+ val->mem_ref = NULL_TREE;
+ }
/* Set the value for variable VAR to NEW_VAL. Return true if the new
value is different from VAR's previous value. */
*************** get_value (tree var, bool may_use_defaul
*** 412,459 ****
static bool
set_lattice_value (tree var, prop_value_t new_val)
{
! prop_value_t *old_val = get_value (var, false);
/* Lattice transitions must always be monotonically increasing in
! value. We allow two exceptions:
!
! 1- If *OLD_VAL and NEW_VAL are the same, return false to
! inform the caller that this was a non-transition.
!
! 2- If we are doing store-ccp (i.e., DOING_STORE_CCP is true),
! allow CONSTANT->UNKNOWN_VAL. The UNKNOWN_VAL state is a
! special type of UNDEFINED state which prevents the short
! circuit evaluation of PHI arguments (see ccp_visit_phi_node
! and ccp_lattice_meet). */
gcc_assert (old_val->lattice_val <= new_val.lattice_val
|| (old_val->lattice_val == new_val.lattice_val
&& old_val->value == new_val.value
! && old_val->mem_ref == new_val.mem_ref)
! || (do_store_ccp
! && old_val->lattice_val == CONSTANT
! && new_val.lattice_val == UNKNOWN_VAL));
if (old_val->lattice_val != new_val.lattice_val)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
dump_lattice_value (dump_file, "Lattice value changed to ", new_val);
! fprintf (dump_file, ". %sdding SSA edges to worklist.\n",
! new_val.lattice_val != UNDEFINED ? "A" : "Not a");
}
*old_val = new_val;
! /* Transitions UNINITIALIZED -> UNDEFINED are never interesting
! for propagation purposes. In these cases return false to
! avoid doing useless work. */
! return (new_val.lattice_val != UNDEFINED);
}
return false;
}
-
/* Return the likely CCP lattice value for STMT.
If STMT has no operands, then return CONSTANT.
--- 412,445 ----
static bool
set_lattice_value (tree var, prop_value_t new_val)
{
! prop_value_t *old_val = get_value (var);
/* Lattice transitions must always be monotonically increasing in
! value. If *OLD_VAL and NEW_VAL are the same, return false to
! inform the caller that this was a non-transition. */
!
gcc_assert (old_val->lattice_val <= new_val.lattice_val
|| (old_val->lattice_val == new_val.lattice_val
&& old_val->value == new_val.value
! && old_val->mem_ref == new_val.mem_ref));
if (old_val->lattice_val != new_val.lattice_val)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
dump_lattice_value (dump_file, "Lattice value changed to ", new_val);
! fprintf (dump_file, ". Adding SSA edges to worklist.\n");
}
*old_val = new_val;
! gcc_assert (new_val.lattice_val != UNDEFINED);
! return true;
}
return false;
}
/* Return the likely CCP lattice value for STMT.
If STMT has no operands, then return CONSTANT.
*************** set_lattice_value (tree var, prop_value_
*** 467,473 ****
static ccp_lattice_t
likely_value (tree stmt)
{
! bool found_constant;
stmt_ann_t ann;
tree use;
ssa_op_iter iter;
--- 453,459 ----
static ccp_lattice_t
likely_value (tree stmt)
{
! bool has_constant_operand;
stmt_ann_t ann;
tree use;
ssa_op_iter iter;
*************** likely_value (tree stmt)
*** 485,491 ****
&& !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return VARYING;
-
/* A CALL_EXPR is assumed to be varying. NOTE: This may be overly
conservative, in the presence of const and pure calls. */
if (get_call_expr_in (stmt) != NULL_TREE)
--- 471,476 ----
*************** likely_value (tree stmt)
*** 494,499 ****
--- 479,485 ----
/* Anything other than assignments and conditional jumps are not
interesting for CCP. */
if (TREE_CODE (stmt) != MODIFY_EXPR
+ && !(TREE_CODE (stmt) == RETURN_EXPR && get_rhs (stmt) != NULL_TREE)
&& TREE_CODE (stmt) != COND_EXPR
&& TREE_CODE (stmt) != SWITCH_EXPR)
return VARYING;
*************** likely_value (tree stmt)
*** 501,533 ****
if (is_gimple_min_invariant (get_rhs (stmt)))
return CONSTANT;
! found_constant = false;
! FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE|SSA_OP_VUSE)
{
! prop_value_t *val = get_value (use, true);
!
! if (val->lattice_val == VARYING)
! return VARYING;
! if (val->lattice_val == UNKNOWN_VAL)
! {
! /* UNKNOWN_VAL is invalid when not doing STORE-CCP. */
! gcc_assert (do_store_ccp);
! return UNKNOWN_VAL;
! }
if (val->lattice_val == CONSTANT)
! found_constant = true;
}
! if (found_constant
! || ZERO_SSA_OPERANDS (stmt, SSA_OP_USE)
! || ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
return CONSTANT;
! return UNDEFINED;
}
/* Initialize local data structures for CCP. */
--- 487,549 ----
if (is_gimple_min_invariant (get_rhs (stmt)))
return CONSTANT;
! has_constant_operand = false;
! FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
{
! prop_value_t *val = get_value (use);
! if (val->lattice_val == UNDEFINED)
! return UNDEFINED;
if (val->lattice_val == CONSTANT)
! has_constant_operand = true;
}
! if (has_constant_operand
! /* We do not consider virtual operands here -- load from read-only
! memory may have only VARYING virtual operands, but still be
! constant. */
! || ZERO_SSA_OPERANDS (stmt, SSA_OP_USE))
return CONSTANT;
! return VARYING;
}
+ /* Returns true if STMT cannot be constant. */
+
+ static bool
+ surely_varying_stmt_p (tree stmt)
+ {
+ /* If the statement has operands that we cannot handle, it cannot be
+ constant. */
+ if (stmt_ann (stmt)->has_volatile_ops)
+ return true;
+
+ if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+ {
+ if (!do_store_ccp)
+ return true;
+
+ /* We can only handle simple loads and stores. */
+ if (!stmt_makes_single_load (stmt)
+ && !stmt_makes_single_store (stmt))
+ return true;
+ }
+
+ /* If it contains a call, it is varying. */
+ if (get_call_expr_in (stmt) != NULL_TREE)
+ return true;
+
+ /* Anything other than assignments and conditional jumps are not
+ interesting for CCP. */
+ if (TREE_CODE (stmt) != MODIFY_EXPR
+ && !(TREE_CODE (stmt) == RETURN_EXPR && get_rhs (stmt) != NULL_TREE)
+ && TREE_CODE (stmt) != COND_EXPR
+ && TREE_CODE (stmt) != SWITCH_EXPR)
+ return true;
+
+ return false;
+ }
/* Initialize local data structures for CCP. */
*************** ccp_initialize (void)
*** 546,556 ****
for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
{
- bool is_varying = false;
tree stmt = bsi_stmt (i);
! if (likely_value (stmt) == VARYING)
!
{
tree def;
ssa_op_iter iter;
--- 562,571 ----
for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
{
tree stmt = bsi_stmt (i);
+ bool is_varying = surely_varying_stmt_p (stmt);
! if (is_varying)
{
tree def;
ssa_op_iter iter;
*************** ccp_initialize (void)
*** 558,601 ****
/* If the statement will not produce a constant, mark
all its outputs VARYING. */
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
! get_value (def, false)->lattice_val = VARYING;
!
! /* Never mark conditional jumps with DONT_SIMULATE_AGAIN,
! otherwise the propagator will never add the outgoing
! control edges. */
! if (TREE_CODE (stmt) != COND_EXPR
! && TREE_CODE (stmt) != SWITCH_EXPR)
! is_varying = true;
}
DONT_SIMULATE_AGAIN (stmt) = is_varying;
}
}
! /* Now process PHI nodes. */
FOR_EACH_BB (bb)
{
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
! int i;
! tree arg;
! prop_value_t *val = get_value (PHI_RESULT (phi), false);
!
! for (i = 0; i < PHI_NUM_ARGS (phi); i++)
! {
! arg = PHI_ARG_DEF (phi, i);
!
! if (TREE_CODE (arg) == SSA_NAME
! && get_value (arg, false)->lattice_val == VARYING)
! {
! val->lattice_val = VARYING;
! break;
! }
! }
!
! DONT_SIMULATE_AGAIN (phi) = (val->lattice_val == VARYING);
}
}
}
--- 573,601 ----
/* If the statement will not produce a constant, mark
all its outputs VARYING. */
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
! {
! if (is_varying)
! set_value_varying (def);
! }
}
DONT_SIMULATE_AGAIN (stmt) = is_varying;
}
}
! /* Now process PHI nodes. We never set DONT_SIMULATE_AGAIN on phi node,
! since we do not know which edges are executable yet, except for
! phi nodes for virtual operands when we do not do store ccp. */
FOR_EACH_BB (bb)
{
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
! if (!do_store_ccp && !is_gimple_reg (PHI_RESULT (phi)))
! DONT_SIMULATE_AGAIN (phi) = true;
! else
! DONT_SIMULATE_AGAIN (phi) = false;
}
}
}
*************** ccp_finalize (void)
*** 618,653 ****
in VAL1.
any M UNDEFINED = any
- any M UNKNOWN_VAL = UNKNOWN_VAL
any M VARYING = VARYING
Ci M Cj = Ci if (i == j)
Ci M Cj = VARYING if (i != j)
!
! Lattice values UNKNOWN_VAL and UNDEFINED are similar but have
! different semantics at PHI nodes. Both values imply that we don't
! know whether the variable is constant or not. However, UNKNOWN_VAL
! values override all others. For instance, suppose that A is a
! global variable:
!
! +------+
! | |
! | / \
! | / \
! | | A_1 = 4
! | \ /
! | \ /
! | A_3 = PHI (A_2, A_1)
! | ... = A_3
! | |
! +----+
!
! If the edge into A_2 is not executable, the first visit to A_3 will
! yield the constant 4. But the second visit to A_3 will be with A_2
! in state UNKNOWN_VAL. We can no longer conclude that A_3 is 4
! because A_2 may have been set in another function. If we had used
! the lattice value UNDEFINED, we would have had wrongly concluded
! that A_3 is 4. */
!
static void
ccp_lattice_meet (prop_value_t *val1, prop_value_t *val2)
--- 618,627 ----
in VAL1.
any M UNDEFINED = any
any M VARYING = VARYING
Ci M Cj = Ci if (i == j)
Ci M Cj = VARYING if (i != j)
! */
static void
ccp_lattice_meet (prop_value_t *val1, prop_value_t *val2)
*************** ccp_lattice_meet (prop_value_t *val1, pr
*** 663,679 ****
Nothing to do. VAL1 already contains the value we want. */
;
}
- else if (val1->lattice_val == UNKNOWN_VAL
- || val2->lattice_val == UNKNOWN_VAL)
- {
- /* UNKNOWN_VAL values are invalid if we are not doing STORE-CCP. */
- gcc_assert (do_store_ccp);
-
- /* any M UNKNOWN_VAL = UNKNOWN_VAL. */
- val1->lattice_val = UNKNOWN_VAL;
- val1->value = NULL_TREE;
- val1->mem_ref = NULL_TREE;
- }
else if (val1->lattice_val == VARYING
|| val2->lattice_val == VARYING)
{
--- 637,642 ----
*************** ccp_visit_phi_node (tree phi)
*** 725,731 ****
print_generic_expr (dump_file, phi, dump_flags);
}
! old_val = get_value (PHI_RESULT (phi), false);
switch (old_val->lattice_val)
{
case VARYING:
--- 688,694 ----
print_generic_expr (dump_file, phi, dump_flags);
}
! old_val = get_value (PHI_RESULT (phi));
switch (old_val->lattice_val)
{
case VARYING:
*************** ccp_visit_phi_node (tree phi)
*** 735,753 ****
new_val = *old_val;
break;
- case UNKNOWN_VAL:
- /* To avoid the default value of UNKNOWN_VAL overriding
- that of its possible constant arguments, temporarily
- set the PHI node's default lattice value to be
- UNDEFINED. If the PHI node's old value was UNKNOWN_VAL and
- the new value is UNDEFINED, then we prevent the invalid
- transition by not calling set_lattice_value. */
- gcc_assert (do_store_ccp);
-
- /* FALLTHRU */
-
case UNDEFINED:
- case UNINITIALIZED:
new_val.lattice_val = UNDEFINED;
new_val.value = NULL_TREE;
new_val.mem_ref = NULL_TREE;
--- 698,704 ----
*************** ccp_visit_phi_node (tree phi)
*** 785,791 ****
arg_val.mem_ref = NULL_TREE;
}
else
! arg_val = *(get_value (arg, true));
ccp_lattice_meet (&new_val, &arg_val);
--- 736,742 ----
arg_val.mem_ref = NULL_TREE;
}
else
! arg_val = *(get_value (arg));
ccp_lattice_meet (&new_val, &arg_val);
*************** ccp_visit_phi_node (tree phi)
*** 808,820 ****
fprintf (dump_file, "\n\n");
}
! /* Check for an invalid change from UNKNOWN_VAL to UNDEFINED. */
! if (do_store_ccp
! && old_val->lattice_val == UNKNOWN_VAL
! && new_val.lattice_val == UNDEFINED)
! return SSA_PROP_NOT_INTERESTING;
!
! /* Otherwise, make the transition to the new value. */
if (set_lattice_value (PHI_RESULT (phi), new_val))
{
if (new_val.lattice_val == VARYING)
--- 759,765 ----
fprintf (dump_file, "\n\n");
}
! /* Make the transition to the new value. */
if (set_lattice_value (PHI_RESULT (phi), new_val))
{
if (new_val.lattice_val == VARYING)
*************** ccp_fold (tree stmt)
*** 848,854 ****
{
/* If the RHS is an SSA_NAME, return its known constant value,
if any. */
! return get_value (rhs, true)->value;
}
else if (do_store_ccp && stmt_makes_single_load (stmt))
{
--- 793,799 ----
{
/* If the RHS is an SSA_NAME, return its known constant value,
if any. */
! return get_value (rhs)->value;
}
else if (do_store_ccp && stmt_makes_single_load (stmt))
{
*************** ccp_fold (tree stmt)
*** 881,889 ****
/* Simplify the operand down to a constant. */
if (TREE_CODE (op0) == SSA_NAME)
{
! prop_value_t *val = get_value (op0, true);
if (val->lattice_val == CONSTANT)
! op0 = get_value (op0, true)->value;
}
if ((code == NOP_EXPR || code == CONVERT_EXPR)
--- 826,834 ----
/* Simplify the operand down to a constant. */
if (TREE_CODE (op0) == SSA_NAME)
{
! prop_value_t *val = get_value (op0);
if (val->lattice_val == CONSTANT)
! op0 = get_value (op0)->value;
}
if ((code == NOP_EXPR || code == CONVERT_EXPR)
*************** ccp_fold (tree stmt)
*** 909,922 ****
/* Simplify the operands down to constants when appropriate. */
if (TREE_CODE (op0) == SSA_NAME)
{
! prop_value_t *val = get_value (op0, true);
if (val->lattice_val == CONSTANT)
op0 = val->value;
}
if (TREE_CODE (op1) == SSA_NAME)
{
! prop_value_t *val = get_value (op1, true);
if (val->lattice_val == CONSTANT)
op1 = val->value;
}
--- 854,867 ----
/* 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;
}
*************** ccp_fold (tree stmt)
*** 969,975 ****
return rhs;
}
-
/* Return the tree representing the element referenced by T if T is an
ARRAY_REF or COMPONENT_REF into constant aggregates. Return
NULL_TREE otherwise. */
--- 914,919 ----
*************** fold_const_aggregate_ref (tree t)
*** 1022,1028 ****
switch (TREE_CODE (idx))
{
case SSA_NAME:
! if ((value = get_value (idx, true))
&& value->lattice_val == CONSTANT
&& TREE_CODE (value->value) == INTEGER_CST)
idx = value->value;
--- 966,972 ----
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;
*************** evaluate_stmt (tree stmt)
*** 1151,1157 ****
/* The statement produced a nonconstant value. If the statement
had UNDEFINED operands, then the result of the statement
should be UNDEFINED. Otherwise, the statement is VARYING. */
! if (likelyvalue == UNDEFINED || likelyvalue == UNKNOWN_VAL)
val.lattice_val = likelyvalue;
else
val.lattice_val = VARYING;
--- 1095,1101 ----
/* The statement produced a nonconstant value. If the statement
had UNDEFINED operands, then the result of the statement
should be UNDEFINED. Otherwise, the statement is VARYING. */
! if (likelyvalue == UNDEFINED)
val.lattice_val = likelyvalue;
else
val.lattice_val = VARYING;
*************** evaluate_stmt (tree stmt)
*** 1162,1168 ****
return val;
}
-
/* Visit the assignment statement STMT. Set the value of its LHS to the
value computed by the RHS and store LHS in *OUTPUT_P. If STMT
creates virtual definitions, set the value of each new name to that
--- 1106,1111 ----
*************** visit_assignment (tree stmt, tree *outpu
*** 1181,1198 ****
if (TREE_CODE (rhs) == SSA_NAME)
{
/* For a simple copy operation, we copy the lattice values. */
! prop_value_t *nval = get_value (rhs, true);
val = *nval;
}
else if (do_store_ccp && stmt_makes_single_load (stmt))
{
/* Same as above, but the RHS is not a gimple register and yet
! has a known VUSE. If STMT is loading from the same memory
location that created the SSA_NAMEs for the virtual operands,
we can propagate the value on the RHS. */
prop_value_t *nval = get_value_loaded_by (stmt, const_val);
! if (nval && nval->mem_ref
&& operand_equal_p (nval->mem_ref, rhs, 0))
val = *nval;
else
--- 1124,1142 ----
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 if (do_store_ccp && stmt_makes_single_load (stmt))
{
/* Same as above, but the RHS is not a gimple register and yet
! has a known VUSE. If STMT is loading from the same memory
location that created the SSA_NAMEs for the virtual operands,
we can propagate the value on the RHS. */
prop_value_t *nval = get_value_loaded_by (stmt, const_val);
! if (nval
! && nval->mem_ref
&& operand_equal_p (nval->mem_ref, rhs, 0))
val = *nval;
else
*************** visit_assignment (tree stmt, tree *outpu
*** 1271,1282 ****
tree vdef;
bool changed;
- /* Stores cannot take on an UNDEFINED value. */
- if (val.lattice_val == UNDEFINED)
- val.lattice_val = UNKNOWN_VAL;
-
/* Mark VAL as stored in the LHS of this assignment. */
! val.mem_ref = lhs;
/* Set the value of every VDEF to VAL. */
changed = false;
--- 1215,1223 ----
tree vdef;
bool changed;
/* Mark VAL as stored in the LHS of this assignment. */
! if (val.lattice_val == CONSTANT)
! val.mem_ref = lhs;
/* Set the value of every VDEF to VAL. */
changed = false;