This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PR68432 21/22] Pass optimization type to direct_internal_fn_supported_p


This adds an argument to direct_internal_fn_supported_p that says
whether the function is going to be used in code optimised for size
or speed.  It also has a "both" option for cases where we want code
that is optimised for both size and speed.

At the moment the match-and-simplify code doesn't have direct access
to the target block, so for now I've used "both" there.

Tested as described in the covering note.

gcc/
	* coretypes.h (optimization_type): New enum.
	* predict.h (function_optimization_type): Declare.
	(bb_optimization_type): Likewise.
	* predict.c (function_optimization_type): New function.
	(bb_optimization_type): Likewise.
	* optabs-query.h (optab_supported_p): Declare.
	* optabs-query.c (optab_supported_p): New function.
	* internal-fn.h (direct_internal_fn_supported_p): Take an
	optimization_type argument.
	* internal-fn.c (direct_optab_supported_p): Likewise.
	(multi_vector_optab_supported_p): Likewise.
	(direct_internal_fn_supported_p): Likewise.
	* builtins.c (replacement_internal_fn): Update call to
	direct_internal_fn_supported_p.
	* gimple-match-head.c (build_call_internal): Likewise.
	* tree-vect-patterns.c (vect_recog_pow_pattern): Likewise.
	* tree-vect-stmts.c (vectorizable_internal_function): Likewise.
	* tree.c (maybe_build_call_expr_loc): Likewise.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index df5c493..7c614e6 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1962,7 +1962,8 @@ replacement_internal_fn (gcall *call)
       if (ifn != IFN_LAST)
 	{
 	  tree_pair types = direct_internal_fn_types (ifn, call);
-	  if (direct_internal_fn_supported_p (ifn, types))
+	  optimization_type opt_type = bb_optimization_type (gimple_bb (call));
+	  if (direct_internal_fn_supported_p (ifn, types, opt_type))
 	    return ifn;
 	}
     }
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index d4a75db..5a9fb63 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -200,6 +200,18 @@ enum node_frequency {
   NODE_FREQUENCY_HOT
 };
 
+/* Ways of optimizing code.  */
+enum optimization_type {
+  /* Prioritize speed over size.  */
+  OPTIMIZE_FOR_SPEED,
+
+  /* Only do things that are good for both size and speed.  */
+  OPTIMIZE_FOR_BOTH,
+
+  /* Prioritize size over speed.  */
+  OPTIMIZE_FOR_SIZE
+};
+
 /* Possible initialization status of a variable.   When requested
    by the user, this information is tracked and recorded in the DWARF
    debug information, along with the variable's location.  */
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index bdc1f98..049ebab 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -261,7 +261,7 @@ build_call_internal (internal_fn fn, tree type, unsigned int nargs, tree *ops)
   if (direct_internal_fn_p (fn))
     {
       tree_pair types = direct_internal_fn_types (fn, type, ops);
-      if (!direct_internal_fn_supported_p (fn, types))
+      if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH))
 	return NULL;
     }
   return gimple_build_call_internal (fn, nargs, ops[0], ops[1], ops[2]);
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index b15657f..c6d2c9a 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2214,23 +2214,28 @@ direct_internal_fn_types (internal_fn fn, gcall *call)
 }
 
 /* Return true if OPTAB is supported for TYPES (whose modes should be
-   the same).  Used for simple direct optabs.  */
+   the same) when the optimization type is OPT_TYPE.  Used for simple
+   direct optabs.  */
 
 static bool
-direct_optab_supported_p (direct_optab optab, tree_pair types)
+direct_optab_supported_p (direct_optab optab, tree_pair types,
+			  optimization_type opt_type)
 {
   machine_mode mode = TYPE_MODE (types.first);
   gcc_checking_assert (mode == TYPE_MODE (types.second));
-  return direct_optab_handler (optab, mode) != CODE_FOR_nothing;
+  insn_code icode = direct_optab_handler (optab, mode);
+  return optab_supported_p (icode, opt_type);
 }
 
 /* Return true if load/store lanes optab OPTAB is supported for
-   array type TYPES.first.  */
+   array type TYPES.first when the optimization type is OPT_TYPE.  */
 
 static bool
-multi_vector_optab_supported_p (convert_optab optab, tree_pair types)
+multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
+				optimization_type opt_type)
 {
-  return get_multi_vector_move (types.first, optab) != CODE_FOR_nothing;
+  insn_code icode = get_multi_vector_move (types.first, optab);
+  return optab_supported_p (icode, opt_type);
 }
 
 #define direct_unary_optab_supported_p direct_optab_supported_p
@@ -2240,12 +2245,14 @@ multi_vector_optab_supported_p (convert_optab optab, tree_pair types)
 #define direct_mask_store_optab_supported_p direct_optab_supported_p
 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
 
-/* Return true if FN is supported for the types in TYPES.  The types
-   are those associated with the "type0" and "type1" fields of FN's
-   direct_internal_fn_info structure.  */
+/* Return true if FN is supported for the types in TYPES when the
+   optimization type is OPT_TYPE.  The types are those associated with
+   the "type0" and "type1" fields of FN's direct_internal_fn_info
+   structure.  */
 
 bool
-direct_internal_fn_supported_p (internal_fn fn, tree_pair types)
+direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
+				optimization_type opt_type)
 {
   switch (fn)
     {
@@ -2253,7 +2260,8 @@ direct_internal_fn_supported_p (internal_fn fn, tree_pair types)
     case IFN_##CODE: break;
 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
     case IFN_##CODE: \
-      return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types);
+      return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
+						opt_type);
 #include "internal-fn.def"
 
     case IFN_LAST:
@@ -2262,16 +2270,17 @@ direct_internal_fn_supported_p (internal_fn fn, tree_pair types)
   gcc_unreachable ();
 }
 
-/* Return true if FN is supported for type TYPE.  The caller knows that
-   the "type0" and "type1" fields of FN's direct_internal_fn_info
-   structure are the same.  */
+/* Return true if FN is supported for type TYPE when the optimization
+   type is OPT_TYPE.  The caller knows that the "type0" and "type1"
+   fields of FN's direct_internal_fn_info structure are the same.  */
 
 bool
-direct_internal_fn_supported_p (internal_fn fn, tree type)
+direct_internal_fn_supported_p (internal_fn fn, tree type,
+				optimization_type opt_type)
 {
   const direct_internal_fn_info &info = direct_internal_fn (fn);
   gcc_checking_assert (info.type0 == info.type1);
-  return direct_internal_fn_supported_p (fn, tree_pair (type, type));
+  return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
 }
 
 /* Return true if IFN_SET_EDOM is supported.  */
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index aea6abd..ef27f09 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -166,8 +166,10 @@ direct_internal_fn (internal_fn fn)
 
 extern tree_pair direct_internal_fn_types (internal_fn, tree, tree *);
 extern tree_pair direct_internal_fn_types (internal_fn, gcall *);
-extern bool direct_internal_fn_supported_p (internal_fn, tree_pair);
-extern bool direct_internal_fn_supported_p (internal_fn, tree);
+extern bool direct_internal_fn_supported_p (internal_fn, tree_pair,
+					    optimization_type);
+extern bool direct_internal_fn_supported_p (internal_fn, tree,
+					    optimization_type);
 extern bool set_edom_supported_p (void);
 
 extern void expand_internal_call (gcall *);
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index c20597c..a059aa2 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -35,6 +35,36 @@ struct target_optabs *this_fn_optabs = &default_target_optabs;
 struct target_optabs *this_target_optabs = &default_target_optabs;
 #endif
 
+/* Return true if ICODE is a valid instruction number and the instruction
+   is supported for optimization type OPT_TYPE.  We allow CODE_FOR_nothing
+   to be passed so that callers can use this function instead of, rather
+   than as well as, an explicit check for CODE_nothing.  */
+
+bool
+optab_supported_p (insn_code icode, optimization_type opt_type)
+{
+  if (icode == CODE_FOR_nothing)
+    return false;
+
+  switch (opt_type)
+    {
+    case OPTIMIZE_FOR_SPEED:
+      return (get_bool_attr_mask (icode, BA_PREFERRED_FOR_SPEED)
+	      == get_bool_attr_mask (icode, BA_ENABLED));
+
+    case OPTIMIZE_FOR_SIZE:
+      return (get_bool_attr_mask (icode, BA_PREFERRED_FOR_SIZE)
+	      == get_bool_attr_mask (icode, BA_ENABLED));
+
+    case OPTIMIZE_FOR_BOTH:
+      /* Require the choice to be good for both size and speed.  */
+      return ((get_bool_attr_mask (icode, BA_PREFERRED_FOR_SIZE)
+	       & get_bool_attr_mask (icode, BA_PREFERRED_FOR_SPEED))
+	      == get_bool_attr_mask (icode, BA_ENABLED));
+    }
+  gcc_unreachable ();
+}
+
 /* Enumerates the possible types of structure operand to an
    extraction_insn.  */
 enum extraction_type { ET_unaligned_mem, ET_reg };
diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h
index 48bcf7c..1898b57 100644
--- a/gcc/optabs-query.h
+++ b/gcc/optabs-query.h
@@ -136,6 +136,7 @@ bool get_best_mem_extraction_insn (extraction_insn *,
 				   enum extraction_pattern,
 				   HOST_WIDE_INT, HOST_WIDE_INT, machine_mode);
 
+bool optab_supported_p (insn_code, optimization_type);
 enum insn_code can_extend_p (machine_mode, machine_mode, int);
 enum insn_code can_float_p (machine_mode, machine_mode, int);
 enum insn_code can_fix_p (machine_mode, machine_mode, int, bool *);
diff --git a/gcc/predict.c b/gcc/predict.c
index 7e0f848..d5c40de 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -269,6 +269,16 @@ optimize_function_for_speed_p (struct function *fun)
   return !optimize_function_for_size_p (fun);
 }
 
+/* Return the optimization type that should be used for the function FUN.  */
+
+optimization_type
+function_optimization_type (struct function *fun)
+{
+  return (optimize_function_for_speed_p (fun)
+	  ? OPTIMIZE_FOR_SPEED
+	  : OPTIMIZE_FOR_SIZE);
+}
+
 /* Return TRUE when BB should be optimized for size.  */
 
 bool
@@ -286,6 +296,16 @@ optimize_bb_for_speed_p (const_basic_block bb)
   return !optimize_bb_for_size_p (bb);
 }
 
+/* Return the optimization type that should be used for block BB.  */
+
+optimization_type
+bb_optimization_type (const_basic_block bb)
+{
+  return (optimize_bb_for_speed_p (bb)
+	  ? OPTIMIZE_FOR_SPEED
+	  : OPTIMIZE_FOR_SIZE);
+}
+
 /* Return TRUE when BB should be optimized for size.  */
 
 bool
diff --git a/gcc/predict.h b/gcc/predict.h
index 85150fe..486ce17 100644
--- a/gcc/predict.h
+++ b/gcc/predict.h
@@ -54,8 +54,10 @@ extern bool probably_never_executed_bb_p (struct function *, const_basic_block);
 extern bool probably_never_executed_edge_p (struct function *, edge);
 extern bool optimize_function_for_size_p (struct function *);
 extern bool optimize_function_for_speed_p (struct function *);
+extern optimization_type function_optimization_type (struct function *);
 extern bool optimize_bb_for_size_p (const_basic_block);
 extern bool optimize_bb_for_speed_p (const_basic_block);
+extern optimization_type bb_optimization_type (const_basic_block);
 extern bool optimize_edge_for_size_p (edge);
 extern bool optimize_edge_for_speed_p (edge);
 extern bool optimize_insn_for_size_p (void);
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 5bab1f5..cd142e1 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -1056,7 +1056,9 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
       && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
     {
       *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
-      if (*type_in && direct_internal_fn_supported_p (IFN_SQRT, *type_in))
+      if (*type_in
+	  && direct_internal_fn_supported_p (IFN_SQRT, *type_in,
+					     OPTIMIZE_FOR_SPEED))
 	{
 	  gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base);
 	  var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 687f982..fe6f44b 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1663,7 +1663,8 @@ vectorizable_internal_function (combined_fn cfn, tree fndecl,
 	{
 	  tree type0 = (info.type0 < 0 ? vectype_out : vectype_in);
 	  tree type1 = (info.type1 < 0 ? vectype_out : vectype_in);
-	  if (direct_internal_fn_supported_p (ifn, tree_pair (type0, type1)))
+	  if (direct_internal_fn_supported_p (ifn, tree_pair (type0, type1),
+					      OPTIMIZE_FOR_SPEED))
 	    return ifn;
 	}
     }
diff --git a/gcc/tree.c b/gcc/tree.c
index 779fe93..e367030 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -11124,7 +11124,8 @@ maybe_build_call_expr_loc (location_t loc, combined_fn fn, tree type,
       if (direct_internal_fn_p (ifn))
 	{
 	  tree_pair types = direct_internal_fn_types (ifn, type, argarray);
-	  if (!direct_internal_fn_supported_p (ifn, types))
+	  if (!direct_internal_fn_supported_p (ifn, types,
+					       OPTIMIZE_FOR_BOTH))
 	    return NULL_TREE;
 	}
       return build_call_expr_internal_loc_array (loc, ifn, type, n, argarray);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]