static int is_aligning_offset (tree, tree);
static rtx expand_increment (tree, int, int);
+static void expand_operands (tree, tree, rtx, rtx*, rtx*,
+ enum expand_modifier);
static rtx do_store_flag (tree, rtx, enum machine_mode, int);
#ifdef PUSH_ROUNDING
static void emit_single_push_insn (enum machine_mode, rtx, tree);
return 0;
}
+
+/* Subroutine of expand_expr. Expand the two operands of a binary
+ expression EXP0 and EXP1 placing the results in OP0 and OP1.
+ The value may be stored in TARGET if TARGET is nonzero. The
+ MODIFIER argument is as documented by expand_expr. */
+
+static void
+expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1,
+ enum expand_modifier modifier)
+{
+ if (! safe_from_p (target, exp1, 1))
+ target = 0;
+ if (operand_equal_p (exp0, exp1, 0))
+ {
+ *op0 = expand_expr (exp0, target, VOIDmode, modifier);
+ *op1 = copy_rtx (*op0);
+ }
+ else
+ {
+ *op0 = expand_expr (exp0, target, VOIDmode, modifier);
+ *op1 = expand_expr (exp1, NULL_RTX, VOIDmode, modifier);
+ }
+}
+
\f
/* expand_expr: generate code for computing expression EXP.
An rtx for the computed value is returned. The value is never null.
emit_block_move will be flagged with BLOCK_OP_CALL_PARM. */
rtx
-expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier modifier)
+expand_expr (tree exp, rtx target, enum machine_mode tmode,
+ enum expand_modifier modifier)
{
rtx op0, op1, temp;
tree type = TREE_TYPE (exp);
if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
|| mode != ptr_mode)
{
- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
- if (! operand_equal_p (TREE_OPERAND (exp, 0),
- TREE_OPERAND (exp, 1), 0))
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
- else
- op1 = op0;
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ subtarget, &op0, &op1, 0);
if (op0 == const0_rtx)
return op1;
if (op1 == const0_rtx)
goto binop2;
}
- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
- if (! operand_equal_p (TREE_OPERAND (exp, 0),
- TREE_OPERAND (exp, 1), 0))
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
- VOIDmode, modifier);
- else
- op1 = op0;
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ subtarget, &op0, &op1, modifier);
return simplify_gen_binary (PLUS, mode, op0, op1);
case MINUS_EXPR:
&& really_constant_p (TREE_OPERAND (exp, 0))
&& really_constant_p (TREE_OPERAND (exp, 1)))
{
- rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode,
- modifier);
- rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode,
- modifier);
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ NULL_RTX, &op0, &op1, modifier);
/* If the last operand is a CONST_INT, use plus_constant of
the negated constant. Else make the MINUS. */
|| mode != ptr_mode)
goto binop;
- if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
- subtarget = 0;
-
- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ subtarget, &op0, &op1, modifier);
/* Convert A - const to A + (-const). */
if (GET_CODE (op1) == CONST_INT)
{
if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
- op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
- NULL_RTX, VOIDmode, 0);
if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
- VOIDmode, 0);
+ expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
+ TREE_OPERAND (exp, 1),
+ NULL_RTX, &op0, &op1, 0);
else
- op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
- NULL_RTX, VOIDmode, 0);
+ expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
+ TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
+ NULL_RTX, &op0, &op1, 0);
goto binop2;
}
else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
}
}
}
- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
- if (! operand_equal_p (TREE_OPERAND (exp, 0),
- TREE_OPERAND (exp, 1), 0))
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
- else
- op1 = op0;
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ subtarget, &op0, &op1, 0);
return expand_mult (mode, op0, op1, target, unsignedp);
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
- if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
- subtarget = 0;
if (modifier == EXPAND_STACK_PARM)
target = 0;
/* Possible optimization: compute the dividend with EXPAND_SUM
then if the divisor is constant can optimize the case
where some terms of the dividend have coeffs divisible by it. */
- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ subtarget, &op0, &op1, 0);
return expand_divmod (0, code, mode, op0, op1, target, unsignedp);
case RDIV_EXPR:
case FLOOR_MOD_EXPR:
case CEIL_MOD_EXPR:
case ROUND_MOD_EXPR:
- if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
- subtarget = 0;
if (modifier == EXPAND_STACK_PARM)
target = 0;
- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ subtarget, &op0, &op1, 0);
return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
case FIX_ROUND_EXPR:
|| (GET_CODE (target) == REG
&& REGNO (target) < FIRST_PSEUDO_REGISTER))
target = gen_reg_rtx (mode);
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
- op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ target, &op0, &op1, 0);
/* First try to do it with a special MIN or MAX instruction.
If that does not win, use a conditional jump to select the proper
/* Here to do an ordinary binary operator, generating an instruction
from the optab already placed in `this_optab'. */
binop:
- if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
- subtarget = 0;
- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
+ expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
+ subtarget, &op0, &op1, 0);
binop2:
if (modifier == EXPAND_STACK_PARM)
target = 0;
|| ! safe_from_p (subtarget, arg1, 1))
subtarget = 0;
- op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ expand_operands (arg0, arg1, subtarget, &op0, &op1, 0);
if (target == 0)
target = gen_reg_rtx (mode);