+2019-06-18 Kewen Lin <linkw@gcc.gnu.org>
+
+ PR middle-end/80791
+ * target.def (predict_doloop_p): New hook.
+ * targhooks.h (default_predict_doloop_p): New declaration.
+ * targhooks.c (default_predict_doloop_p): New function.
+ * doc/tm.texi.in (TARGET_PREDICT_DOLOOP_P): New hook.
+ * doc/tm.texi: Regenerate.
+ * config/rs6000/rs6000.c (rs6000_predict_doloop_p): New function.
+ (TARGET_PREDICT_DOLOOP_P): New macro.
+ * tree-ssa-loop-ivopts.c (generic_predict_doloop_p): New function.
+
2019-06-17 Jakub Jelinek <jakub@redhat.com>
* omp-low.c (struct omp_context): Add scan_inclusive field.
#undef TARGET_CAN_USE_DOLOOP_P
#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
+#undef TARGET_PREDICT_DOLOOP_P
+#define TARGET_PREDICT_DOLOOP_P rs6000_predict_doloop_p
+
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV rs6000_atomic_assign_expand_fenv
return id;
}
-\f
+/* Predict whether the given loop in gimple will be transformed in the RTL
+ doloop_optimize pass. */
+
+static bool
+rs6000_predict_doloop_p (struct loop *loop)
+{
+ gcc_assert (loop);
+
+ /* On rs6000, targetm.can_use_doloop_p is actually
+ can_use_doloop_if_innermost. Just ensure the loop is innermost. */
+ if (loop->inner != NULL)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predict doloop failure due to"
+ " loop nesting.\n");
+ return false;
+ }
+
+ return true;
+}
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rs6000.h"
body must be generated.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_PREDICT_DOLOOP_P (struct loop *@var{loop})
+Return true if we can predict it is possible to use a low-overhead loop
+for a particular loop. The parameter @var{loop} is a pointer to the loop.
+This target hook is required only when the target supports low-overhead
+loops, and will help ivopts to make some decisions.
+The default version of this hook returns false.
+@end deftypefn
+
@deftypefn {Target Hook} bool TARGET_CAN_USE_DOLOOP_P (const widest_int @var{&iterations}, const widest_int @var{&iterations_max}, unsigned int @var{loop_depth}, bool @var{entered_at_top})
Return true if it is possible to use low-overhead loops (@code{doloop_end}
and @code{doloop_begin}) for a particular loop. @var{iterations} gives the
@hook TARGET_GENERATE_VERSION_DISPATCHER_BODY
+@hook TARGET_PREDICT_DOLOOP_P
+
@hook TARGET_CAN_USE_DOLOOP_P
@hook TARGET_INVALID_WITHIN_DOLOOP
rtx, (machine_mode mode, rtx result, rtx val, rtx failval),
default_speculation_safe_value)
+DEFHOOK
+(predict_doloop_p,
+ "Return true if we can predict it is possible to use a low-overhead loop\n\
+for a particular loop. The parameter @var{loop} is a pointer to the loop.\n\
+This target hook is required only when the target supports low-overhead\n\
+loops, and will help ivopts to make some decisions.\n\
+The default version of this hook returns false.",
+ bool, (struct loop *loop),
+ default_predict_doloop_p)
DEFHOOK
(can_use_doloop_p,
return HAVE_GNU_INDIRECT_FUNCTION;
}
+/* Return true if we predict the loop LOOP will be transformed to a
+ low-overhead loop, otherwise return false.
+
+ By default, false is returned, as this hook's applicability should be
+ verified for each target. Target maintainers should re-define the hook
+ if the target can take advantage of it. */
+
+bool
+default_predict_doloop_p (struct loop *loop ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
/* NULL if INSN insn is valid within a low-overhead loop, otherwise returns
an error message.
extern bool default_has_ifunc_p (void);
+extern bool default_predict_doloop_p (struct loop *);
extern const char * default_invalid_within_doloop (const rtx_insn *);
extern tree default_builtin_vectorized_function (unsigned int, tree, tree);
return NULL_TREE;
}
+/* Predict whether the given loop will be transformed in the RTL
+ doloop_optimize pass. Attempt to duplicate some doloop_optimize checks.
+ This is only for target independent checks, see targetm.predict_doloop_p
+ for the target dependent ones.
+
+ Note that according to some initial investigation, some checks like costly
+ niter check and invalid stmt scanning don't have much gains among general
+ cases, so keep this as simple as possible first.
+
+ Some RTL specific checks seems unable to be checked in gimple, if any new
+ checks or easy checks _are_ missing here, please add them. */
+
+static bool ATTRIBUTE_UNUSED
+generic_predict_doloop_p (struct ivopts_data *data)
+{
+ struct loop *loop = data->current_loop;
+
+ /* Call target hook for target dependent checks. */
+ if (!targetm.predict_doloop_p (loop))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predict doloop failure due to"
+ " target specific checks.\n");
+ return false;
+ }
+
+ /* Similar to doloop_optimize, check iteration description to know it's
+ suitable or not. Keep it as simple as possible, feel free to extend it
+ if you find any multiple exits cases matter. */
+ edge exit = single_dom_exit (loop);
+ struct tree_niter_desc *niter_desc;
+ if (!exit || !(niter_desc = niter_for_exit (data, exit)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predict doloop failure due to"
+ " unexpected niters.\n");
+ return false;
+ }
+
+ /* Similar to doloop_optimize, check whether iteration count too small
+ and not profitable. */
+ HOST_WIDE_INT est_niter = get_estimated_loop_iterations_int (loop);
+ if (est_niter == -1)
+ est_niter = get_likely_max_loop_iterations_int (loop);
+ if (est_niter >= 0 && est_niter < 3)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Predict doloop failure due to"
+ " too few iterations (%u).\n",
+ (unsigned int) est_niter);
+ return false;
+ }
+
+ return true;
+}
+
/* Determines cost of the computation of EXPR. */
static unsigned