https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105053

--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
Err, no - the reduction epilogue is simply incomplete:

  <bb 46> [local count: 202926872]:
  # prephitmp_27 = PHI <prephitmp_97(12)>
  # vect__26.72_63 = PHI <vect__26.72_62(12)>
  _64 = .REDUC_MAX (vect__26.72_63);
  if (prephitmp_27 != prephitmp_35)
    goto <bb 18>; [0.00%]
  else
    goto <bb 19>; [100.00%]

  <bb 18> [count: 0]:
  abort ();

and the reason is that live_out_stmts has the wrong entry and we fail to
adjust the PHI nodes.  Now that's a missed optimization and should still
keep the scalar code live of course.

In fact

    /* The last statement in the reduction chain produces the live-out
       value.  */
    single_live_out_stmt[0] = SLP_TREE_SCALAR_STMTS (slp_node)[group_size - 1];

is wrong.  Or rather the way to get at it is.

The following fixes this and the testcase.

@@ -5271,9 +5275,17 @@ vect_create_epilog_for_reduction (loop_vec_info
loop_vinfo,
     /* All statements produce live-out values.  */
     live_out_stmts = SLP_TREE_SCALAR_STMTS (slp_node);
   else if (slp_node)
-    /* The last statement in the reduction chain produces the live-out
-       value.  */
-    single_live_out_stmt[0] = SLP_TREE_SCALAR_STMTS (slp_node)[group_size -
1];
+    {
+      /* The last statement in the reduction chain produces the live-out
+        value.  Note SLP optimization can shuffle scalar stmts to
+        optimize permutations so we have to search for the last stmt.  */
+      for (k = 0; k < group_size; ++k)
+       if (!REDUC_GROUP_NEXT_ELEMENT (SLP_TREE_SCALAR_STMTS (slp_node)[k]))
+         {
+           single_live_out_stmt[0] = SLP_TREE_SCALAR_STMTS (slp_node)[k];
+           break;
+         }
+    }

   unsigned vec_num;
   int ncopies;

Reply via email to