mirror of git://gcc.gnu.org/git/gcc.git
re PR tree-optimization/69270 (DOM should exploit range information to create more equivalences)
PR tree-optimization/69270 * tree-ssanames.c (ssa_name_has_boolean_range): Moved here from tree-ssa-dom.c. Improve test for [0..1] ranve from VRP. * tree-ssa-dom.c (ssa_name_has_boolean_range): Remove. * tree-ssanames.h (ssa_name_has_boolean_range): Prototype. * tree-ssa-uncprop.c (associate_equivalences_with_edges): Use ssa_name_has_boolean_range and constant_boolean_node. PR tree-optimization/69270 * gcc.dg/tree-ssa/pr69270-2.c: New test. * gcc.dg/tree-ssa/pr69270-3.c: New test. From-SVN: r232453
This commit is contained in:
parent
cebeb718fe
commit
40c43acacc
|
|
@ -1,3 +1,13 @@
|
||||||
|
2016-01-15 Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/69270
|
||||||
|
* tree-ssanames.c (ssa_name_has_boolean_range): Moved here from
|
||||||
|
tree-ssa-dom.c. Improve test for [0..1] ranve from VRP.
|
||||||
|
* tree-ssa-dom.c (ssa_name_has_boolean_range): Remove.
|
||||||
|
* tree-ssanames.h (ssa_name_has_boolean_range): Prototype.
|
||||||
|
* tree-ssa-uncprop.c (associate_equivalences_with_edges): Use
|
||||||
|
ssa_name_has_boolean_range and constant_boolean_node.
|
||||||
|
|
||||||
2016-01-15 Vladimir Makarov <vmakarov@redhat.com>
|
2016-01-15 Vladimir Makarov <vmakarov@redhat.com>
|
||||||
|
|
||||||
PR rtl-optimization/69030
|
PR rtl-optimization/69030
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2016-01-15 Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/69270
|
||||||
|
* gcc.dg/tree-ssa/pr69270-2.c: New test.
|
||||||
|
* gcc.dg/tree-ssa/pr69270-3.c: New test.
|
||||||
|
|
||||||
2016-01-15 Paul Thomas <pault@gcc.gnu.org>
|
2016-01-15 Paul Thomas <pault@gcc.gnu.org>
|
||||||
|
|
||||||
PR fortran/49630
|
PR fortran/49630
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-O2 -fdump-tree-dom3-details -w" } */
|
||||||
|
|
||||||
|
/* There should be a reference to usecount that turn into
|
||||||
|
constants. */
|
||||||
|
/* { dg-final { scan-tree-dump-times "Replaced .usecount_\[0-9\]+. with constant .1." 1 "dom3"} } */
|
||||||
|
|
||||||
|
/* And an assignment using usecount ought to fold down to constants. */
|
||||||
|
/* { dg-final { scan-tree-dump-times "Folded to: usecount_\[0-9\]+ = 2;" 1 "dom3"} } */
|
||||||
|
|
||||||
|
/* The arithmetic using usecount should be gone, except for the one in the
|
||||||
|
details debugging. */
|
||||||
|
/* { dg-final { scan-tree-dump-times "usecount_\[0-9\]+ = usecount_\[0-9\]+ . 1;" 1 "dom3"} } */
|
||||||
|
|
||||||
|
typedef union tree_node *tree;
|
||||||
|
typedef union gimple_statement_d *gimple;
|
||||||
|
extern const int tree_code_type[];
|
||||||
|
union tree_node
|
||||||
|
{
|
||||||
|
int code:16;
|
||||||
|
};
|
||||||
|
typedef struct immediate_use_iterator_d
|
||||||
|
{
|
||||||
|
}
|
||||||
|
imm_use_iterator;
|
||||||
|
void
|
||||||
|
insert_debug_temp_for_var_def (gimple stmt)
|
||||||
|
{
|
||||||
|
gimple def_stmt = ((void *) 0);
|
||||||
|
int usecount = 0;
|
||||||
|
tree value = ((void *) 0);
|
||||||
|
for (; arf ();)
|
||||||
|
{
|
||||||
|
if (!gimple_debug_bind_p (stmt))
|
||||||
|
continue;
|
||||||
|
if (usecount++)
|
||||||
|
break;
|
||||||
|
unsigned char no_value = 0;
|
||||||
|
if (!gimple_bb (def_stmt))
|
||||||
|
no_value = 1;
|
||||||
|
if (!no_value)
|
||||||
|
value = gimple_assign_rhs_to_tree ();
|
||||||
|
}
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
if ((tree_code_type[(int) (((value)->code))] == 42)
|
||||||
|
|| (usecount == 1 && (is_gimple_min_invariant (value))))
|
||||||
|
value = unshare_expr (value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-O2 -fdump-tree-uncprop-details -w" } */
|
||||||
|
|
||||||
|
/* We're looking for a constant argument a PHI node. There
|
||||||
|
should only be one if we unpropagate correctly. */
|
||||||
|
/* { dg-final { scan-tree-dump-times ", 1" 1 "uncprop1"} } */
|
||||||
|
|
||||||
|
typedef long unsigned int size_t;
|
||||||
|
typedef union gimple_statement_d *gimple;
|
||||||
|
unsigned char
|
||||||
|
propagate_with_phi ()
|
||||||
|
{
|
||||||
|
gimple use_stmt;
|
||||||
|
unsigned char phi_inserted;
|
||||||
|
phi_inserted = 0;
|
||||||
|
for (; !end_imm_use_stmt_p (); next_imm_use_stmt ())
|
||||||
|
{
|
||||||
|
if (!(arf () == 10 && boo () == 20))
|
||||||
|
continue;
|
||||||
|
if (!phi_inserted)
|
||||||
|
phi_inserted = 1;
|
||||||
|
else
|
||||||
|
update_stmt ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -316,39 +316,6 @@ record_conditions (struct edge_info *edge_info, tree cond, tree inverted)
|
||||||
edge_info->cond_equivalences.safe_push (c);
|
edge_info->cond_equivalences.safe_push (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return TRUE is OP, an SSA_NAME has a range of values [0..1], false
|
|
||||||
otherwise.
|
|
||||||
|
|
||||||
This can be because it is a boolean type, any unsigned integral
|
|
||||||
type with a single bit of precision, or has known range of [0..1]
|
|
||||||
via VRP analysis. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
ssa_name_has_boolean_range (tree op)
|
|
||||||
{
|
|
||||||
/* Boolean types always have a range [0..1]. */
|
|
||||||
if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/* An integral type with a single bit of precision. */
|
|
||||||
if (INTEGRAL_TYPE_P (TREE_TYPE (op))
|
|
||||||
&& TYPE_UNSIGNED (TREE_TYPE (op))
|
|
||||||
&& TYPE_PRECISION (TREE_TYPE (op)) == 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/* An integral type with more precision, but the object
|
|
||||||
only takes on values [0..1] as determined by VRP
|
|
||||||
analysis. */
|
|
||||||
wide_int min, max;
|
|
||||||
if (INTEGRAL_TYPE_P (TREE_TYPE (op))
|
|
||||||
&& get_range_info (op, &min, &max) == VR_RANGE
|
|
||||||
&& wi::eq_p (min, 0)
|
|
||||||
&& wi::eq_p (max, 1))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have finished optimizing BB, record any information implied by
|
/* We have finished optimizing BB, record any information implied by
|
||||||
taking a specific outgoing edge from BB. */
|
taking a specific outgoing edge from BB. */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,23 +94,26 @@ associate_equivalences_with_edges (void)
|
||||||
can record an equivalence for OP0 rather than COND. */
|
can record an equivalence for OP0 rather than COND. */
|
||||||
if (TREE_CODE (op0) == SSA_NAME
|
if (TREE_CODE (op0) == SSA_NAME
|
||||||
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
|
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
|
||||||
&& TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
|
&& ssa_name_has_boolean_range (op0)
|
||||||
&& is_gimple_min_invariant (op1))
|
&& is_gimple_min_invariant (op1))
|
||||||
{
|
{
|
||||||
|
tree true_val = constant_boolean_node (true, TREE_TYPE (op0));
|
||||||
|
tree false_val = constant_boolean_node (false,
|
||||||
|
TREE_TYPE (op0));
|
||||||
if (code == EQ_EXPR)
|
if (code == EQ_EXPR)
|
||||||
{
|
{
|
||||||
equivalency = XNEW (struct edge_equivalency);
|
equivalency = XNEW (struct edge_equivalency);
|
||||||
equivalency->lhs = op0;
|
equivalency->lhs = op0;
|
||||||
equivalency->rhs = (integer_zerop (op1)
|
equivalency->rhs = (integer_zerop (op1)
|
||||||
? boolean_false_node
|
? false_val
|
||||||
: boolean_true_node);
|
: true_val);
|
||||||
true_edge->aux = equivalency;
|
true_edge->aux = equivalency;
|
||||||
|
|
||||||
equivalency = XNEW (struct edge_equivalency);
|
equivalency = XNEW (struct edge_equivalency);
|
||||||
equivalency->lhs = op0;
|
equivalency->lhs = op0;
|
||||||
equivalency->rhs = (integer_zerop (op1)
|
equivalency->rhs = (integer_zerop (op1)
|
||||||
? boolean_true_node
|
? true_val
|
||||||
: boolean_false_node);
|
: false_val);
|
||||||
false_edge->aux = equivalency;
|
false_edge->aux = equivalency;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -118,15 +121,15 @@ associate_equivalences_with_edges (void)
|
||||||
equivalency = XNEW (struct edge_equivalency);
|
equivalency = XNEW (struct edge_equivalency);
|
||||||
equivalency->lhs = op0;
|
equivalency->lhs = op0;
|
||||||
equivalency->rhs = (integer_zerop (op1)
|
equivalency->rhs = (integer_zerop (op1)
|
||||||
? boolean_true_node
|
? true_val
|
||||||
: boolean_false_node);
|
: false_val);
|
||||||
true_edge->aux = equivalency;
|
true_edge->aux = equivalency;
|
||||||
|
|
||||||
equivalency = XNEW (struct edge_equivalency);
|
equivalency = XNEW (struct edge_equivalency);
|
||||||
equivalency->lhs = op0;
|
equivalency->lhs = op0;
|
||||||
equivalency->rhs = (integer_zerop (op1)
|
equivalency->rhs = (integer_zerop (op1)
|
||||||
? boolean_false_node
|
? false_val
|
||||||
: boolean_true_node);
|
: true_val);
|
||||||
false_edge->aux = equivalency;
|
false_edge->aux = equivalency;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -411,6 +411,40 @@ get_nonzero_bits (const_tree name)
|
||||||
return ri->get_nonzero_bits ();
|
return ri->get_nonzero_bits ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return TRUE is OP, an SSA_NAME has a range of values [0..1], false
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
This can be because it is a boolean type, any unsigned integral
|
||||||
|
type with a single bit of precision, or has known range of [0..1]
|
||||||
|
via VRP analysis. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
ssa_name_has_boolean_range (tree op)
|
||||||
|
{
|
||||||
|
gcc_assert (TREE_CODE (op) == SSA_NAME);
|
||||||
|
|
||||||
|
/* Boolean types always have a range [0..1]. */
|
||||||
|
if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* An integral type with a single bit of precision. */
|
||||||
|
if (INTEGRAL_TYPE_P (TREE_TYPE (op))
|
||||||
|
&& TYPE_UNSIGNED (TREE_TYPE (op))
|
||||||
|
&& TYPE_PRECISION (TREE_TYPE (op)) == 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* An integral type with more precision, but the object
|
||||||
|
only takes on values [0..1] as determined by VRP
|
||||||
|
analysis. */
|
||||||
|
if (INTEGRAL_TYPE_P (TREE_TYPE (op))
|
||||||
|
&& (TYPE_PRECISION (TREE_TYPE (op)) > 1
|
||||||
|
|| TYPE_UNSIGNED (TREE_TYPE (op)))
|
||||||
|
&& wi::eq_p (get_nonzero_bits (op), 1))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* We no longer need the SSA_NAME expression VAR, release it so that
|
/* We no longer need the SSA_NAME expression VAR, release it so that
|
||||||
it may be reused.
|
it may be reused.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ extern enum value_range_type get_range_info (const_tree, wide_int *,
|
||||||
wide_int *);
|
wide_int *);
|
||||||
extern void set_nonzero_bits (tree, const wide_int_ref &);
|
extern void set_nonzero_bits (tree, const wide_int_ref &);
|
||||||
extern wide_int get_nonzero_bits (const_tree);
|
extern wide_int get_nonzero_bits (const_tree);
|
||||||
|
extern bool ssa_name_has_boolean_range (tree);
|
||||||
extern void init_ssanames (struct function *, int);
|
extern void init_ssanames (struct function *, int);
|
||||||
extern void fini_ssanames (struct function *);
|
extern void fini_ssanames (struct function *);
|
||||||
extern void ssanames_print_statistics (void);
|
extern void ssanames_print_statistics (void);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue