aboutsummaryrefslogtreecommitdiff
path: root/gcc/internal-fn.c
diff options
context:
space:
mode:
authorPrathamesh Kulkarni <prathamesh.kulkarni@linaro.org>2016-10-28 19:05:12 +0000
committerPrathamesh Kulkarni <prathamesh3492@gcc.gnu.org>2016-10-28 19:05:12 +0000
commite72531b9cb3c214731f0e0f64f53033d3efb80ca (patch)
tree9837b3df122e46bd34e1497c40a603aa1033fab1 /gcc/internal-fn.c
parent0dfeae289cc3c97f0f61d02c81df393e720badf9 (diff)
downloadgcc-e72531b9cb3c214731f0e0f64f53033d3efb80ca.zip
gcc-e72531b9cb3c214731f0e0f64f53033d3efb80ca.tar.gz
gcc-e72531b9cb3c214731f0e0f64f53033d3efb80ca.tar.bz2
re PR tree-optimization/43721 (Failure to optimise (a/b) and (a%b) into single __aeabi_idivmod call)
2016-10-28 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> Kugan Vivekanandarajah <kuganv@linaro.org> Jim Wilson <jim.wilson@linaro.org> PR tree-optimization/43721 * target.def: New hook expand_divmod_libfunc. * doc/tm.texi.in: Add hook for TARGET_EXPAND_DIVMOD_LIBFUNC * doc/tm.texi: Regenerate. * internal-fn.def: Add new entry for DIVMOD ifn. * internal-fn.c (expand_DIVMOD): New. * tree-ssa-math-opts.c: Include optabs-libfuncs.h, tree-eh.h, targhooks.h. (widen_mul_stats): Add new field divmod_calls_inserted. (target_supports_divmod_p): New. (divmod_candidate_p): Likewise. (convert_to_divmod): Likewise. (pass_optimize_widening_mul::execute): Call calculate_dominance_info(), renumber_gimple_stmt_uids() at beginning of function. Call convert_to_divmod() and record stats for divmod. * config/arm/arm.c (arm_expand_divmod_libfunc): Override hook TARGET_EXPAND_DIVMOD_LIBFUNC. * doc/sourcebuild.texi: Add items for arm_divmod_simode, divmod, divmod_simode. testsuite/ * lib/target-supports.exp (check_effective_target_divmod): New. (check_effective_target_divmod_simode): Likewise. (check_effective_target_arm_divmod_simode): Likewise. * gcc.dg/divmod-1-simode.c: New test. * gcc.dg/divmod-1.c: Likewise. * gcc.dg/divmod-2-simode.c: Likewise. * gcc.dg/divmod-2.c: Likewise. * gcc.dg/divmod-3-simode.c: Likewise. * gcc.dg/divmod-3.c: Likewise. * gcc.dg/divmod-4-simode.c: Likewise. * gcc.dg/divmod-4.c: Likewise. * gcc.dg/divmod-5.c: Likewise. * gcc.dg/divmod-6-simode.c: Likewise. * gcc.dg/divmod-6.c: Likewise. * gcc.dg/divmod-7.c: Likewise. Co-Authored-By: Jim Wilson <jim.wilson@linaro.org> Co-Authored-By: Kugan Vivekanandarajah <kuganv@linaro.org> From-SVN: r241660
Diffstat (limited to 'gcc/internal-fn.c')
-rw-r--r--gcc/internal-fn.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 156ba31..1eeb15e 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2232,6 +2232,53 @@ expand_LAUNDER (internal_fn, gcall *call)
expand_assignment (lhs, gimple_call_arg (call, 0), false);
}
+/* Expand DIVMOD() using:
+ a) optab handler for udivmod/sdivmod if it is available.
+ b) If optab_handler doesn't exist, generate call to
+ target-specific divmod libfunc. */
+
+static void
+expand_DIVMOD (internal_fn, gcall *call_stmt)
+{
+ tree lhs = gimple_call_lhs (call_stmt);
+ tree arg0 = gimple_call_arg (call_stmt, 0);
+ tree arg1 = gimple_call_arg (call_stmt, 1);
+
+ gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
+ tree type = TREE_TYPE (TREE_TYPE (lhs));
+ machine_mode mode = TYPE_MODE (type);
+ bool unsignedp = TYPE_UNSIGNED (type);
+ optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
+
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
+
+ rtx quotient, remainder, libfunc;
+
+ /* Check if optab_handler exists for divmod_optab for given mode. */
+ if (optab_handler (tab, mode) != CODE_FOR_nothing)
+ {
+ quotient = gen_reg_rtx (mode);
+ remainder = gen_reg_rtx (mode);
+ expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
+ }
+
+ /* Generate call to divmod libfunc if it exists. */
+ else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
+ targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
+ &quotient, &remainder);
+
+ else
+ gcc_unreachable ();
+
+ /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
+ expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
+ make_tree (TREE_TYPE (arg0), quotient),
+ make_tree (TREE_TYPE (arg1), remainder)),
+ target, VOIDmode, EXPAND_NORMAL);
+}
+
/* Expand a call to FN using the operands in STMT. FN has a single
output operand and NARGS input operands. */