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:
parent
17c15cb932
commit
2bedb645f2
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue