Commit 92007ba6 by Jakub Jelinek Committed by Jakub Jelinek

re PR tree-optimization/85529 (wrong code at -O2 and -O3 on x86_64-linux-gnu)

	PR tree-optimization/85529
	* tree-ssa-reassoc.c (optimize_range_tests_var_bound): Add FIRST_BB
	argument.  Don't call get_nonzero_bits if opcode is ERROR_MARK_NODE,
	rhs2 def stmt's bb is dominated by first_bb and it isn't an obvious
	zero extension or masking of the MSB bit.
	(optimize_range_tests): Add FIRST_BB argument, pass it through
	to optimize_range_tests_var_bound.
	(maybe_optimize_range_tests, reassociate_bb): Adjust
	optimize_range_tests callers.

	* gcc.c-torture/execute/pr85529-1.c: New test.
	* gcc.c-torture/execute/pr85529-2.c: New test.
	* gcc.dg/pr85529.c: New test.

From-SVN: r259696
parent be876cc4
2018-04-27 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/85529
* tree-ssa-reassoc.c (optimize_range_tests_var_bound): Add FIRST_BB
argument. Don't call get_nonzero_bits if opcode is ERROR_MARK_NODE,
rhs2 def stmt's bb is dominated by first_bb and it isn't an obvious
zero extension or masking of the MSB bit.
(optimize_range_tests): Add FIRST_BB argument, pass it through
to optimize_range_tests_var_bound.
(maybe_optimize_range_tests, reassociate_bb): Adjust
optimize_range_tests callers.
2018-04-26 Richard Biener <rguenther@suse.de> 2018-04-26 Richard Biener <rguenther@suse.de>
Jakub Jelinek <jakub@redhat.com> Jakub Jelinek <jakub@redhat.com>
......
2018-04-27 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/85529
* gcc.c-torture/execute/pr85529-1.c: New test.
* gcc.c-torture/execute/pr85529-2.c: New test.
* gcc.dg/pr85529.c: New test.
2018-04-26 Maciej W. Rozycki <macro@mips.com> 2018-04-26 Maciej W. Rozycki <macro@mips.com>
* gcc.target/mips/data-sym-pool.c (dg-options): Match `ld' and * gcc.target/mips/data-sym-pool.c (dg-options): Match `ld' and
......
/* PR tree-optimization/85529 */
struct S { int a; };
int b, c = 1, d, e, f;
static int g;
volatile struct S s;
signed char
foo (signed char i, int j)
{
return i < 0 ? i : i << j;
}
int
main ()
{
signed char k = -83;
if (!d)
goto L;
k = e || f;
L:
for (; b < 1; b++)
s.a != (k < foo (k, 2) && (c = k = g));
if (c != 1)
__builtin_abort ();
return 0;
}
/* PR tree-optimization/85529 */
__attribute__((noipa)) int
foo (int x)
{
x &= 63;
x -= 50;
x |= 1;
if (x < 0)
return 1;
int y = x >> 2;
if (x >= y)
return 1;
return 0;
}
int
main ()
{
int i;
for (i = 0; i < 63; i++)
if (foo (i) != 1)
__builtin_abort ();
return 0;
}
/* PR tree-optimization/85529 */
/* { dg-do run } */
/* { dg-options "-O2 -fno-ssa-phiopt" } */
__attribute__((noinline, noclone)) int
foo (int x)
{
x &= 31;
x -= 25;
x *= 2;
if (x < 0)
return 1;
int y = x >> 2;
if (x >= y)
return 1;
return 0;
}
int
main ()
{
int i;
for (i = 0; i < 63; i++)
if (foo (i) != 1)
__builtin_abort ();
return 0;
}
...@@ -3035,7 +3035,8 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length, ...@@ -3035,7 +3035,8 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
static bool static bool
optimize_range_tests_var_bound (enum tree_code opcode, int first, int length, optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
vec<operand_entry *> *ops, vec<operand_entry *> *ops,
struct range_entry *ranges) struct range_entry *ranges,
basic_block first_bb)
{ {
int i; int i;
bool any_changes = false; bool any_changes = false;
...@@ -3143,6 +3144,60 @@ optimize_range_tests_var_bound (enum tree_code opcode, int first, int length, ...@@ -3143,6 +3144,60 @@ optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
if (idx == NULL) if (idx == NULL)
continue; continue;
/* maybe_optimize_range_tests allows statements without side-effects
in the basic blocks as long as they are consumed in the same bb.
Make sure rhs2's def stmt is not among them, otherwise we can't
use safely get_nonzero_bits on it. E.g. in:
# RANGE [-83, 1] NONZERO 173
# k_32 = PHI <k_47(13), k_12(9)>
...
if (k_32 >= 0)
goto <bb 5>; [26.46%]
else
goto <bb 9>; [73.54%]
<bb 5> [local count: 140323371]:
# RANGE [0, 1] NONZERO 1
_5 = (int) k_32;
# RANGE [0, 4] NONZERO 4
_21 = _5 << 2;
# RANGE [0, 4] NONZERO 4
iftmp.0_44 = (char) _21;
if (k_32 < iftmp.0_44)
goto <bb 6>; [84.48%]
else
goto <bb 9>; [15.52%]
the ranges on _5/_21/iftmp.0_44 are flow sensitive, assume that
k_32 >= 0. If we'd optimize k_32 >= 0 to true and k_32 < iftmp.0_44
to (unsigned) k_32 < (unsigned) iftmp.0_44, then we would execute
those stmts even for negative k_32 and the value ranges would be no
longer guaranteed and so the optimization would be invalid. */
if (opcode == ERROR_MARK)
{
gimple *g = SSA_NAME_DEF_STMT (rhs2);
basic_block bb2 = gimple_bb (g);
if (bb2
&& bb2 != first_bb
&& dominated_by_p (CDI_DOMINATORS, bb2, first_bb))
{
/* As an exception, handle a few common cases. */
if (gimple_assign_cast_p (g)
&& INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (g)))
&& TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)))
&& (TYPE_PRECISION (TREE_TYPE (rhs2))
> TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (g)))))
/* Zero-extension is always ok. */ ;
else if (is_gimple_assign (g)
&& gimple_assign_rhs_code (g) == BIT_AND_EXPR
&& TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
&& !wi::neg_p (wi::to_wide (gimple_assign_rhs2 (g))))
/* Masking with INTEGER_CST with MSB clear is always ok
too. */ ;
else
continue;
}
}
wide_int nz = get_nonzero_bits (rhs2); wide_int nz = get_nonzero_bits (rhs2);
if (wi::neg_p (nz)) if (wi::neg_p (nz))
continue; continue;
...@@ -3269,11 +3324,12 @@ optimize_range_tests_var_bound (enum tree_code opcode, int first, int length, ...@@ -3269,11 +3324,12 @@ optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
maybe_optimize_range_tests for inter-bb range optimization. maybe_optimize_range_tests for inter-bb range optimization.
In that case if oe->op is NULL, oe->id is bb->index whose In that case if oe->op is NULL, oe->id is bb->index whose
GIMPLE_COND is && or ||ed into the test, and oe->rank says GIMPLE_COND is && or ||ed into the test, and oe->rank says
the actual opcode. */ the actual opcode.
FIRST_BB is the first basic block if OPCODE is ERROR_MARK. */
static bool static bool
optimize_range_tests (enum tree_code opcode, optimize_range_tests (enum tree_code opcode,
vec<operand_entry *> *ops) vec<operand_entry *> *ops, basic_block first_bb)
{ {
unsigned int length = ops->length (), i, j, first; unsigned int length = ops->length (), i, j, first;
operand_entry *oe; operand_entry *oe;
...@@ -3353,7 +3409,7 @@ optimize_range_tests (enum tree_code opcode, ...@@ -3353,7 +3409,7 @@ optimize_range_tests (enum tree_code opcode,
any_changes |= optimize_range_tests_cmp_bitwise (opcode, first, length, any_changes |= optimize_range_tests_cmp_bitwise (opcode, first, length,
ops, ranges); ops, ranges);
any_changes |= optimize_range_tests_var_bound (opcode, first, length, ops, any_changes |= optimize_range_tests_var_bound (opcode, first, length, ops,
ranges); ranges, first_bb);
if (any_changes && opcode != ERROR_MARK) if (any_changes && opcode != ERROR_MARK)
{ {
...@@ -4100,7 +4156,7 @@ maybe_optimize_range_tests (gimple *stmt) ...@@ -4100,7 +4156,7 @@ maybe_optimize_range_tests (gimple *stmt)
break; break;
} }
if (ops.length () > 1) if (ops.length () > 1)
any_changes = optimize_range_tests (ERROR_MARK, &ops); any_changes = optimize_range_tests (ERROR_MARK, &ops, first_bb);
if (any_changes) if (any_changes)
{ {
unsigned int idx, max_idx = 0; unsigned int idx, max_idx = 0;
...@@ -5855,7 +5911,7 @@ reassociate_bb (basic_block bb) ...@@ -5855,7 +5911,7 @@ reassociate_bb (basic_block bb)
if (is_vector) if (is_vector)
optimize_vec_cond_expr (rhs_code, &ops); optimize_vec_cond_expr (rhs_code, &ops);
else else
optimize_range_tests (rhs_code, &ops); optimize_range_tests (rhs_code, &ops, NULL);
} }
if (rhs_code == MULT_EXPR && !is_vector) if (rhs_code == MULT_EXPR && !is_vector)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment