From 85e2723649382f35c98ca4b2953ab0c3375cc54a Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 12 Jul 2018 11:53:04 -0400
Subject: [PATCH 62/68] FIXME: remove the bool to opt_result ctor

---
 gcc/opt-problem.h     | 18 ++++++++++--
 gcc/tree-vect-loop.c  | 76 +++++++++++++++++++++++++++++++--------------------
 gcc/tree-vect-stmts.c | 38 +++++++++++++++++---------
 gcc/tree-vectorizer.h |  2 +-
 4 files changed, 88 insertions(+), 46 deletions(-)

diff --git a/gcc/opt-problem.h b/gcc/opt-problem.h
index 100eed0..91333ea 100644
--- a/gcc/opt-problem.h
+++ b/gcc/opt-problem.h
@@ -235,6 +235,7 @@ class opt_result : public opt_wrapper <bool>
   /* Deprecated ctor.  During transition, allow construction from bool.
      We want to eliminate this, as it doesn't capture the reason for
      failures.  */
+#if 0
   opt_result (bool result,
 	      const dump_impl_location_t &impl_location
 		= dump_impl_location_t ())
@@ -242,6 +243,7 @@ class opt_result : public opt_wrapper <bool>
 			  opt_problem::make ("UNKNOWN", NULL, impl_location))
   {
   }
+#endif
 
   static opt_result success () { return opt_result (true, NULL); }
   static opt_result failure (const char *gmsgid, gimple *stmt,
@@ -252,6 +254,16 @@ class opt_result : public opt_wrapper <bool>
 		       opt_problem::make (gmsgid, stmt, impl_location));
   }
 
+  /* Given a failure wrapper of some other kind, make a failure object,
+     propagating the problem.  */
+
+  template <typename S>
+  static opt_result
+  failure (opt_wrapper <S> other)
+  {
+    return opt_result (false, other.get_problem ());
+  }
+
   static opt_result bad_type (const char *gmsgid, gimple *stmt, tree /*type*/,
 			      const dump_impl_location_t &impl_location
 				= dump_impl_location_t ())
@@ -292,11 +304,11 @@ class opt_pointer_wrapper : public opt_wrapper <PtrType_t>
   /* Make a NULL pointer failure object, with the given message.  */
 
   static opt_pointer_wrapper <wrapped_pointer_t>
-  failure (const char *gmsgid,
+  failure (const char *gmsgid, gimple *stmt = NULL,
 	   const dump_impl_location_t &impl_location
 	     = dump_impl_location_t ())
   {
-    opt_problem *problem = opt_problem::make (gmsgid, NULL, impl_location);
+    opt_problem *problem = opt_problem::make (gmsgid, stmt, impl_location);
     return opt_pointer_wrapper <wrapped_pointer_t> (NULL, problem);
   }
 
@@ -323,4 +335,6 @@ class opt_pointer_wrapper : public opt_wrapper <PtrType_t>
   {}
 };
 
+typedef opt_pointer_wrapper<tree> opt_tree;
+
 #endif /* #ifndef GCC_OPT_PROBLEM_H */
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 88902c4..54e1497 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -403,9 +403,10 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
   for (i = 0; i < mask_producers.length (); i++)
     {
       stmt_info = mask_producers[i];
-      tree mask_type = vect_get_mask_type_for_stmt (stmt_info);
+      opt_tree mask_type = vect_get_mask_type_for_stmt (stmt_info);
       if (!mask_type)
-	return false;
+	/* Propagate the failure.  */
+	return opt_result::failure (mask_type);
       STMT_VINFO_VECTYPE (stmt_info) = mask_type;
     }
 
@@ -1199,7 +1200,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
           if (dump_enabled_p ())
             dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
 			     "not vectorized: control flow in loop.\n");
-          return opt_result::failure ("control flow in loop", NULL);
+	  return opt_result::failure ("control flow in loop", NULL);
         }
 
       if (empty_block_p (loop->header))
@@ -1207,7 +1208,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 	  if (dump_enabled_p ())
 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
 			     "not vectorized: empty loop.\n");
-          return opt_result::failure ("empty loop", NULL);
+	  return opt_result::failure ("empty loop", NULL);
 	}
     }
   else
@@ -1237,7 +1238,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 	  if (dump_enabled_p ())
 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
 			     "not vectorized: multiple nested loops.\n");
-          return opt_result::failure ("multiple nested loops", NULL);
+	  return opt_result::failure ("multiple nested loops", NULL);
 	}
 
       if (loop->num_nodes != 5)
@@ -1245,7 +1246,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 	  if (dump_enabled_p ())
 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
 			     "not vectorized: control flow in loop.\n");
-          return opt_result::failure ("control flow in loop", NULL);
+	  return opt_result::failure ("control flow in loop", NULL);
         }
 
       entryedge = loop_preheader_edge (innerloop);
@@ -1256,22 +1257,31 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 	  if (dump_enabled_p ())
 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
 			     "not vectorized: unsupported outerloop form.\n");
-          return opt_result::failure ("unsupported outerloop form", NULL);
+	  return opt_result::failure ("unsupported outerloop form", NULL);
 	}
 
       /* Analyze the inner-loop.  */
       tree inner_niterm1, inner_niter, inner_assumptions;
-      if (! vect_analyze_loop_form_1 (loop->inner, inner_loop_cond,
-				      &inner_assumptions, &inner_niterm1,
-				      &inner_niter, NULL)
-	  /* Don't support analyzing niter under assumptions for inner
-	     loop.  */
-	  || !integer_onep (inner_assumptions))
+      opt_result res
+	= vect_analyze_loop_form_1 (loop->inner, inner_loop_cond,
+				    &inner_assumptions, &inner_niterm1,
+				    &inner_niter, NULL);
+      if (!res)
 	{
 	  if (dump_enabled_p ())
-            dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
 			     "not vectorized: Bad inner loop.\n");
-	  return false;
+	  return res;
+	}
+
+      /* Don't support analyzing niter under assumptions for inner
+	 loop.  */
+      if (!integer_onep (inner_assumptions))
+	{
+	  if (dump_enabled_p ())
+	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+			     "not vectorized: Bad inner loop.\n");
+	  return opt_result::failure ("Bad inner loop", NULL);
 	}
 
       if (!expr_invariant_in_loop_p (loop, inner_niter))
@@ -1280,7 +1290,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
 			     "not vectorized: inner-loop count not"
                              " invariant.\n");
-	  return false;
+	  return opt_result::failure ("inner-loop count not invariant", NULL);
 	}
 
       if (dump_enabled_p ())
@@ -1288,19 +1298,23 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond,
 			 "Considering outer-loop vectorization.\n");
     }
 
-  if (!single_exit (loop)
-      || EDGE_COUNT (loop->header->preds) != 2)
+  if (!single_exit (loop))
     {
       if (dump_enabled_p ())
         {
-          if (!single_exit (loop))
-	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-			     "not vectorized: multiple exits.\n");
-          else if (EDGE_COUNT (loop->header->preds) != 2)
-	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-			     "not vectorized: too many incoming edges.\n");
+	  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+			   "not vectorized: multiple exits.\n");
         }
-      return false;
+      return opt_result::failure ("multiple exits", NULL);
+    }
+  if (EDGE_COUNT (loop->header->preds) != 2)
+    {
+      if (dump_enabled_p ())
+        {
+	  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+			   "not vectorized: too many incoming edges.\n");
+        }
+      return opt_result::failure ("too many incoming edges", NULL);
     }
 
   /* We assume that the loop exit condition is at the end of the loop. i.e,
@@ -1645,7 +1659,7 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
 				   "supported: ");
                   dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, phi, 0);
                 }
-	      return false;
+	      return opt_result::failure ("relevant phi not supported", phi);
             }
         }
 
@@ -2214,11 +2228,13 @@ again:
   /* Try again with SLP forced off but if we didn't do any SLP there is
      no point in re-trying.  */
   if (!slp)
-    return false;
+    // do we need to capture the last thing before the "goto"?
+    return opt_result::failure ("FIXME: need a message here", NULL);
 
   /* If there are reduction chains re-trying will fail anyway.  */
   if (! LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo).is_empty ())
-    return false;
+    // do we need to capture the last thing before the "goto"?
+    return opt_result::failure ("FIXME: need a message here", NULL);
 
   /* Likewise if the grouped loads or stores in the SLP cannot be handled
      via interleaving or lane instructions.  */
@@ -2238,7 +2254,7 @@ again:
       if (! vect_store_lanes_supported (vectype, size, false)
 	 && ! known_eq (TYPE_VECTOR_SUBPARTS (vectype), 1U)
 	 && ! vect_grouped_store_supported (vectype, size))
-       return false;
+	return opt_result::failure ("FIXME: need a message here", NULL);
       FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), j, node)
 	{
 	  vinfo = vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (node)[0]);
@@ -2249,7 +2265,7 @@ again:
 	  if (! vect_load_lanes_supported (vectype, size, false)
 	      && ! vect_grouped_load_supported (vectype, single_element_p,
 						size))
-	    return false;
+	    return opt_result::failure ("FIXME: need a message here", NULL);
 	}
     }
 
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 2bee13c..6455dd0 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -10779,7 +10779,8 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
 				 scalar_type);
 	      dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
 	    }
-	  return false;
+	  // FIXME: should capture scalar_type
+	  return opt_result::failure ("unsupported data-type", stmt);
 	}
 
       if (!*stmt_vectype_out)
@@ -10826,7 +10827,8 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
 	  dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, scalar_type);
 	  dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
 	}
-      return false;
+      // FIXME: should capture scalar_type
+      return opt_result::failure ("unsupported data-type", stmt);
     }
 
   if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (vectype)),
@@ -10863,7 +10865,7 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
    statement that produces a scalar boolean result.  Return the vector
    type on success, otherwise return NULL_TREE.  */
 
-tree
+opt_tree
 vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
 {
   gimple *stmt = stmt_info->stmt;
@@ -10882,7 +10884,7 @@ vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
 	  if (dump_enabled_p ())
 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
 			     "not vectorized: unsupported mask\n");
-	  return NULL_TREE;
+	  return opt_tree::failure ("unsupported mask", stmt);
 	}
     }
   else
@@ -10903,7 +10905,8 @@ vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
 		  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt,
 				    0);
 		}
-	      return NULL_TREE;
+	      return opt_tree::failure ("can't compute mask type for"
+					" statement", stmt);
 	    }
 
 	  /* No vectype probably means external definition.
@@ -10929,7 +10932,9 @@ vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
 				     vectype);
 		  dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
 		}
-	      return NULL_TREE;
+	      // FIXME: print the types
+	      return opt_tree::failure ("different sized masks "
+					" types in statement", stmt);
 	    }
 	  else if (VECTOR_BOOLEAN_TYPE_P (mask_type)
 		   != VECTOR_BOOLEAN_TYPE_P (vectype))
@@ -10946,7 +10951,9 @@ vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
 				     vectype);
 		  dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
 		}
-	      return NULL_TREE;
+	      // FIXME: print the types
+	      return opt_tree::failure ("mixed mask and "
+					"nonmask vector types in statement");
 	    }
 	}
 
@@ -10961,12 +10968,17 @@ vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
 
   /* No mask_type should mean loop invariant predicate.
      This is probably a subject for optimization in if-conversion.  */
-  if (!mask_type && dump_enabled_p ())
+  if (!mask_type)
     {
-      dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-		       "not vectorized: can't compute mask type "
-		       "for statement, ");
-      dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
+      if (dump_enabled_p ())
+	{
+	  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+			   "not vectorized: can't compute mask type "
+			   "for statement, ");
+	  dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
+	}
+      return opt_tree::failure ("can't compute mask type "
+				"for statement", stmt);
     }
-  return mask_type;
+  return opt_tree::success (mask_type);
 }
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index e822c08..97f280b 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1550,7 +1550,7 @@ extern gcall *vect_gen_while (tree, tree, tree);
 extern tree vect_gen_while_not (gimple_seq *, tree, tree, tree);
 extern opt_result vect_get_vector_types_for_stmt (stmt_vec_info, tree *,
 						  tree *);
-extern tree vect_get_mask_type_for_stmt (stmt_vec_info);
+extern opt_tree vect_get_mask_type_for_stmt (stmt_vec_info);
 
 /* In tree-vect-data-refs.c.  */
 extern bool vect_can_force_dr_alignment_p (const_tree, unsigned int);
-- 
1.8.5.3

