On Fri, 19 Aug 2016, Yuri Rumyantsev wrote: > Hi, > > Here is a simple test-case to reproduce 176.gcc failure (I run it on > Haswell machine). > Using 20160819 compiler build we get: > gcc -O3 -m32 -mavx2 test.c -o test.ref.exe > /users/ysrumyan/isse_6866$ ./test.ref.exe > Aborted (core dumped) > > If I apply patch proposed by Patrick test runs properly > Instead of running we can check number of .jump thread.
Thanks! With this test case I was able to identify the cause of the wrong code generation. Turns out that the problem lies in fold-const.c. It does not correctly fold VECTOR_CST comparisons that have a scalar boolean result type. In particular fold_binary folds the comparison {1,1,1} != {0,0,0} to false which causes the threader to register an incorrect jump thread. In general VEC1 != VEC2 gets folded as if it were VEC1 == VEC2. This patch fixes the problematic folding logic. Does this look OK to commit after bootstrap + regtesting? The faulty logic was introduced by the fix for PR68542 (r232518) so I think it is present on the 6 branch as well. gcc/ChangeLog: PR tree-optimization/71044 PR tree-optimization/68542 * fold-const.c (fold_relational_const): Fix folding of VECTOR_CST comparisons that have a scalar boolean result type. (test_vector_folding): New static function. (fold_const_c_tests): Call it. --- gcc/fold-const.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 30c1e0d..0271ac3 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -13897,7 +13897,6 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1) if (!VECTOR_TYPE_P (type)) { /* Have vector comparison with scalar boolean result. */ - bool result = true; gcc_assert ((code == EQ_EXPR || code == NE_EXPR) && VECTOR_CST_NELTS (op0) == VECTOR_CST_NELTS (op1)); for (unsigned i = 0; i < VECTOR_CST_NELTS (op0); i++) @@ -13905,11 +13904,12 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1) tree elem0 = VECTOR_CST_ELT (op0, i); tree elem1 = VECTOR_CST_ELT (op1, i); tree tmp = fold_relational_const (code, type, elem0, elem1); - result &= integer_onep (tmp); + if (tmp == NULL_TREE) + return NULL_TREE; + if (integer_zerop (tmp)) + return constant_boolean_node (false, type); } - if (code == NE_EXPR) - result = !result; - return constant_boolean_node (result, type); + return constant_boolean_node (true, type); } unsigned count = VECTOR_CST_NELTS (op0); tree *elts = XALLOCAVEC (tree, count); @@ -14517,12 +14517,32 @@ test_arithmetic_folding () x); } +/* Verify that various binary operations on vectors are folded + correctly. */ + +static void +test_vector_folding () +{ + tree inner_type = integer_type_node; + tree type = build_vector_type (inner_type, 4); + tree zero = build_zero_cst (type); + tree one = build_one_cst (type); + + /* Verify equality tests that return a scalar boolean result. */ + tree res_type = boolean_type_node; + ASSERT_FALSE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type, zero, one))); + ASSERT_TRUE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type, zero, zero))); + ASSERT_TRUE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, zero, one))); + ASSERT_FALSE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, one, one))); +} + /* Run all of the selftests within this file. */ void fold_const_c_tests () { test_arithmetic_folding (); + test_vector_folding (); } } // namespace selftest -- 2.9.3.650.g20ba99f