diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 45 |
1 files changed, 43 insertions, 2 deletions
@@ -7254,7 +7254,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, int ignore; bool reduce_bit_field; location_t loc = ops->location; - tree treeop0, treeop1; + tree treeop0, treeop1, treeop2; #define REDUCE_BIT_FIELD(expr) (reduce_bit_field \ ? reduce_to_bit_field_precision ((expr), \ target, \ @@ -7267,6 +7267,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, treeop0 = ops->op0; treeop1 = ops->op1; + treeop2 = ops->op2; /* We should be called only on simple (binary or unary) expressions, exactly those that are valid in gimple expressions that aren't @@ -7624,7 +7625,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, case WIDEN_MULT_PLUS_EXPR: case WIDEN_MULT_MINUS_EXPR: expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); - op2 = expand_normal (ops->op2); + op2 = expand_normal (treeop2); target = expand_widen_pattern_expr (ops, op0, op1, op2, target, unsignedp); return target; @@ -7711,6 +7712,46 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL); return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp)); + case FMA_EXPR: + { + optab opt = fma_optab; + gimple def0, def2; + + def0 = get_def_for_expr (treeop0, NEGATE_EXPR); + def2 = get_def_for_expr (treeop2, NEGATE_EXPR); + + op0 = op2 = NULL; + + if (def0 && def2 + && optab_handler (fnms_optab, mode) != CODE_FOR_nothing) + { + opt = fnms_optab; + op0 = expand_normal (gimple_assign_rhs1 (def0)); + op2 = expand_normal (gimple_assign_rhs1 (def2)); + } + else if (def0 + && optab_handler (fnma_optab, mode) != CODE_FOR_nothing) + { + opt = fnma_optab; + op0 = expand_normal (gimple_assign_rhs1 (def0)); + } + else if (def2 + && optab_handler (fms_optab, mode) != CODE_FOR_nothing) + { + opt = fms_optab; + op2 = expand_normal (gimple_assign_rhs1 (def2)); + } + + if (op0 == NULL) + op0 = expand_expr (treeop0, subtarget, VOIDmode, EXPAND_NORMAL); + if (op2 == NULL) + op2 = expand_normal (treeop2); + op1 = expand_normal (treeop1); + + return expand_ternary_op (TYPE_MODE (type), opt, + op0, op1, op2, target, 0); + } + 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 |