aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2010-04-22 09:30:27 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2010-04-22 09:30:27 +0000
commit5b58b39b0a7d1c79b0d57e51199864f9a3685bb4 (patch)
tree9248604cc9a0efe5af0b9ed453fe7110c80743c8 /gcc/expr.c
parent92375a2020b1f32bf7be92025493cebd9b3b4400 (diff)
downloadgcc-5b58b39b0a7d1c79b0d57e51199864f9a3685bb4.zip
gcc-5b58b39b0a7d1c79b0d57e51199864f9a3685bb4.tar.gz
gcc-5b58b39b0a7d1c79b0d57e51199864f9a3685bb4.tar.bz2
re PR middle-end/29274 (not using mulsidi3)
gcc/ 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. From-SVN: r158633
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c170
1 files changed, 73 insertions, 97 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 2547511..5448bbe 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7212,7 +7212,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
optab this_optab;
rtx subtarget, original_target;
int ignore;
- tree subexp0, subexp1;
bool reduce_bit_field;
gimple subexp0_def, subexp1_def;
tree top0, top1;
@@ -7667,13 +7666,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
goto binop2;
- case MULT_EXPR:
- /* If this is a fixed-point operation, then we cannot use the code
- below because "expand_mult" doesn't support sat/no-sat fixed-point
- multiplications. */
- if (ALL_FIXED_POINT_MODE_P (mode))
- goto binop;
-
+ case WIDEN_MULT_EXPR:
/* If first operand is constant, swap them.
Thus the following special case checks need only
check the second operand. */
@@ -7684,96 +7677,35 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
treeop1 = t1;
}
- /* Attempt to return something suitable for generating an
- indexed address, for machines that support that. */
-
- if (modifier == EXPAND_SUM && mode == ptr_mode
- && host_integerp (treeop1, 0))
- {
- tree exp1 = treeop1;
-
- op0 = expand_expr (treeop0, subtarget, VOIDmode,
- EXPAND_SUM);
-
- if (!REG_P (op0))
- op0 = force_operand (op0, NULL_RTX);
- if (!REG_P (op0))
- op0 = copy_to_mode_reg (mode, op0);
-
- return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
- gen_int_mode (tree_low_cst (exp1, 0),
- TYPE_MODE (TREE_TYPE (exp1)))));
- }
-
- if (modifier == EXPAND_STACK_PARM)
- target = 0;
-
- /* Check for multiplying things that have been extended
- from a narrower type. If this machine supports multiplying
- in that narrower type with a result in the desired type,
- do it that way, and avoid the explicit type-conversion. */
-
- subexp0 = treeop0;
- subexp1 = treeop1;
- subexp0_def = get_def_for_expr (subexp0, NOP_EXPR);
- subexp1_def = get_def_for_expr (subexp1, NOP_EXPR);
- top0 = top1 = NULL_TREE;
-
/* First, check if we have a multiplication of one signed and one
unsigned operand. */
- if (subexp0_def
- && (top0 = gimple_assign_rhs1 (subexp0_def))
- && subexp1_def
- && (top1 = gimple_assign_rhs1 (subexp1_def))
- && TREE_CODE (type) == INTEGER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (top0))
- < TYPE_PRECISION (TREE_TYPE (subexp0)))
- && (TYPE_PRECISION (TREE_TYPE (top0))
- == TYPE_PRECISION (TREE_TYPE (top1)))
- && (TYPE_UNSIGNED (TREE_TYPE (top0))
- != TYPE_UNSIGNED (TREE_TYPE (top1))))
+ if (TREE_CODE (treeop1) != INTEGER_CST
+ && (TYPE_UNSIGNED (TREE_TYPE (treeop0))
+ != TYPE_UNSIGNED (TREE_TYPE (treeop1))))
{
- enum machine_mode innermode
- = TYPE_MODE (TREE_TYPE (top0));
+ enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0));
this_optab = usmul_widen_optab;
- if (mode == GET_MODE_WIDER_MODE (innermode))
+ if (mode == GET_MODE_2XWIDER_MODE (innermode))
{
if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
{
- if (TYPE_UNSIGNED (TREE_TYPE (top0)))
- expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+ if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1,
EXPAND_NORMAL);
else
- expand_operands (top0, top1, NULL_RTX, &op1, &op0,
+ expand_operands (treeop0, treeop1, subtarget, &op1, &op0,
EXPAND_NORMAL);
-
goto binop3;
}
}
}
- /* Check for a multiplication with matching signedness. If
- valid, TOP0 and TOP1 were set in the previous if
- condition. */
- else if (top0
- && TREE_CODE (type) == INTEGER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (top0))
- < TYPE_PRECISION (TREE_TYPE (subexp0)))
- && ((TREE_CODE (subexp1) == INTEGER_CST
- && int_fits_type_p (subexp1, TREE_TYPE (top0))
- /* Don't use a widening multiply if a shift will do. */
- && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (subexp1)))
- > HOST_BITS_PER_WIDE_INT)
- || exact_log2 (TREE_INT_CST_LOW (subexp1)) < 0))
- ||
- (top1
- && (TYPE_PRECISION (TREE_TYPE (top1))
- == TYPE_PRECISION (TREE_TYPE (top0))
- /* If both operands are extended, they must either both
- be zero-extended or both be sign-extended. */
- && (TYPE_UNSIGNED (TREE_TYPE (top1))
- == TYPE_UNSIGNED (TREE_TYPE (top0)))))))
+ /* Check for a multiplication with matching signedness. */
+ else if ((TREE_CODE (treeop1) == INTEGER_CST
+ && int_fits_type_p (treeop1, TREE_TYPE (treeop0)))
+ || (TYPE_UNSIGNED (TREE_TYPE (treeop1))
+ == TYPE_UNSIGNED (TREE_TYPE (treeop0))))
{
- tree op0type = TREE_TYPE (top0);
+ tree op0type = TREE_TYPE (treeop0);
enum machine_mode innermode = TYPE_MODE (op0type);
bool zextend_p = TYPE_UNSIGNED (op0type);
optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
@@ -7783,24 +7715,22 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
{
if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
{
- if (TREE_CODE (subexp1) == INTEGER_CST)
- expand_operands (top0, subexp1, NULL_RTX, &op0, &op1,
- EXPAND_NORMAL);
- else
- expand_operands (top0, top1, NULL_RTX, &op0, &op1,
- EXPAND_NORMAL);
- goto binop3;
+ expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
+ EXPAND_NORMAL);
+ temp = expand_widening_mult (mode, op0, op1, target,
+ unsignedp, this_optab);
+ return REDUCE_BIT_FIELD (temp);
}
- else if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
- && innermode == word_mode)
+ if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
+ && innermode == word_mode)
{
rtx htem, hipart;
- op0 = expand_normal (top0);
- if (TREE_CODE (subexp1) == INTEGER_CST)
+ op0 = expand_normal (treeop0);
+ if (TREE_CODE (treeop1) == INTEGER_CST)
op1 = convert_modes (innermode, mode,
- expand_normal (subexp1), unsignedp);
+ expand_normal (treeop1), unsignedp);
else
- op1 = expand_normal (top1);
+ op1 = expand_normal (treeop1);
temp = expand_binop (mode, other_optab, op0, op1, target,
unsignedp, OPTAB_LIB_WIDEN);
hipart = gen_highpart (innermode, temp);
@@ -7813,7 +7743,53 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
}
}
}
- expand_operands (subexp0, subexp1, subtarget, &op0, &op1, EXPAND_NORMAL);
+ treeop0 = fold_build1 (CONVERT_EXPR, type, treeop0);
+ treeop1 = fold_build1 (CONVERT_EXPR, type, treeop1);
+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
+ return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
+
+ case MULT_EXPR:
+ /* If this is a fixed-point operation, then we cannot use the code
+ below because "expand_mult" doesn't support sat/no-sat fixed-point
+ multiplications. */
+ if (ALL_FIXED_POINT_MODE_P (mode))
+ goto binop;
+
+ /* If first operand is constant, swap them.
+ Thus the following special case checks need only
+ check the second operand. */
+ if (TREE_CODE (treeop0) == INTEGER_CST)
+ {
+ tree t1 = treeop0;
+ treeop0 = treeop1;
+ treeop1 = t1;
+ }
+
+ /* Attempt to return something suitable for generating an
+ indexed address, for machines that support that. */
+
+ if (modifier == EXPAND_SUM && mode == ptr_mode
+ && host_integerp (treeop1, 0))
+ {
+ tree exp1 = treeop1;
+
+ op0 = expand_expr (treeop0, subtarget, VOIDmode,
+ EXPAND_SUM);
+
+ if (!REG_P (op0))
+ op0 = force_operand (op0, NULL_RTX);
+ if (!REG_P (op0))
+ op0 = copy_to_mode_reg (mode, op0);
+
+ return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
+ gen_int_mode (tree_low_cst (exp1, 0),
+ TYPE_MODE (TREE_TYPE (exp1)))));
+ }
+
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
+
+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
case TRUNC_DIV_EXPR: