static optab new_optab PARAMS ((void));
static inline optab init_optab PARAMS ((enum rtx_code));
static inline optab init_optabv PARAMS ((enum rtx_code));
-static inline int complex_part_zero_p PARAMS ((rtx, enum mode_class,
- enum machine_mode));
static void init_libfuncs PARAMS ((optab, int, int, const char *, int));
static void init_integral_libfuncs PARAMS ((optab, const char *, int));
static void init_floating_libfuncs PARAMS ((optab, const char *, int));
enum rtx_code, int, rtx));
static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *,
enum machine_mode *, int *));
+static rtx expand_vector_binop PARAMS ((enum machine_mode, optab,
+ rtx, rtx, rtx, int,
+ enum optab_methods));
+static rtx expand_vector_unop PARAMS ((enum machine_mode, optab, rtx, rtx,
+ int));
\f
-/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
+/* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
the result of operation CODE applied to OP0 (and OP1 if it is a binary
operation).
again, ensuring that TARGET is not one of the operands. */
static int
-add_equal_note (seq, target, code, op0, op1)
- rtx seq;
+add_equal_note (insns, target, code, op0, op1)
+ rtx insns;
rtx target;
enum rtx_code code;
rtx op0, op1;
{
- rtx set;
- int i;
+ rtx last_insn, insn, set;
rtx note;
- if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
- && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
- || GET_CODE (seq) != SEQUENCE
- || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
- || GET_CODE (target) == ZERO_EXTRACT
- || (! rtx_equal_p (SET_DEST (set), target)
- /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
- SUBREG. */
- && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
- || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
- target))))
+ if (! insns
+ || ! INSN_P (insns)
+ || NEXT_INSN (insns) == NULL_RTX)
+ abort ();
+
+ if (GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
+ && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
+ return 1;
+
+ if (GET_CODE (target) == ZERO_EXTRACT)
+ return 1;
+
+ for (last_insn = insns;
+ NEXT_INSN (last_insn) != NULL_RTX;
+ last_insn = NEXT_INSN (last_insn))
+ ;
+
+ set = single_set (last_insn);
+ if (set == NULL_RTX)
+ return 1;
+
+ if (! rtx_equal_p (SET_DEST (set), target)
+ /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
+ SUBREG. */
+ && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
+ || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
+ target)))
return 1;
/* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
besides the last insn. */
if (reg_overlap_mentioned_p (target, op0)
|| (op1 && reg_overlap_mentioned_p (target, op1)))
- for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
- if (reg_set_p (target, XVECEXP (seq, 0, i)))
- return 0;
+ {
+ insn = PREV_INSN (last_insn);
+ while (insn != NULL_RTX)
+ {
+ if (reg_set_p (target, insn))
+ return 0;
+
+ insn = PREV_INSN (insn);
+ }
+ }
if (GET_RTX_CLASS (code) == '1')
note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
else
note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
- set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note);
+ set_unique_reg_note (last_insn, REG_EQUAL, note);
return 1;
}
return result;
}
\f
-/* Test whether either the real or imaginary part of a complex floating
- point number is 0.0, so that it can be ignored (when compiling
- with -funsafe-math-optimizations). */
-
-static inline int
-complex_part_zero_p (part, class, submode)
- rtx part;
- enum mode_class class;
- enum machine_mode submode;
-{
- return part == 0 ||
- (flag_unsafe_math_optimizations
- && class == MODE_COMPLEX_FLOAT
- && part == CONST0_RTX (submode));
-}
-
/* Generate code to perform a straightforward complex divide. */
static int
if (divisor == 0)
return 0;
- if (complex_part_zero_p (imag0, class, submode))
+ if (imag0 == 0)
{
/* Mathematically, ((a)(c-id))/divisor. */
/* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
/* Calculate dividend. */
- if (complex_part_zero_p (imag0, class, submode))
+ if (imag0 == 0)
{
real_t = real0;
/* Calculate dividend. */
- if (complex_part_zero_p (imag0, class, submode))
+ if (imag0 == 0)
{
/* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
}
/* In case the insn wants input operands in modes different from
- the result, convert the operands. It would seem that we
- don't need to convert CONST_INTs, but we do, so that they're
- a properly sign-extended for their modes; we choose the
- widest mode between mode and mode[01], so that, in a widening
- operation, we call convert_modes with different FROM and TO
- modes, which ensures the value is sign-extended. Shift
- operations are an exception, because the second operand needs
- not be extended to the mode of the result. */
-
- if (GET_MODE (op0) != mode0
- && mode0 != VOIDmode)
+ those of the actual operands, convert the operands. It would
+ seem that we don't need to convert CONST_INTs, but we do, so
+ that they're properly zero-extended or sign-extended for their
+ modes; shift operations are an exception, because the second
+ operand need not be extended to the mode of the result. */
+
+ if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
xop0 = convert_modes (mode0,
GET_MODE (op0) != VOIDmode
? GET_MODE (op0)
- : GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode0)
- ? mode
- : mode0,
+ : mode,
xop0, unsignedp);
- if (GET_MODE (xop1) != mode1
- && mode1 != VOIDmode)
+ if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
xop1 = convert_modes (mode1,
GET_MODE (op1) != VOIDmode
? GET_MODE (op1)
- : (GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode1)
- && ! shift_op)
- ? mode
- : mode1,
+ : (shift_op ? mode1 : mode),
xop1, unsignedp);
/* Now, if insn's predicates don't allow our operands, put them into
pat = GEN_FCN (icode) (temp, xop0, xop1);
if (pat)
{
- /* If PAT is a multi-insn sequence, try to add an appropriate
+ /* If PAT is composed of more than one insn, try to add an appropriate
REG_EQUAL note to it. If we can't because TEMP conflicts with an
operand, call ourselves again, this time without a target. */
- if (GET_CODE (pat) == SEQUENCE
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
&& ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
{
delete_insns_since (last);
if (shift_count != BITS_PER_WORD)
emit_no_conflict_block (insns, target, op0, op1, equiv_value);
else
- emit_insns (insns);
+ emit_insn (insns);
return target;
&& GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
&& binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
{
- int i;
+ unsigned int i;
optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
- unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+ const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
- rtx xop0, xop1;
+ rtx xop0, xop1, xtarget;
/* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
value is one of those, use it. Otherwise, use 1 since it is the
xop0 = force_reg (mode, op0);
xop1 = force_reg (mode, op1);
- if (target == 0 || GET_CODE (target) != REG
- || target == xop0 || target == xop1)
- target = gen_reg_rtx (mode);
+ xtarget = gen_reg_rtx (mode);
+
+ if (target == 0 || GET_CODE (target) != REG)
+ target = xtarget;
/* Indicate for flow that the entire target reg is being set. */
if (GET_CODE (target) == REG)
- emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, xtarget));
/* Do the actual arithmetic. */
for (i = 0; i < nwords; i++)
{
int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
- rtx target_piece = operand_subword (target, index, 1, mode);
+ rtx target_piece = operand_subword (xtarget, index, 1, mode);
rtx op0_piece = operand_subword_force (xop0, index, mode);
rtx op1_piece = operand_subword_force (xop1, index, mode);
rtx x;
carry_in = carry_out;
}
- if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
+ if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
{
if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
- rtx temp = emit_move_insn (target, target);
+ rtx temp = emit_move_insn (target, xtarget);
set_unique_reg_note (temp,
REG_EQUAL,
rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
NULL_RTX, 0, OPTAB_DIRECT);
+ if (!REG_P (product_high))
+ product_high = force_reg (word_mode, product_high);
+
if (temp != 0)
temp = expand_binop (word_mode, add_optab, temp, product_high,
product_high, 0, next_methods);
if (temp != 0 && temp != product_high)
emit_move_insn (product_high, temp);
+ emit_move_insn (operand_subword (product, high, 1, mode), product_high);
+
if (temp != 0)
{
if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
delete_insns_since (last);
}
+ /* Open-code the vector operations if we have no hardware support
+ for them. */
+ if (class == MODE_VECTOR_INT || class == MODE_VECTOR_FLOAT)
+ return expand_vector_binop (mode, binoptab, op0, op1, target,
+ unsignedp, methods);
+
/* We need to open-code the complex type operations: '+, -, * and /' */
/* At this point we allow operations between two similar complex
else if (res != realr)
emit_move_insn (realr, res);
- if (!complex_part_zero_p (imag0, class, submode)
- && !complex_part_zero_p (imag1, class, submode))
+ if (imag0 != 0 && imag1 != 0)
res = expand_binop (submode, binoptab, imag0, imag1,
imagr, unsignedp, methods);
- else if (!complex_part_zero_p (imag0, class, submode))
+ else if (imag0 != 0)
res = imag0;
else if (binoptab->code == MINUS)
res = expand_unop (submode,
case MULT:
/* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
- if (!complex_part_zero_p (imag0, class, submode)
- && !complex_part_zero_p (imag1, class, submode))
+ if (imag0 != 0 && imag1 != 0)
{
rtx temp1, temp2;
else if (res != realr)
emit_move_insn (realr, res);
- if (!complex_part_zero_p (imag0, class, submode))
+ if (imag0 != 0)
res = expand_binop (submode, binoptab,
real1, imag0, imagr, unsignedp, methods);
else
case DIV:
/* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
- if (complex_part_zero_p (imag1, class, submode))
+ if (imag1 == 0)
{
/* (a+ib) / (c+i0) = (a/c) + i(b/c) */
delete_insns_since (entry_last);
return 0;
}
+
+/* Like expand_binop, but for open-coding vectors binops. */
+
+static rtx
+expand_vector_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
+ enum machine_mode mode;
+ optab binoptab;
+ rtx op0, op1;
+ rtx target;
+ int unsignedp;
+ enum optab_methods methods;
+{
+ enum machine_mode submode, tmode;
+ int size, elts, subsize, subbitsize, i;
+ rtx t, a, b, res, seq;
+ enum mode_class class;
+
+ class = GET_MODE_CLASS (mode);
+
+ size = GET_MODE_SIZE (mode);
+ submode = GET_MODE_INNER (mode);
+
+ /* Search for the widest vector mode with the same inner mode that is
+ still narrower than MODE and that allows to open-code this operator.
+ Note, if we find such a mode and the handler later decides it can't
+ do the expansion, we'll be called recursively with the narrower mode. */
+ for (tmode = GET_CLASS_NARROWEST_MODE (class);
+ GET_MODE_SIZE (tmode) < GET_MODE_SIZE (mode);
+ tmode = GET_MODE_WIDER_MODE (tmode))
+ {
+ if (GET_MODE_INNER (tmode) == GET_MODE_INNER (mode)
+ && binoptab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
+ submode = tmode;
+ }
+
+ switch (binoptab->code)
+ {
+ case AND:
+ case IOR:
+ case XOR:
+ tmode = int_mode_for_mode (mode);
+ if (tmode != BLKmode)
+ submode = tmode;
+ case PLUS:
+ case MINUS:
+ case MULT:
+ case DIV:
+ subsize = GET_MODE_SIZE (submode);
+ subbitsize = GET_MODE_BITSIZE (submode);
+ elts = size / subsize;
+
+ /* If METHODS is OPTAB_DIRECT, we don't insist on the exact mode,
+ but that we operate on more than one element at a time. */
+ if (subsize == GET_MODE_UNIT_SIZE (mode) && methods == OPTAB_DIRECT)
+ return 0;
+
+ start_sequence ();
+
+ /* Errors can leave us with a const0_rtx as operand. */
+ if (GET_MODE (op0) != mode)
+ op0 = copy_to_mode_reg (mode, op0);
+ if (GET_MODE (op1) != mode)
+ op1 = copy_to_mode_reg (mode, op1);
+
+ if (!target)
+ target = gen_reg_rtx (mode);
+
+ for (i = 0; i < elts; ++i)
+ {
+ /* If this is part of a register, and not the first item in the
+ word, we can't store using a SUBREG - that would clobber
+ previous results.
+ And storing with a SUBREG is only possible for the least
+ significant part, hence we can't do it for big endian
+ (unless we want to permute the evaluation order. */
+ if (GET_CODE (target) == REG
+ && (BYTES_BIG_ENDIAN
+ ? subsize < UNITS_PER_WORD
+ : ((i * subsize) % UNITS_PER_WORD) != 0))
+ t = NULL_RTX;
+ else
+ t = simplify_gen_subreg (submode, target, mode, i * subsize);
+ if (CONSTANT_P (op0))
+ a = simplify_gen_subreg (submode, op0, mode, i * subsize);
+ else
+ a = extract_bit_field (op0, subbitsize, i * subbitsize, unsignedp,
+ NULL_RTX, submode, submode, size);
+ if (CONSTANT_P (op1))
+ b = simplify_gen_subreg (submode, op1, mode, i * subsize);
+ else
+ b = extract_bit_field (op1, subbitsize, i * subbitsize, unsignedp,
+ NULL_RTX, submode, submode, size);
+
+ if (binoptab->code == DIV)
+ {
+ if (class == MODE_VECTOR_FLOAT)
+ res = expand_binop (submode, binoptab, a, b, t,
+ unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ a, b, t, unsignedp);
+ }
+ else
+ res = expand_binop (submode, binoptab, a, b, t,
+ unsignedp, methods);
+
+ if (res == 0)
+ break;
+
+ if (t)
+ emit_move_insn (t, res);
+ else
+ store_bit_field (target, subbitsize, i * subbitsize, submode, res,
+ size);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ seq = get_insns ();
+ end_sequence ();
+ emit_insn (seq);
+
+ return target;
+}
+
+/* Like expand_unop but for open-coding vector unops. */
+
+static rtx
+expand_vector_unop (mode, unoptab, op0, target, unsignedp)
+ enum machine_mode mode;
+ optab unoptab;
+ rtx op0;
+ rtx target;
+ int unsignedp;
+{
+ enum machine_mode submode, tmode;
+ int size, elts, subsize, subbitsize, i;
+ rtx t, a, res, seq;
+
+ size = GET_MODE_SIZE (mode);
+ submode = GET_MODE_INNER (mode);
+
+ /* Search for the widest vector mode with the same inner mode that is
+ still narrower than MODE and that allows to open-code this operator.
+ Note, if we find such a mode and the handler later decides it can't
+ do the expansion, we'll be called recursively with the narrower mode. */
+ for (tmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (mode));
+ GET_MODE_SIZE (tmode) < GET_MODE_SIZE (mode);
+ tmode = GET_MODE_WIDER_MODE (tmode))
+ {
+ if (GET_MODE_INNER (tmode) == GET_MODE_INNER (mode)
+ && unoptab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
+ submode = tmode;
+ }
+ /* If there is no negate operation, try doing a subtract from zero. */
+ if (unoptab == neg_optab && GET_MODE_CLASS (submode) == MODE_INT
+ /* Avoid infinite recursion when an
+ error has left us with the wrong mode. */
+ && GET_MODE (op0) == mode)
+ {
+ rtx temp;
+ temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
+ target, unsignedp, OPTAB_DIRECT);
+ if (temp)
+ return temp;
+ }
+
+ if (unoptab == one_cmpl_optab)
+ {
+ tmode = int_mode_for_mode (mode);
+ if (tmode != BLKmode)
+ submode = tmode;
+ }
+
+ subsize = GET_MODE_SIZE (submode);
+ subbitsize = GET_MODE_BITSIZE (submode);
+ elts = size / subsize;
+
+ /* Errors can leave us with a const0_rtx as operand. */
+ if (GET_MODE (op0) != mode)
+ op0 = copy_to_mode_reg (mode, op0);
+
+ if (!target)
+ target = gen_reg_rtx (mode);
+
+ start_sequence ();
+
+ for (i = 0; i < elts; ++i)
+ {
+ /* If this is part of a register, and not the first item in the
+ word, we can't store using a SUBREG - that would clobber
+ previous results.
+ And storing with a SUBREG is only possible for the least
+ significant part, hence we can't do it for big endian
+ (unless we want to permute the evaluation order. */
+ if (GET_CODE (target) == REG
+ && (BYTES_BIG_ENDIAN
+ ? subsize < UNITS_PER_WORD
+ : ((i * subsize) % UNITS_PER_WORD) != 0))
+ t = NULL_RTX;
+ else
+ t = simplify_gen_subreg (submode, target, mode, i * subsize);
+ if (CONSTANT_P (op0))
+ a = simplify_gen_subreg (submode, op0, mode, i * subsize);
+ else
+ a = extract_bit_field (op0, subbitsize, i * subbitsize, unsignedp,
+ t, submode, submode, size);
+
+ res = expand_unop (submode, unoptab, a, t, unsignedp);
+
+ if (t)
+ emit_move_insn (t, res);
+ else
+ store_bit_field (target, subbitsize, i * subbitsize, submode, res,
+ size);
+ }
+
+ seq = get_insns ();
+ end_sequence ();
+ emit_insn (seq);
+
+ return target;
+}
\f
/* Expand a binary operator which has both signed and unsigned forms.
UOPTAB is the optab for unsigned operations, and SOPTAB is for
rtx pat;
rtx xop0 = op0, xop1 = op1;
- /* In case this insn wants input operands in modes different from the
- result, convert the operands. */
- if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
- xop0 = convert_to_mode (mode0, xop0, unsignedp);
+ /* In case the insn wants input operands in modes different from
+ those of the actual operands, convert the operands. It would
+ seem that we don't need to convert CONST_INTs, but we do, so
+ that they're properly zero-extended or sign-extended for their
+ modes. */
+
+ if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
+ xop0 = convert_modes (mode0,
+ GET_MODE (op0) != VOIDmode
+ ? GET_MODE (op0)
+ : mode,
+ xop0, unsignedp);
- if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
- xop1 = convert_to_mode (mode1, xop1, unsignedp);
+ if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
+ xop1 = convert_modes (mode1,
+ GET_MODE (op1) != VOIDmode
+ ? GET_MODE (op1)
+ : mode,
+ xop1, unsignedp);
/* Now, if insn doesn't accept these operands, put them into pseudos. */
if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
pat = GEN_FCN (icode) (temp, xop0);
if (pat)
{
- if (GET_CODE (pat) == SEQUENCE
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
&& ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
{
delete_insns_since (last);
return target;
}
+ if (class == MODE_VECTOR_FLOAT || class == MODE_VECTOR_INT)
+ return expand_vector_unop (mode, unoptab, op0, target, unsignedp);
+
/* It can't be done in this mode. Can we do it in a wider mode? */
if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
pat = GEN_FCN (icode) (temp, xop0);
if (pat)
{
- if (GET_CODE (pat) == SEQUENCE
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
&& ! add_equal_note (pat, temp, this_abs_optab->code, xop0,
NULL_RTX))
{
pat = GEN_FCN (icode) (temp, op0);
- if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
add_equal_note (pat, temp, code, op0, NULL_RTX);
emit_insn (pat);
rtx prev, next, first, last, insn;
if (GET_CODE (target) != REG || reload_in_progress)
- return emit_insns (insns);
+ return emit_insn (insns);
else
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) != INSN
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX))
- return emit_insns (insns);
+ return emit_insn (insns);
/* First emit all insns that do not store into words of the output and remove
these from the list. */
}
/* Generate the body of an instruction to copy Y into X.
- It may be a SEQUENCE, if one insn isn't enough. */
+ It may be a list of insns, if one insn isn't enough. */
rtx
gen_move_insn (x, y)
start_sequence ();
emit_move_insn_1 (x, y);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
return seq;
}
new_optab ()
{
int i;
- optab op = (optab) xmalloc (sizeof (struct optab));
+ optab op = (optab) ggc_alloc (sizeof (struct optab));
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
op->handlers[i].insn_code = CODE_FOR_nothing;
return XEXP (DECL_RTL (decl), 0);
}
-/* Mark ARG (which is really an OPTAB *) for GC. */
-
-void
-mark_optab (arg)
- void *arg;
-{
- optab o = *(optab *) arg;
- int i;
-
- for (i = 0; i < NUM_MACHINE_MODES; ++i)
- ggc_mark_rtx (o->handlers[i].libfunc);
-}
-
/* Call this once to initialize the contents of the optabs
appropriately for the current target machine. */
sqrt_optab = init_optab (SQRT);
sin_optab = init_optab (UNKNOWN);
cos_optab = init_optab (UNKNOWN);
+ exp_optab = init_optab (UNKNOWN);
+ log_optab = init_optab (UNKNOWN);
strlen_optab = init_optab (UNKNOWN);
cbranch_optab = init_optab (UNKNOWN);
cmov_optab = init_optab (UNKNOWN);
/* Allow the target to add more libcalls or rename some, etc. */
INIT_TARGET_OPTABS;
#endif
-
- /* Add these GC roots. */
- ggc_add_root (optab_table, OTI_MAX, sizeof(optab), mark_optab);
- ggc_add_rtx_root (libfunc_table, LTI_MAX);
}
\f
+static GTY(()) rtx trap_rtx;
+
#ifdef HAVE_conditional_trap
/* The insn generating function can not take an rtx_code argument.
TRAP_RTX is used as an rtx argument. Its code is replaced with
the code to be used in the trap insn and all other fields are
ignored. */
-static rtx trap_rtx;
static void
init_traps ()
if (HAVE_conditional_trap)
{
trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
- ggc_add_rtx_root (&trap_rtx, 1);
}
}
#endif
if (insn)
{
emit_insn (insn);
- insn = gen_sequence ();
+ insn = get_insns ();
}
end_sequence();
return insn;
return 0;
}
+
+#include "gt-optabs.h"