re PR tree-optimization/69320 (wrong code generation at -O2 and higher)

2016-01-18  Jeff Law  <law@redhat.com>

	PR tree-optimization/69320
	* tree-ssa-dom.c (record_edge_info): For comparisons against a boolean
	ranged object, do nothing if the RHS constant is not [0..1].
	(optimize_stmt): Comparing a boolean ranged object against a
	constant outside [0..1] results in a compile-time constant.

	* tree-ssanames.c (ssa_name_has_boolean_range): Remove unnecessary
	test.

	PR tree-optimization/69320
	* gcc.c-torture/pr69320-1.c: New test.
	* gcc.c-torture/pr69320-2.c: New test.
	* gcc.c-torture/pr69320-3.c: New test.
	* gcc.c-torture/pr69320-4.c: New test.

From-SVN: r232548
This commit is contained in:
Jeff Law 2016-01-18 23:43:54 -07:00 committed by Jeff Law
parent 17c15cb932
commit 2bedb645f2
8 changed files with 144 additions and 6 deletions

View File

@ -1,3 +1,14 @@
2016-01-18 Jeff Law <law@redhat.com>
PR tree-optimization/69320
* tree-ssa-dom.c (record_edge_info): For comparisons against a boolean
ranged object, do nothing if the RHS constant is not [0..1].
(optimize_stmt): Comparing a boolean ranged object against a
constant outside [0..1] results in a compile-time constant.
* tree-ssanames.c (ssa_name_has_boolean_range): Remove unnecessary
test.
2016-01-18 Sandra Loosemore <sandra@codesourcery.com>
* doc/invoke.texi (Invoking GCC): Add new section to menu.

View File

@ -1,3 +1,11 @@
2016-01-15 Jeff Law <law@redhat.com>
PR tree-optimization/69320
* gcc.c-torture/pr69320-1.c: New test.
* gcc.c-torture/pr69320-2.c: New test.
* gcc.c-torture/pr69320-3.c: New test.
* gcc.c-torture/pr69320-4.c: New test.
2016-01-18 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/11858

View File

@ -0,0 +1,20 @@
#include <stdlib.h>
int a, b, d, f;
char c;
static int *e = &d;
int main() {
int g = -1L;
*e = g;
c = 4;
for (; c >= 14; c++)
*e = 1;
f = a == 0;
*e ^= f;
int h = ~d;
if (d)
b = h;
if (h)
exit (0);
abort ();
}

View File

@ -0,0 +1,35 @@
#include <stdlib.h>
int a, *c, d, e, g, f;
short b;
int
fn1 ()
{
int h = d != 10;
if (h > g)
asm volatile ("" : : : "memory");
if (h == 10)
{
int *i = 0;
a = 0;
for (; a < 7; a++)
for (; *i;)
;
}
else
{
b = e / h;
return f;
}
c = &h;
abort ();
}
int
main ()
{
fn1 ();
exit (0);
}

View File

@ -0,0 +1,17 @@
#include <stdlib.h>
static int a[40] = {7, 5, 3, 3, 0, 0, 3};
short b;
int c = 5;
int main() {
b = 0;
for (; b <= 3; b++)
if (a[b + 6] ^ (0 || c))
;
else
break;
if (b != 4)
abort ();
exit (0);
}

View File

@ -0,0 +1,18 @@
#include <stdlib.h>
int a;
char b, d;
short c;
short fn1(int p1, int p2) { return p2 >= 2 ? p1 : p1 > p2; }
int main() {
int *e = &a, *f = &a;
b = 1;
for (; b <= 9; b++) {
c = *e != 5 || d;
*f = fn1(c || b, a);
}
if ((long long) a != 1)
abort ();
exit (0);
}

View File

@ -387,11 +387,16 @@ record_edge_info (basic_block bb)
/* Special case comparing booleans against a constant as we
know the value of OP0 on both arms of the branch. i.e., we
can record an equivalence for OP0 rather than COND. */
if ((code == EQ_EXPR || code == NE_EXPR)
&& TREE_CODE (op0) == SSA_NAME
can record an equivalence for OP0 rather than COND.
However, don't do this if the constant isn't zero or one.
Such conditionals will get optimized more thoroughly during
the domwalk. */
if ((code == EQ_EXPR || code == NE_EXPR)
&& TREE_CODE (op0) == SSA_NAME
&& ssa_name_has_boolean_range (op0)
&& is_gimple_min_invariant (op1))
&& is_gimple_min_invariant (op1)
&& (integer_zerop (op1) || integer_onep (op1)))
{
tree true_val = constant_boolean_node (true, TREE_TYPE (op0));
tree false_val = constant_boolean_node (false, TREE_TYPE (op0));
@ -1828,6 +1833,31 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
}
}
if (gimple_code (stmt) == GIMPLE_COND)
{
tree lhs = gimple_cond_lhs (stmt);
tree rhs = gimple_cond_rhs (stmt);
/* If the LHS has a range [0..1] and the RHS has a range ~[0..1],
then this conditional is computable at compile time. We can just
shove either 0 or 1 into the LHS, mark the statement as modified
and all the right things will just happen below.
Note this would apply to any case where LHS has a range
narrower than its type implies and RHS is outside that
narrower range. Future work. */
if (TREE_CODE (lhs) == SSA_NAME
&& ssa_name_has_boolean_range (lhs)
&& TREE_CODE (rhs) == INTEGER_CST
&& ! (integer_zerop (rhs) || integer_onep (rhs)))
{
gimple_cond_set_lhs (as_a <gcond *> (stmt),
fold_convert (TREE_TYPE (lhs),
integer_zero_node));
gimple_set_modified (stmt, true);
}
}
update_stmt_if_modified (stmt);
eliminate_redundant_computations (&si, const_and_copies,
avail_exprs_stack);

View File

@ -437,8 +437,7 @@ ssa_name_has_boolean_range (tree op)
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)))
&& (TYPE_PRECISION (TREE_TYPE (op)) > 1)
&& wi::eq_p (get_nonzero_bits (op), 1))
return true;