aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2002-05-04 13:23:21 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2002-05-04 11:23:21 +0000
commit8a28dbccfd0a67fbde3b8364d4da3688508c5ca3 (patch)
tree8e6feb5e7b280b49663becdac5be4fee44ee12b1 /gcc/expr.c
parentae1a07e00c1f0bab2b14dc4987e9f428e6b7b990 (diff)
downloadgcc-8a28dbccfd0a67fbde3b8364d4da3688508c5ca3.zip
gcc-8a28dbccfd0a67fbde3b8364d4da3688508c5ca3.tar.gz
gcc-8a28dbccfd0a67fbde3b8364d4da3688508c5ca3.tar.bz2
expr.c (force_operand): Use expand_simple_* to handle more cases.
* expr.c (force_operand): Use expand_simple_* to handle more cases. From-SVN: r53154
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c111
1 files changed, 68 insertions, 43 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 46cf042..dc4c335 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5432,16 +5432,13 @@ rtx
force_operand (value, target)
rtx value, target;
{
- optab binoptab = 0;
- /* Use a temporary to force order of execution of calls to
- `force_operand'. */
- rtx tmp;
- rtx op2;
+ rtx op1, op2;
/* Use subtarget as the target for operand 0 of a binary operation. */
rtx subtarget = get_subtarget (target);
+ enum rtx_code code = GET_CODE (value);
/* Check for a PIC address load. */
- if ((GET_CODE (value) == PLUS || GET_CODE (value) == MINUS)
+ if ((code == PLUS || code == MINUS)
&& XEXP (value, 0) == pic_offset_table_rtx
&& (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
|| GET_CODE (XEXP (value, 1)) == LABEL_REF
@@ -5453,60 +5450,88 @@ force_operand (value, target)
return subtarget;
}
- if (GET_CODE (value) == PLUS)
- binoptab = add_optab;
- else if (GET_CODE (value) == MINUS)
- binoptab = sub_optab;
- else if (GET_CODE (value) == MULT)
+ if (code == ZERO_EXTEND || code == SIGN_EXTEND)
{
- op2 = XEXP (value, 1);
- if (!CONSTANT_P (op2)
- && !(GET_CODE (op2) == REG && op2 != subtarget))
- subtarget = 0;
- tmp = force_operand (XEXP (value, 0), subtarget);
- return expand_mult (GET_MODE (value), tmp,
- force_operand (op2, NULL_RTX),
- target, 1);
+ if (!target)
+ target = gen_reg_rtx (GET_MODE (value));
+ convert_move (force_operand (XEXP (value, 0), NULL), target,
+ code == ZERO_EXTEND);
+ return target;
}
- if (binoptab)
+ if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
{
op2 = XEXP (value, 1);
- if (!CONSTANT_P (op2)
- && !(GET_CODE (op2) == REG && op2 != subtarget))
+ if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget))
subtarget = 0;
- if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT)
+ if (code == MINUS && GET_CODE (op2) == CONST_INT)
{
- binoptab = add_optab;
+ code = PLUS;
op2 = negate_rtx (GET_MODE (value), op2);
}
/* Check for an addition with OP2 a constant integer and our first
- operand a PLUS of a virtual register and something else. In that
- case, we want to emit the sum of the virtual register and the
- constant first and then add the other value. This allows virtual
- register instantiation to simply modify the constant rather than
- creating another one around this addition. */
- if (binoptab == add_optab && GET_CODE (op2) == CONST_INT
+ operand a PLUS of a virtual register and something else. In that
+ case, we want to emit the sum of the virtual register and the
+ constant first and then add the other value. This allows virtual
+ register instantiation to simply modify the constant rather than
+ creating another one around this addition. */
+ if (code == PLUS && GET_CODE (op2) == CONST_INT
&& GET_CODE (XEXP (value, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
&& REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
&& REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
{
- rtx temp = expand_binop (GET_MODE (value), binoptab,
- XEXP (XEXP (value, 0), 0), op2,
- subtarget, 0, OPTAB_LIB_WIDEN);
- return expand_binop (GET_MODE (value), binoptab, temp,
- force_operand (XEXP (XEXP (value, 0), 1), 0),
- target, 0, OPTAB_LIB_WIDEN);
+ rtx temp = expand_simple_binop (GET_MODE (value), code,
+ XEXP (XEXP (value, 0), 0), op2,
+ subtarget, 0, OPTAB_LIB_WIDEN);
+ return expand_simple_binop (GET_MODE (value), code, temp,
+ force_operand (XEXP (XEXP (value,
+ 0), 1), 0),
+ target, 0, OPTAB_LIB_WIDEN);
+ }
+
+ op1 = force_operand (XEXP (value, 0), subtarget);
+ op2 = force_operand (op2, NULL_RTX);
+ switch (code)
+ {
+ case MULT:
+ return expand_mult (GET_MODE (value), op1, op2, target, 1);
+ case DIV:
+ if (!INTEGRAL_MODE_P (GET_MODE (value)))
+ return expand_simple_binop (GET_MODE (value), code, op1, op2,
+ target, 1, OPTAB_LIB_WIDEN);
+ else
+ return expand_divmod (0,
+ FLOAT_MODE_P (GET_MODE (value))
+ ? RDIV_EXPR : TRUNC_DIV_EXPR,
+ GET_MODE (value), op1, op2, target, 0);
+ break;
+ case MOD:
+ return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
+ target, 0);
+ break;
+ case UDIV:
+ return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
+ target, 1);
+ break;
+ case UMOD:
+ return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
+ target, 1);
+ break;
+ case ASHIFTRT:
+ return expand_simple_binop (GET_MODE (value), code, op1, op2,
+ target, 0, OPTAB_LIB_WIDEN);
+ break;
+ default:
+ return expand_simple_binop (GET_MODE (value), code, op1, op2,
+ target, 1, OPTAB_LIB_WIDEN);
}
-
- tmp = force_operand (XEXP (value, 0), subtarget);
- return expand_binop (GET_MODE (value), binoptab, tmp,
- force_operand (op2, NULL_RTX),
- target, 0, OPTAB_LIB_WIDEN);
- /* We give UNSIGNEDP = 0 to expand_binop
- because the only operations we are expanding here are signed ones. */
+ }
+ if (GET_RTX_CLASS (code) == '1')
+ {
+ op1 = force_operand (XEXP (value, 0), NULL_RTX);
+ return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
}
#ifdef INSN_SCHEDULING