Commit e67bbd5d by Marek Polacek Committed by Marek Polacek

re PR middle-end/81814 (Incorrect behaviour at -O0 (conditional operator))

	PR middle-end/81814
	* fold-const.c (operand_equal_for_comparison_p): Remove code that used
	to mimic what shorten_compare did.  Change the return type to bool.
	(fold_cond_expr_with_comparison): Update call to
	operand_equal_for_comparison_p.
	(fold_ternary_loc): Likewise.

	* gcc.dg/torture/pr81814.c: New test.

From-SVN: r251152
parent 909e448f
2017-08-17 Marek Polacek <polacek@redhat.com>
PR middle-end/81814
* fold-const.c (operand_equal_for_comparison_p): Remove code that used
to mimic what shorten_compare did. Change the return type to bool.
(fold_cond_expr_with_comparison): Update call to
operand_equal_for_comparison_p.
(fold_ternary_loc): Likewise.
2017-08-17 Jackson Woodruff <jackson.woodruff@arm.com> 2017-08-17 Jackson Woodruff <jackson.woodruff@arm.com>
* aarch64-simd.md (mov<mode>): No longer force zero immediate into * aarch64-simd.md (mov<mode>): No longer force zero immediate into
......
...@@ -113,7 +113,6 @@ static tree negate_expr (tree); ...@@ -113,7 +113,6 @@ static tree negate_expr (tree);
static tree associate_trees (location_t, tree, tree, enum tree_code, tree); static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
static enum comparison_code comparison_to_compcode (enum tree_code); static enum comparison_code comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (enum comparison_code); static enum tree_code compcode_to_comparison (enum comparison_code);
static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *); static int twoval_comparison_p (tree, tree *, tree *, int *);
static tree eval_subst (location_t, tree, tree, tree, tree, tree); static tree eval_subst (location_t, tree, tree, tree, tree, tree);
static tree optimize_bit_field_compare (location_t, enum tree_code, static tree optimize_bit_field_compare (location_t, enum tree_code,
...@@ -3365,60 +3364,27 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) ...@@ -3365,60 +3364,27 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
#undef OP_SAME_WITH_NULL #undef OP_SAME_WITH_NULL
} }
/* Similar to operand_equal_p, but see if ARG0 might have been made by /* Similar to operand_equal_p, but strip nops first. */
shorten_compare from ARG1 when ARG1 was being compared with OTHER.
When in doubt, return 0. */ static bool
operand_equal_for_comparison_p (tree arg0, tree arg1)
static int
operand_equal_for_comparison_p (tree arg0, tree arg1, tree other)
{ {
int unsignedp1, unsignedpo;
tree primarg0, primarg1, primother;
unsigned int correct_width;
if (operand_equal_p (arg0, arg1, 0)) if (operand_equal_p (arg0, arg1, 0))
return 1; return true;
if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0)) if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|| ! INTEGRAL_TYPE_P (TREE_TYPE (arg1))) || ! INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
return 0; return false;
/* Discard any conversions that don't change the modes of ARG0 and ARG1 /* Discard any conversions that don't change the modes of ARG0 and ARG1
and see if the inner values are the same. This removes any and see if the inner values are the same. This removes any
signedness comparison, which doesn't matter here. */ signedness comparison, which doesn't matter here. */
primarg0 = arg0, primarg1 = arg1; STRIP_NOPS (arg0);
STRIP_NOPS (primarg0); STRIP_NOPS (arg1);
STRIP_NOPS (primarg1); if (operand_equal_p (arg0, arg1, 0))
if (operand_equal_p (primarg0, primarg1, 0)) return true;
return 1;
/* Duplicate what shorten_compare does to ARG1 and see if that gives the
actual comparison operand, ARG0.
First throw away any conversions to wider types
already present in the operands. */
primarg1 = get_narrower (arg1, &unsignedp1);
primother = get_narrower (other, &unsignedpo);
correct_width = TYPE_PRECISION (TREE_TYPE (arg1));
if (unsignedp1 == unsignedpo
&& TYPE_PRECISION (TREE_TYPE (primarg1)) < correct_width
&& TYPE_PRECISION (TREE_TYPE (primother)) < correct_width)
{
tree type = TREE_TYPE (arg0);
/* Make sure shorter operand is extended the right way
to match the longer operand. */
primarg1 = fold_convert (signed_or_unsigned_type_for
(unsignedp1, TREE_TYPE (primarg1)), primarg1);
if (operand_equal_p (arg0, fold_convert (type, primarg1), 0))
return 1;
}
return 0; return false;
} }
/* See if ARG is an expression that is either a comparison or is performing /* See if ARG is an expression that is either a comparison or is performing
...@@ -5300,7 +5266,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type, ...@@ -5300,7 +5266,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
expressions will be false, so all four give B. The min() expressions will be false, so all four give B. The min()
and max() versions would give a NaN instead. */ and max() versions would give a NaN instead. */
if (!HONOR_SIGNED_ZEROS (element_mode (type)) if (!HONOR_SIGNED_ZEROS (element_mode (type))
&& operand_equal_for_comparison_p (arg01, arg2, arg00) && operand_equal_for_comparison_p (arg01, arg2)
/* Avoid these transformations if the COND_EXPR may be used /* Avoid these transformations if the COND_EXPR may be used
as an lvalue in the C++ front-end. PR c++/19199. */ as an lvalue in the C++ front-end. PR c++/19199. */
&& (in_gimple_form && (in_gimple_form
...@@ -11357,8 +11323,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, ...@@ -11357,8 +11323,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
Also try swapping the arguments and inverting the conditional. */ Also try swapping the arguments and inverting the conditional. */
if (COMPARISON_CLASS_P (arg0) if (COMPARISON_CLASS_P (arg0)
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), arg1)
arg1, TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (element_mode (arg1))) && !HONOR_SIGNED_ZEROS (element_mode (arg1)))
{ {
tem = fold_cond_expr_with_comparison (loc, type, arg0, op1, op2); tem = fold_cond_expr_with_comparison (loc, type, arg0, op1, op2);
...@@ -11367,9 +11332,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, ...@@ -11367,9 +11332,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
} }
if (COMPARISON_CLASS_P (arg0) if (COMPARISON_CLASS_P (arg0)
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), op2)
op2,
TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (element_mode (op2))) && !HONOR_SIGNED_ZEROS (element_mode (op2)))
{ {
location_t loc0 = expr_location_or (arg0, loc); location_t loc0 = expr_location_or (arg0, loc);
......
2017-08-17 Marek Polacek <polacek@redhat.com>
PR middle-end/81814
* gcc.dg/torture/pr81814.c: New test.
2017-08-17 Jackson Woodruff <jackson.woodruff@arm.com> 2017-08-17 Jackson Woodruff <jackson.woodruff@arm.com>
* gcc.target/aarch64/simd/vect_str_zero.c: New testcase. * gcc.target/aarch64/simd/vect_str_zero.c: New testcase.
......
/* PR middle-end/81814 */
/* { dg-do run } */
int
main ()
{
int i = 0x01000000;
int a;
a = ((signed char) i) != 0 ? 0 : (unsigned long long int) i;
if (a != 0x01000000)
__builtin_abort ();
a = ((signed short int) i) != 0 ? 0 : (unsigned long long int) i;
if (a != 0x01000000)
__builtin_abort ();
a = ((unsigned short int) i) != 0 ? 0 : (unsigned long long int) i;
if (a != 0x01000000)
__builtin_abort ();
a = ((unsigned char) i) != 0 ? 0 : (unsigned long long int) i;
if (a != 0x01000000)
__builtin_abort ();
a = ((signed char) i) == 0 ? (unsigned long long int) i : 0;
if (a != 0x01000000)
__builtin_abort ();
a = ((signed short int) i) == 0 ? (unsigned long long int) i : 0;
if (a != 0x01000000)
__builtin_abort ();
a = ((unsigned short int) i) == 0 ? (unsigned long long int) i : 0;
if (a != 0x01000000)
__builtin_abort ();
a = ((unsigned char) i) == 0 ? (unsigned long long int) i : 0;
if (a != 0x01000000)
__builtin_abort ();
return 0;
}
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