PR middle-end/29274
* optabs.h (expand_widening_mult): Declare.
* tree-pass.h (pass_optimize_widening_mul): Declare.
* tree-ssa-math-opts.c (execute_optimize_widening_mul,
gate_optimize_widening_mul): New static functions.
(pass_optimize_widening_mul): New.
* expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: New
case.
<case MULT_EXPR>: Remove support for widening multiplies.
* tree.def (WIDEN_MULT_EXPR): Tweak comment.
* cfgexpand.c (expand_debug_expr) <case WIDEN_MULT_EXPR>: Use
simplify_gen_unary rather than directly building extensions.
* tree-cfg.c (verify_gimple_assign_binary): Add tests for
WIDEN_MULT_EXPR.
* expmed.c (expand_widening_mult): New function.
* passes.c (init_optimization_passes): Add pass_optimize_widening_mul.
gcc/testsuite/
PR middle-end/29274
* gcc.target/i386/wmul-1.c: New test.
* gcc.target/i386/wmul-2.c: New test.
* gcc.target/bfin/wmul-1.c: New test.
* gcc.target/bfin/wmul-2.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158633
138bc75d-0d04-0410-961f-
82ee72b054a4
+2010-04-22 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR middle-end/29274
+ * optabs.h (expand_widening_mult): Declare.
+ * tree-pass.h (pass_optimize_widening_mul): Declare.
+ * tree-ssa-math-opts.c (execute_optimize_widening_mul,
+ gate_optimize_widening_mul): New static functions.
+ (pass_optimize_widening_mul): New.
+ * expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: New
+ case.
+ <case MULT_EXPR>: Remove support for widening multiplies.
+ * tree.def (WIDEN_MULT_EXPR): Tweak comment.
+ * cfgexpand.c (expand_debug_expr) <case WIDEN_MULT_EXPR>: Use
+ simplify_gen_unary rather than directly building extensions.
+ * tree-cfg.c (verify_gimple_assign_binary): Add tests for
+ WIDEN_MULT_EXPR.
+ * expmed.c (expand_widening_mult): New function.
+ * passes.c (init_optimization_passes): Add pass_optimize_widening_mul.
+
2010-04-21 Jan Hubicka <jh@suse.cz>
* timevar.def (TV_WHOPR_WPA_FIXUP): Remove.
gcc_assert (op0);
return op0;
}
+
+/* Perform a widening multiplication and return an rtx for the result.
+ MODE is mode of value; OP0 and OP1 are what to multiply (rtx's);
+ TARGET is a suggestion for where to store the result (an rtx).
+ THIS_OPTAB is the optab we should use, it must be either umul_widen_optab
+ or smul_widen_optab.
+
+ We check specially for a constant integer as OP1, comparing the
+ cost of a widening multiply against the cost of a sequence of shifts
+ and adds. */
+
+rtx
+expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
+ int unsignedp, optab this_optab)
+{
+ bool speed = optimize_insn_for_speed_p ();
+
+ if (CONST_INT_P (op1)
+ && (INTVAL (op1) >= 0
+ || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT))
+ {
+ HOST_WIDE_INT coeff = INTVAL (op1);
+ int max_cost;
+ enum mult_variant variant;
+ struct algorithm algorithm;
+
+ /* Special case powers of two. */
+ if (EXACT_POWER_OF_2_OR_ZERO_P (coeff))
+ {
+ op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab);
+ return expand_shift (LSHIFT_EXPR, mode, op0,
+ build_int_cst (NULL_TREE, floor_log2 (coeff)),
+ target, unsignedp);
+ }
+
+ /* Exclude cost of op0 from max_cost to match the cost
+ calculation of the synth_mult. */
+ max_cost = mul_widen_cost[speed][mode];
+ if (choose_mult_variant (mode, coeff, &algorithm, &variant,
+ max_cost))
+ {
+ op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab);
+ return expand_mult_const (mode, op0, coeff, target,
+ &algorithm, variant);
+ }
+ }
+ return expand_binop (mode, this_optab, op0, op1, target,
+ unsignedp, OPTAB_LIB_WIDEN);
+}
\f
/* Return the smallest n such that 2**n >= X. */
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_phiopt);
NEXT_PASS (pass_fold_builtins);
+ NEXT_PASS (pass_optimize_widening_mul);
NEXT_PASS (pass_tail_calls);
NEXT_PASS (pass_rename_ssa_copies);
NEXT_PASS (pass_uncprop);
+2010-04-22 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR middle-end/29274
+ * gcc.target/i386/wmul-1.c: New test.
+ * gcc.target/i386/wmul-2.c: New test.
+ * gcc.target/bfin/wmul-1.c: New test.
+ * gcc.target/bfin/wmul-2.c: New test.
+
2010-04-22 Richard Guenther <rguenther@suse.de>
PR fortran/43829
/* { dg-do compile } */
/* { dg-options "-O2" } */
-/* { dg-require-effective-target ilp32 } */
long long mac(const int *a, const int *b, long long sqr, long long *sum)
{
/* { dg-do compile } */
/* { dg-options "-O2" } */
-/* { dg-require-effective-target ilp32 } */
void vec_mpy(int y[], const int x[], int scaler)
{
connected to the operand types. */
return verify_gimple_comparison (lhs_type, rhs1, rhs2);
- case WIDEN_SUM_EXPR:
case WIDEN_MULT_EXPR:
+ if (TREE_CODE (lhs_type) != INTEGER_TYPE)
+ return true;
+ return ((2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type))
+ || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)));
+
+ case WIDEN_SUM_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_PACK_TRUNC_EXPR:
extern struct gimple_opt_pass pass_cse_reciprocals;
extern struct gimple_opt_pass pass_cse_sincos;
extern struct gimple_opt_pass pass_optimize_bswap;
+extern struct gimple_opt_pass pass_optimize_widening_mul;
extern struct gimple_opt_pass pass_warn_function_return;
extern struct gimple_opt_pass pass_warn_function_noreturn;
extern struct gimple_opt_pass pass_cselim;