diff --git a/gcc/testsuite/gcc.dg/torture/pr110979.c b/gcc/testsuite/gcc.dg/torture/pr110979.c new file mode 100644 index 00000000000..c25ad7a8a31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr110979.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options "--param vect-partial-vector-usage=2" } */ + +#define FLT double +#define N 20 + +__attribute__((noipa)) +FLT +foo3 (FLT *a) +{ + FLT sum = -0.0; + for (int i = 0; i != N; i++) + sum += a[i]; + return sum; +} + +int main() +{ + FLT a[N]; + for (int i = 0; i != N; i++) + a[i] = -0.0; + if (!__builtin_signbit(foo3(a))) + __builtin_abort(); + return 0; +} diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index bf8d677b584..bc3063c3615 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -6905,7 +6905,17 @@ vectorize_fold_left_reduction (loop_vec_info loop_vinfo, tree vector_identity = NULL_TREE; if (LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)) - vector_identity = build_zero_cst (vectype_out); + { + vector_identity = build_zero_cst (vectype_out); + if (!HONOR_SIGNED_ZEROS (vectype_out)) + ; + else + { + gcc_assert (!HONOR_SIGN_DEPENDENT_ROUNDING (vectype_out)); + vector_identity = const_unop (NEGATE_EXPR, vectype_out, + vector_identity); + } + } tree scalar_dest_var = vect_create_destination_var (scalar_dest, NULL); int i; @@ -8037,6 +8047,18 @@ vectorizable_reduction (loop_vec_info loop_vinfo, " no conditional operation is available.\n"); LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false; } + else if (reduction_type == FOLD_LEFT_REDUCTION + && reduc_fn == IFN_LAST + && FLOAT_TYPE_P (vectype_in) + && HONOR_SIGNED_ZEROS (vectype_in) + && HONOR_SIGN_DEPENDENT_ROUNDING (vectype_in)) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "can't operate on partial vectors because" + " signed zeros cannot be preserved.\n"); + LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false; + } else { internal_fn mask_reduc_fn