diff options
author | Bernd Schmidt <bernds@codesourcery.com> | 2010-04-22 09:30:27 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2010-04-22 09:30:27 +0000 |
commit | 5b58b39b0a7d1c79b0d57e51199864f9a3685bb4 (patch) | |
tree | 9248604cc9a0efe5af0b9ed453fe7110c80743c8 /gcc/expr.c | |
parent | 92375a2020b1f32bf7be92025493cebd9b3b4400 (diff) | |
download | gcc-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.c | 170 |
1 files changed, 73 insertions, 97 deletions
@@ -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: |