summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/optabs.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-02-01 18:16:02 +0000
committerobrien <obrien@FreeBSD.org>2002-02-01 18:16:02 +0000
commitc9ab9ae440a8066b2c2b85b157b1fdadcf09916a (patch)
tree086d9d6c8fbd4fc8fe4495059332f66bc0f8d12b /contrib/gcc/optabs.c
parent2ecfd8bd04b63f335c1ec6295740a4bfd97a4fa6 (diff)
downloadFreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.zip
FreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.tar.gz
Enlist the FreeBSD-CURRENT users as testers of what is to become Gcc 3.1.0.
These bits are taken from the FSF anoncvs repo on 1-Feb-2002 08:20 PST.
Diffstat (limited to 'contrib/gcc/optabs.c')
-rw-r--r--contrib/gcc/optabs.c1851
1 files changed, 1058 insertions, 793 deletions
diff --git a/contrib/gcc/optabs.c b/contrib/gcc/optabs.c
index b360262..2a2ebb3 100644
--- a/contrib/gcc/optabs.c
+++ b/contrib/gcc/optabs.c
@@ -1,23 +1,23 @@
/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
- Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
#include "config.h"
@@ -25,16 +25,21 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
/* Include insn-config.h before expr.h so that HAVE_conditional_move
- is properly defined. */
+ is properly defined. */
#include "insn-config.h"
#include "rtl.h"
#include "tree.h"
+#include "tm_p.h"
#include "flags.h"
-#include "insn-flags.h"
-#include "insn-codes.h"
+#include "function.h"
+#include "except.h"
#include "expr.h"
+#include "optabs.h"
+#include "libfuncs.h"
#include "recog.h"
#include "reload.h"
+#include "ggc.h"
+#include "real.h"
/* Each optab contains info on how this target machine
can perform a particular operation
@@ -45,50 +50,9 @@ Boston, MA 02111-1307, USA. */
See expr.h for documentation of these optabs. */
-optab add_optab;
-optab sub_optab;
-optab smul_optab;
-optab smul_highpart_optab;
-optab umul_highpart_optab;
-optab smul_widen_optab;
-optab umul_widen_optab;
-optab sdiv_optab;
-optab sdivmod_optab;
-optab udiv_optab;
-optab udivmod_optab;
-optab smod_optab;
-optab umod_optab;
-optab flodiv_optab;
-optab ftrunc_optab;
-optab and_optab;
-optab ior_optab;
-optab xor_optab;
-optab ashl_optab;
-optab lshr_optab;
-optab ashr_optab;
-optab rotl_optab;
-optab rotr_optab;
-optab smin_optab;
-optab smax_optab;
-optab umin_optab;
-optab umax_optab;
-
-optab mov_optab;
-optab movstrict_optab;
-
-optab neg_optab;
-optab abs_optab;
-optab one_cmpl_optab;
-optab ffs_optab;
-optab sqrt_optab;
-optab sin_optab;
-optab cos_optab;
-
-optab cmp_optab;
-optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
-optab tst_optab;
-
-optab strlen_optab;
+optab optab_table[OTI_MAX];
+
+rtx libfunc_table[LTI_MAX];
/* Tables of patterns for extending one integer mode to another. */
enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
@@ -101,129 +65,6 @@ enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
/* Contains the optab used for each rtx code. */
optab code_to_optab[NUM_RTX_CODE + 1];
-/* SYMBOL_REF rtx's for the library functions that are called
- implicitly and not via optabs. */
-
-rtx extendsfdf2_libfunc;
-rtx extendsfxf2_libfunc;
-rtx extendsftf2_libfunc;
-rtx extenddfxf2_libfunc;
-rtx extenddftf2_libfunc;
-
-rtx truncdfsf2_libfunc;
-rtx truncxfsf2_libfunc;
-rtx trunctfsf2_libfunc;
-rtx truncxfdf2_libfunc;
-rtx trunctfdf2_libfunc;
-
-rtx memcpy_libfunc;
-rtx bcopy_libfunc;
-rtx memcmp_libfunc;
-rtx bcmp_libfunc;
-rtx memset_libfunc;
-rtx bzero_libfunc;
-
-rtx throw_libfunc;
-rtx rethrow_libfunc;
-rtx sjthrow_libfunc;
-rtx sjpopnthrow_libfunc;
-rtx terminate_libfunc;
-rtx setjmp_libfunc;
-rtx longjmp_libfunc;
-rtx eh_rtime_match_libfunc;
-
-rtx eqhf2_libfunc;
-rtx nehf2_libfunc;
-rtx gthf2_libfunc;
-rtx gehf2_libfunc;
-rtx lthf2_libfunc;
-rtx lehf2_libfunc;
-
-rtx eqsf2_libfunc;
-rtx nesf2_libfunc;
-rtx gtsf2_libfunc;
-rtx gesf2_libfunc;
-rtx ltsf2_libfunc;
-rtx lesf2_libfunc;
-
-rtx eqdf2_libfunc;
-rtx nedf2_libfunc;
-rtx gtdf2_libfunc;
-rtx gedf2_libfunc;
-rtx ltdf2_libfunc;
-rtx ledf2_libfunc;
-
-rtx eqxf2_libfunc;
-rtx nexf2_libfunc;
-rtx gtxf2_libfunc;
-rtx gexf2_libfunc;
-rtx ltxf2_libfunc;
-rtx lexf2_libfunc;
-
-rtx eqtf2_libfunc;
-rtx netf2_libfunc;
-rtx gttf2_libfunc;
-rtx getf2_libfunc;
-rtx lttf2_libfunc;
-rtx letf2_libfunc;
-
-rtx floatsisf_libfunc;
-rtx floatdisf_libfunc;
-rtx floattisf_libfunc;
-
-rtx floatsidf_libfunc;
-rtx floatdidf_libfunc;
-rtx floattidf_libfunc;
-
-rtx floatsixf_libfunc;
-rtx floatdixf_libfunc;
-rtx floattixf_libfunc;
-
-rtx floatsitf_libfunc;
-rtx floatditf_libfunc;
-rtx floattitf_libfunc;
-
-rtx fixsfsi_libfunc;
-rtx fixsfdi_libfunc;
-rtx fixsfti_libfunc;
-
-rtx fixdfsi_libfunc;
-rtx fixdfdi_libfunc;
-rtx fixdfti_libfunc;
-
-rtx fixxfsi_libfunc;
-rtx fixxfdi_libfunc;
-rtx fixxfti_libfunc;
-
-rtx fixtfsi_libfunc;
-rtx fixtfdi_libfunc;
-rtx fixtfti_libfunc;
-
-rtx fixunssfsi_libfunc;
-rtx fixunssfdi_libfunc;
-rtx fixunssfti_libfunc;
-
-rtx fixunsdfsi_libfunc;
-rtx fixunsdfdi_libfunc;
-rtx fixunsdfti_libfunc;
-
-rtx fixunsxfsi_libfunc;
-rtx fixunsxfdi_libfunc;
-rtx fixunsxfti_libfunc;
-
-rtx fixunstfsi_libfunc;
-rtx fixunstfdi_libfunc;
-rtx fixunstfti_libfunc;
-
-rtx chkr_check_addr_libfunc;
-rtx chkr_set_right_libfunc;
-rtx chkr_copy_bitmap_libfunc;
-rtx chkr_check_exec_libfunc;
-rtx chkr_check_str_libfunc;
-
-rtx profile_function_entry_libfunc;
-rtx profile_function_exit_libfunc;
-
/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
gives the gen_function to make a branch to test that condition. */
@@ -244,29 +85,39 @@ enum insn_code setcc_gen_code[NUM_RTX_CODE];
enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
#endif
-static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
-static rtx widen_operand PROTO((rtx, enum machine_mode,
+static int add_equal_note PARAMS ((rtx, rtx, enum rtx_code, rtx, rtx));
+static rtx widen_operand PARAMS ((rtx, enum machine_mode,
enum machine_mode, int, int));
-static int expand_cmplxdiv_straight PROTO((rtx, rtx, rtx, rtx,
+static int expand_cmplxdiv_straight PARAMS ((rtx, rtx, rtx, rtx,
rtx, rtx, enum machine_mode,
int, enum optab_methods,
enum mode_class, optab));
-static int expand_cmplxdiv_wide PROTO((rtx, rtx, rtx, rtx,
+static int expand_cmplxdiv_wide PARAMS ((rtx, rtx, rtx, rtx,
rtx, rtx, enum machine_mode,
int, enum optab_methods,
enum mode_class, optab));
-static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode,
+static void prepare_cmp_insn PARAMS ((rtx *, rtx *, enum rtx_code *, rtx,
+ enum machine_mode *, int *,
+ enum can_compare_purpose));
+static enum insn_code can_fix_p PARAMS ((enum machine_mode, enum machine_mode,
int, int *));
-static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
- int));
-static rtx ftruncify PROTO((rtx));
-static optab init_optab PROTO((enum rtx_code));
-static void init_libfuncs PROTO((optab, int, int, const char *, int));
-static void init_integral_libfuncs PROTO((optab, const char *, int));
-static void init_floating_libfuncs PROTO((optab, const char *, int));
+static enum insn_code can_float_p PARAMS ((enum machine_mode,
+ enum machine_mode,
+ int));
+static rtx ftruncify PARAMS ((rtx));
+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 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));
#ifdef HAVE_conditional_trap
-static void init_traps PROTO((void));
+static void init_traps PARAMS ((void));
#endif
+static void emit_cmp_and_jump_insn_1 PARAMS ((rtx, rtx, enum machine_mode,
+ enum rtx_code, int, rtx));
+static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *,
+ enum machine_mode *, int *));
/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
the result of operation CODE applied to OP0 (and OP1 if it is a binary
@@ -373,7 +224,19 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
rtx real_t, imag_t;
rtx temp1, temp2;
rtx res;
+ optab this_add_optab = add_optab;
+ optab this_sub_optab = sub_optab;
+ optab this_neg_optab = neg_optab;
+ optab this_mul_optab = smul_optab;
+ if (binoptab == sdivv_optab)
+ {
+ this_add_optab = addv_optab;
+ this_sub_optab = subv_optab;
+ this_neg_optab = negv_optab;
+ this_mul_optab = smulv_optab;
+ }
+
/* Don't fetch these from memory more than once. */
real0 = force_reg (submode, real0);
real1 = force_reg (submode, real1);
@@ -384,16 +247,16 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
imag1 = force_reg (submode, imag1);
/* Divisor: c*c + d*d. */
- temp1 = expand_binop (submode, smul_optab, real1, real1,
+ temp1 = expand_binop (submode, this_mul_optab, real1, real1,
NULL_RTX, unsignedp, methods);
- temp2 = expand_binop (submode, smul_optab, imag1, imag1,
+ temp2 = expand_binop (submode, this_mul_optab, imag1, imag1,
NULL_RTX, unsignedp, methods);
if (temp1 == 0 || temp2 == 0)
return 0;
- divisor = expand_binop (submode, add_optab, temp1, temp2,
+ divisor = expand_binop (submode, this_add_optab, temp1, temp2,
NULL_RTX, unsignedp, methods);
if (divisor == 0)
return 0;
@@ -404,44 +267,44 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
/* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
/* Calculate the dividend. */
- real_t = expand_binop (submode, smul_optab, real0, real1,
+ real_t = expand_binop (submode, this_mul_optab, real0, real1,
NULL_RTX, unsignedp, methods);
- imag_t = expand_binop (submode, smul_optab, real0, imag1,
+ imag_t = expand_binop (submode, this_mul_optab, real0, imag1,
NULL_RTX, unsignedp, methods);
if (real_t == 0 || imag_t == 0)
return 0;
- imag_t = expand_unop (submode, neg_optab, imag_t,
+ imag_t = expand_unop (submode, this_neg_optab, imag_t,
NULL_RTX, unsignedp);
}
else
{
/* Mathematically, ((a+ib)(c-id))/divider. */
/* Calculate the dividend. */
- temp1 = expand_binop (submode, smul_optab, real0, real1,
+ temp1 = expand_binop (submode, this_mul_optab, real0, real1,
NULL_RTX, unsignedp, methods);
- temp2 = expand_binop (submode, smul_optab, imag0, imag1,
+ temp2 = expand_binop (submode, this_mul_optab, imag0, imag1,
NULL_RTX, unsignedp, methods);
if (temp1 == 0 || temp2 == 0)
return 0;
- real_t = expand_binop (submode, add_optab, temp1, temp2,
+ real_t = expand_binop (submode, this_add_optab, temp1, temp2,
NULL_RTX, unsignedp, methods);
- temp1 = expand_binop (submode, smul_optab, imag0, real1,
+ temp1 = expand_binop (submode, this_mul_optab, imag0, real1,
NULL_RTX, unsignedp, methods);
- temp2 = expand_binop (submode, smul_optab, real0, imag1,
+ temp2 = expand_binop (submode, this_mul_optab, real0, imag1,
NULL_RTX, unsignedp, methods);
if (temp1 == 0 || temp2 == 0)
return 0;
- imag_t = expand_binop (submode, sub_optab, temp1, temp2,
+ imag_t = expand_binop (submode, this_sub_optab, temp1, temp2,
NULL_RTX, unsignedp, methods);
if (real_t == 0 || imag_t == 0)
@@ -493,8 +356,19 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
rtx real_t, imag_t;
rtx temp1, temp2, lab1, lab2;
enum machine_mode mode;
- int align;
rtx res;
+ optab this_add_optab = add_optab;
+ optab this_sub_optab = sub_optab;
+ optab this_neg_optab = neg_optab;
+ optab this_mul_optab = smul_optab;
+
+ if (binoptab == sdivv_optab)
+ {
+ this_add_optab = addv_optab;
+ this_sub_optab = subv_optab;
+ this_neg_optab = negv_optab;
+ this_mul_optab = smulv_optab;
+ }
/* Don't fetch these from memory more than once. */
real0 = force_reg (submode, real0);
@@ -513,18 +387,17 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
}
else
{
- temp1 = expand_abs (submode, real1, NULL_RTX, 1);
- temp2 = expand_abs (submode, imag1, NULL_RTX, 1);
+ temp1 = expand_abs (submode, real1, NULL_RTX, unsignedp, 1);
+ temp2 = expand_abs (submode, imag1, NULL_RTX, unsignedp, 1);
}
if (temp1 == 0 || temp2 == 0)
return 0;
mode = GET_MODE (temp1);
- align = GET_MODE_ALIGNMENT (mode);
lab1 = gen_label_rtx ();
emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
- mode, unsignedp, align, lab1);
+ mode, unsignedp, lab1);
/* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
@@ -540,13 +413,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
/* Calculate divisor. */
- temp1 = expand_binop (submode, smul_optab, imag1, ratio,
+ temp1 = expand_binop (submode, this_mul_optab, imag1, ratio,
NULL_RTX, unsignedp, methods);
if (temp1 == 0)
return 0;
- divisor = expand_binop (submode, add_optab, temp1, real1,
+ divisor = expand_binop (submode, this_add_optab, temp1, real1,
NULL_RTX, unsignedp, methods);
if (divisor == 0)
@@ -560,13 +433,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
/* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
- imag_t = expand_binop (submode, smul_optab, real0, ratio,
+ imag_t = expand_binop (submode, this_mul_optab, real0, ratio,
NULL_RTX, unsignedp, methods);
if (imag_t == 0)
return 0;
- imag_t = expand_unop (submode, neg_optab, imag_t,
+ imag_t = expand_unop (submode, this_neg_optab, imag_t,
NULL_RTX, unsignedp);
if (real_t == 0 || imag_t == 0)
@@ -577,22 +450,22 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
/* Compute (a+ib)/(c+id) as
(a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
- temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+ temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
NULL_RTX, unsignedp, methods);
if (temp1 == 0)
return 0;
- real_t = expand_binop (submode, add_optab, temp1, real0,
+ real_t = expand_binop (submode, this_add_optab, temp1, real0,
NULL_RTX, unsignedp, methods);
- temp1 = expand_binop (submode, smul_optab, real0, ratio,
+ temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
NULL_RTX, unsignedp, methods);
if (temp1 == 0)
return 0;
- imag_t = expand_binop (submode, sub_optab, imag0, temp1,
+ imag_t = expand_binop (submode, this_sub_optab, imag0, temp1,
NULL_RTX, unsignedp, methods);
if (real_t == 0 || imag_t == 0)
@@ -645,13 +518,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
/* Calculate divisor. */
- temp1 = expand_binop (submode, smul_optab, real1, ratio,
+ temp1 = expand_binop (submode, this_mul_optab, real1, ratio,
NULL_RTX, unsignedp, methods);
if (temp1 == 0)
return 0;
- divisor = expand_binop (submode, add_optab, temp1, imag1,
+ divisor = expand_binop (submode, this_add_optab, temp1, imag1,
NULL_RTX, unsignedp, methods);
if (divisor == 0)
@@ -663,10 +536,10 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
{
/* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
- real_t = expand_binop (submode, smul_optab, real0, ratio,
+ real_t = expand_binop (submode, this_mul_optab, real0, ratio,
NULL_RTX, unsignedp, methods);
- imag_t = expand_unop (submode, neg_optab, real0,
+ imag_t = expand_unop (submode, this_neg_optab, real0,
NULL_RTX, unsignedp);
if (real_t == 0 || imag_t == 0)
@@ -677,22 +550,22 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
/* Compute (a+ib)/(c+id) as
(a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
- temp1 = expand_binop (submode, smul_optab, real0, ratio,
+ temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
NULL_RTX, unsignedp, methods);
if (temp1 == 0)
return 0;
- real_t = expand_binop (submode, add_optab, temp1, imag0,
+ real_t = expand_binop (submode, this_add_optab, temp1, imag0,
NULL_RTX, unsignedp, methods);
- temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+ temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
NULL_RTX, unsignedp, methods);
if (temp1 == 0)
return 0;
- imag_t = expand_binop (submode, sub_optab, temp1, real0,
+ imag_t = expand_binop (submode, this_sub_optab, temp1, real0,
NULL_RTX, unsignedp, methods);
if (real_t == 0 || imag_t == 0)
@@ -730,6 +603,25 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
return 1;
}
+/* Wrapper around expand_binop which takes an rtx code to specify
+ the operation to perform, not an optab pointer. All other
+ arguments are the same. */
+rtx
+expand_simple_binop (mode, code, op0, op1, target, unsignedp, methods)
+ enum machine_mode mode;
+ enum rtx_code code;
+ rtx op0, op1;
+ rtx target;
+ int unsignedp;
+ enum optab_methods methods;
+{
+ optab binop = code_to_optab [(int) code];
+ if (binop == 0)
+ abort ();
+
+ return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
+}
+
/* Generate code to perform an operation specified by BINOPTAB
on operands OP0 and OP1, with result having machine-mode MODE.
@@ -755,7 +647,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
? OPTAB_WIDEN : methods);
enum mode_class class;
enum machine_mode wider_mode;
- register rtx temp;
+ rtx temp;
int commutative_op = 0;
int shift_op = (binoptab->code == ASHIFT
|| binoptab->code == ASHIFTRT
@@ -790,11 +682,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
/* If we are inside an appropriately-short loop and one operand is an
expensive constant, force it into a register. */
if (CONSTANT_P (op0) && preserve_subexpressions_p ()
- && rtx_cost (op0, binoptab->code) > 2)
+ && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
op0 = force_reg (mode, op0);
if (CONSTANT_P (op1) && preserve_subexpressions_p ()
- && ! shift_op && rtx_cost (op1, binoptab->code) > 2)
+ && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
op1 = force_reg (mode, op1);
/* Record where to delete back to if we backtrack. */
@@ -831,8 +723,8 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
&& binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
int icode = (int) binoptab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
- enum machine_mode mode1 = insn_operand_mode[icode][2];
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
rtx pat;
rtx xop0 = op0, xop1 = op1;
@@ -848,7 +740,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
&& GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
{
- register rtx tmp;
+ rtx tmp;
tmp = op0; op0 = op1; op1 = tmp;
tmp = xop0; xop0 = xop1; xop1 = tmp;
@@ -856,30 +748,48 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
}
/* In case the insn wants input operands in modes different from
- the result, convert the operands. */
-
- if (GET_MODE (op0) != VOIDmode
- && GET_MODE (op0) != mode0
+ 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)
- xop0 = convert_to_mode (mode0, xop0, unsignedp);
-
- if (GET_MODE (xop1) != VOIDmode
- && GET_MODE (xop1) != mode1
+ xop0 = convert_modes (mode0,
+ GET_MODE (op0) != VOIDmode
+ ? GET_MODE (op0)
+ : GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode0)
+ ? mode
+ : mode0,
+ xop0, unsignedp);
+
+ if (GET_MODE (xop1) != mode1
&& mode1 != VOIDmode)
- xop1 = convert_to_mode (mode1, xop1, unsignedp);
+ xop1 = convert_modes (mode1,
+ GET_MODE (op1) != VOIDmode
+ ? GET_MODE (op1)
+ : (GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode1)
+ && ! shift_op)
+ ? mode
+ : mode1,
+ xop1, unsignedp);
/* Now, if insn's predicates don't allow our operands, put them into
pseudo regs. */
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)
+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0)
&& mode0 != VOIDmode)
xop0 = copy_to_mode_reg (mode0, xop0);
- if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)
+ if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1)
&& mode1 != VOIDmode)
xop1 = copy_to_mode_reg (mode1, xop1);
- if (! (*insn_operand_predicate[icode][0]) (temp, mode))
+ if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
temp = gen_reg_rtx (mode);
pat = GEN_FCN (icode) (temp, xop0, xop1);
@@ -945,7 +855,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
/* For certain integer operations, we need not actually extend
the narrow operands, as long as we will truncate
- the results to the same narrowness. */
+ the results to the same narrowness. */
if ((binoptab == ior_optab || binoptab == and_optab
|| binoptab == xor_optab
@@ -1277,9 +1187,8 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
&& binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
{
int i;
- rtx carry_tmp = gen_reg_rtx (word_mode);
optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
- int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+ unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
rtx xop0, xop1;
@@ -1326,31 +1235,29 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
carry_out = gen_reg_rtx (word_mode);
carry_out = emit_store_flag_force (carry_out,
(binoptab == add_optab
- ? LTU : GTU),
+ ? LT : GT),
x, op0_piece,
word_mode, 1, normalizep);
}
if (i > 0)
{
+ rtx newx;
+
/* Add/subtract previous carry to main result. */
- x = expand_binop (word_mode,
- normalizep == 1 ? binoptab : otheroptab,
- x, carry_in,
- target_piece, 1, next_methods);
- if (x == 0)
- break;
- else if (target_piece != x)
- emit_move_insn (target_piece, x);
+ newx = expand_binop (word_mode,
+ normalizep == 1 ? binoptab : otheroptab,
+ x, carry_in,
+ NULL_RTX, 1, next_methods);
if (i + 1 < nwords)
{
- /* THIS CODE HAS NOT BEEN TESTED. */
/* Get out carry from adding/subtracting carry in. */
+ rtx carry_tmp = gen_reg_rtx (word_mode);
carry_tmp = emit_store_flag_force (carry_tmp,
- binoptab == add_optab
- ? LTU : GTU,
- x, carry_in,
+ (binoptab == add_optab
+ ? LT : GT),
+ newx, x,
word_mode, 1, normalizep);
/* Logical-ior the two poss. carry together. */
@@ -1360,6 +1267,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (carry_out == 0)
break;
}
+ emit_move_insn (target_piece, newx);
}
carry_in = carry_out;
@@ -1377,8 +1285,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
copy_rtx (xop0),
copy_rtx (xop1)));
}
+
return target;
}
+
else
delete_insns_since (last);
}
@@ -1559,6 +1469,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
copy_rtx (op0),
copy_rtx (op1)));
}
+
return product;
}
}
@@ -1643,7 +1554,9 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
else if (imag0)
res = imag0;
else if (binoptab->code == MINUS)
- res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
+ res = expand_unop (submode,
+ binoptab == subv_optab ? negv_optab : neg_optab,
+ imag1, imagr, unsignedp);
else
res = imag1;
@@ -1677,8 +1590,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (temp1 == 0 || temp2 == 0)
break;
- res = expand_binop (submode, sub_optab, temp1, temp2,
- realr, unsignedp, methods);
+ res = (expand_binop
+ (submode,
+ binoptab == smulv_optab ? subv_optab : sub_optab,
+ temp1, temp2, realr, unsignedp, methods));
if (res == 0)
break;
@@ -1694,8 +1609,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (temp1 == 0 || temp2 == 0)
break;
- res = expand_binop (submode, add_optab, temp1, temp2,
- imagr, unsignedp, methods);
+ res = (expand_binop
+ (submode,
+ binoptab == smulv_optab ? addv_optab : add_optab,
+ temp1, temp2, imagr, unsignedp, methods));
if (res == 0)
break;
@@ -1844,7 +1761,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
/* Pass 1 for NO_QUEUE so we don't lose any increments
if the libcall is cse'd or moved. */
value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
- NULL_RTX, 1, mode, 2,
+ NULL_RTX, LCT_CONST, mode, 2,
op0, mode, op1x, op1_mode);
insns = get_insns ();
@@ -1947,7 +1864,7 @@ sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
int unsignedp;
enum optab_methods methods;
{
- register rtx temp;
+ rtx temp;
optab direct_optab = unsignedp ? uoptab : soptab;
struct optab wide_soptab;
@@ -2028,11 +1945,11 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
/* If we are inside an appropriately-short loop and one operand is an
expensive constant, force it into a register. */
if (CONSTANT_P (op0) && preserve_subexpressions_p ()
- && rtx_cost (op0, binoptab->code) > 2)
+ && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
op0 = force_reg (mode, op0);
if (CONSTANT_P (op1) && preserve_subexpressions_p ()
- && rtx_cost (op1, binoptab->code) > 2)
+ && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
op1 = force_reg (mode, op1);
if (targ0)
@@ -2050,8 +1967,8 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
int icode = (int) binoptab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
- enum machine_mode mode1 = insn_operand_mode[icode][2];
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
rtx pat;
rtx xop0 = op0, xop1 = op1;
@@ -2064,16 +1981,16 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
xop1 = convert_to_mode (mode1, xop1, unsignedp);
/* Now, if insn doesn't accept these operands, put them into pseudos. */
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
xop0 = copy_to_mode_reg (mode0, xop0);
- if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
+ if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1))
xop1 = copy_to_mode_reg (mode1, xop1);
/* We could handle this, but we should always be called with a pseudo
for our targets and all insns should take them as outputs. */
- if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
- || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
+ if (! (*insn_data[icode].operand[0].predicate) (targ0, mode)
+ || ! (*insn_data[icode].operand[3].predicate) (targ1, mode))
abort ();
pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
@@ -2096,14 +2013,12 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
if (binoptab->handlers[(int) wider_mode].insn_code
!= CODE_FOR_nothing)
{
- register rtx t0 = gen_reg_rtx (wider_mode);
- register rtx t1 = gen_reg_rtx (wider_mode);
-
- if (expand_twoval_binop (binoptab,
- convert_modes (wider_mode, mode, op0,
- unsignedp),
- convert_modes (wider_mode, mode, op1,
- unsignedp),
+ rtx t0 = gen_reg_rtx (wider_mode);
+ rtx t1 = gen_reg_rtx (wider_mode);
+ rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
+ rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
+
+ if (expand_twoval_binop (binoptab, cop0, cop1,
t0, t1, unsignedp))
{
convert_move (targ0, t0, unsignedp);
@@ -2120,6 +2035,24 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
return 0;
}
+/* Wrapper around expand_unop which takes an rtx code to specify
+ the operation to perform, not an optab pointer. All other
+ arguments are the same. */
+rtx
+expand_simple_unop (mode, code, op0, target, unsignedp)
+ enum machine_mode mode;
+ enum rtx_code code;
+ rtx op0;
+ rtx target;
+ int unsignedp;
+{
+ optab unop = code_to_optab [(int) code];
+ if (unop == 0)
+ abort ();
+
+ return expand_unop (mode, unop, op0, target, unsignedp);
+}
+
/* Generate code to perform an operation specified by UNOPTAB
on operand OP0, with result having machine-mode MODE.
@@ -2141,7 +2074,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
{
enum mode_class class;
enum machine_mode wider_mode;
- register rtx temp;
+ rtx temp;
rtx last = get_last_insn ();
rtx pat;
@@ -2160,7 +2093,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
int icode = (int) unoptab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
rtx xop0 = op0;
if (target)
@@ -2174,10 +2107,10 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
/* Now, if insn doesn't accept our operand, put it into a pseudo. */
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
xop0 = copy_to_mode_reg (mode0, xop0);
- if (! (*insn_operand_predicate[icode][0]) (temp, mode))
+ if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
temp = gen_reg_rtx (mode);
pat = GEN_FCN (icode) (temp, xop0);
@@ -2258,6 +2191,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
rtx x = expand_unop (word_mode, unoptab,
operand_subword_force (op0, i, mode),
target_piece, unsignedp);
+
if (target_piece != x)
emit_move_insn (target_piece, x);
}
@@ -2272,7 +2206,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
}
/* Open-code the complex negation operation. */
- else if (unoptab == neg_optab
+ else if (unoptab->code == NEG
&& (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
{
rtx target_piece;
@@ -2327,7 +2261,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
/* Pass 1 for NO_QUEUE so we don't lose any increments
if the libcall is cse'd or moved. */
value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
- NULL_RTX, 1, mode, 1, op0, mode);
+ NULL_RTX, LCT_CONST, mode, 1, op0, mode);
insns = get_insns ();
end_sequence ();
@@ -2383,11 +2317,13 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
/* If there is no negate operation, try doing a subtract from zero.
The US Software GOFAST library needs this. */
- if (unoptab == neg_optab)
+ if (unoptab->code == NEG)
{
rtx temp;
- temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
- target, unsignedp, OPTAB_LIB_WIDEN);
+ temp = expand_binop (mode,
+ unoptab == negv_optab ? subv_optab : sub_optab,
+ CONST0_RTX (mode), op0,
+ target, unsignedp, OPTAB_LIB_WIDEN);
if (temp)
return temp;
}
@@ -2405,19 +2341,40 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
*/
rtx
-expand_abs (mode, op0, target, safe)
+expand_abs (mode, op0, target, result_unsignedp, safe)
enum machine_mode mode;
rtx op0;
rtx target;
+ int result_unsignedp;
int safe;
{
rtx temp, op1;
+ if (! flag_trapv)
+ result_unsignedp = 1;
+
/* First try to do it with a special abs instruction. */
- temp = expand_unop (mode, abs_optab, op0, target, 0);
+ temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
+ op0, target, 0);
if (temp != 0)
return temp;
+ /* If we have a MAX insn, we can do this as MAX (x, -x). */
+ if (smax_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ {
+ rtx last = get_last_insn ();
+
+ temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
+ if (temp != 0)
+ temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
+ OPTAB_WIDEN);
+
+ if (temp != 0)
+ return temp;
+
+ delete_insns_since (last);
+ }
+
/* If this machine has expensive jumps, we can do integer absolute
value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
where W is the width of MODE. */
@@ -2431,8 +2388,8 @@ expand_abs (mode, op0, target, safe)
temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
OPTAB_LIB_WIDEN);
if (temp != 0)
- temp = expand_binop (mode, sub_optab, temp, extended, target, 0,
- OPTAB_LIB_WIDEN);
+ temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
+ temp, extended, target, 0, OPTAB_LIB_WIDEN);
if (temp != 0)
return temp;
@@ -2459,25 +2416,16 @@ expand_abs (mode, op0, target, safe)
/* If this mode is an integer too wide to compare properly,
compare word by word. Rely on CSE to optimize constant cases. */
- if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode))
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && ! can_compare_p (GE, mode, ccp_jump))
do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx,
NULL_RTX, op1);
else
- {
- temp = compare_from_rtx (target, CONST0_RTX (mode), GE, 0, mode,
- NULL_RTX, 0);
- if (temp == const1_rtx)
- return target;
- else if (temp != const0_rtx)
- {
- if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0)
- emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op1));
- else
- abort ();
- }
- }
+ do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
+ NULL_RTX, NULL_RTX, op1);
- op0 = expand_unop (mode, neg_optab, target, target, 0);
+ op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
+ target, target, 0);
if (op0 != target)
emit_move_insn (target, op0);
emit_label (op1);
@@ -2503,10 +2451,11 @@ expand_complex_abs (mode, op0, target, unsignedp)
{
enum mode_class class = GET_MODE_CLASS (mode);
enum machine_mode wider_mode;
- register rtx temp;
+ rtx temp;
rtx entry_last = get_last_insn ();
rtx last;
rtx pat;
+ optab this_abs_optab;
/* Find the correct mode for the real and imaginary parts. */
enum machine_mode submode
@@ -2529,10 +2478,14 @@ expand_complex_abs (mode, op0, target, unsignedp)
if (target)
target = protect_from_queue (target, 1);
- if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ this_abs_optab = ! unsignedp && flag_trapv
+ && (GET_MODE_CLASS(mode) == MODE_INT)
+ ? absv_optab : abs_optab;
+
+ if (this_abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
- int icode = (int) abs_optab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
+ int icode = (int) this_abs_optab->handlers[(int) mode].insn_code;
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
rtx xop0 = op0;
if (target)
@@ -2546,20 +2499,22 @@ expand_complex_abs (mode, op0, target, unsignedp)
/* Now, if insn doesn't accept our operand, put it into a pseudo. */
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
xop0 = copy_to_mode_reg (mode0, xop0);
- if (! (*insn_operand_predicate[icode][0]) (temp, submode))
+ if (! (*insn_data[icode].operand[0].predicate) (temp, submode))
temp = gen_reg_rtx (submode);
pat = GEN_FCN (icode) (temp, xop0);
if (pat)
{
if (GET_CODE (pat) == SEQUENCE
- && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
+ && ! add_equal_note (pat, temp, this_abs_optab->code, xop0,
+ NULL_RTX))
{
delete_insns_since (last);
- return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
+ return expand_unop (mode, this_abs_optab, op0, NULL_RTX,
+ unsignedp);
}
emit_insn (pat);
@@ -2575,7 +2530,8 @@ expand_complex_abs (mode, op0, target, unsignedp)
for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
- if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
+ if (this_abs_optab->handlers[(int) wider_mode].insn_code
+ != CODE_FOR_nothing)
{
rtx xop0 = op0;
@@ -2601,7 +2557,8 @@ expand_complex_abs (mode, op0, target, unsignedp)
/* Open-code the complex absolute-value operation
if we can open-code sqrt. Otherwise it's not worth while. */
- if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
+ if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing
+ && ! flag_trapv)
{
rtx real, imag, total;
@@ -2625,7 +2582,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
}
/* Now try a library call in this mode. */
- if (abs_optab->handlers[(int) mode].libfunc)
+ if (this_abs_optab->handlers[(int) mode].libfunc)
{
rtx insns;
rtx value;
@@ -2635,13 +2592,13 @@ expand_complex_abs (mode, op0, target, unsignedp)
/* Pass 1 for NO_QUEUE so we don't lose any increments
if the libcall is cse'd or moved. */
value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
- NULL_RTX, 1, submode, 1, op0, mode);
+ NULL_RTX, LCT_CONST, submode, 1, op0, mode);
insns = get_insns ();
end_sequence ();
target = gen_reg_rtx (submode);
emit_libcall_block (insns, target, value,
- gen_rtx_fmt_e (abs_optab->code, mode, op0));
+ gen_rtx_fmt_e (this_abs_optab->code, mode, op0));
return target;
}
@@ -2651,9 +2608,9 @@ expand_complex_abs (mode, op0, target, unsignedp)
for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
- if ((abs_optab->handlers[(int) wider_mode].insn_code
+ if ((this_abs_optab->handlers[(int) wider_mode].insn_code
!= CODE_FOR_nothing)
- || abs_optab->handlers[(int) wider_mode].libfunc)
+ || this_abs_optab->handlers[(int) wider_mode].libfunc)
{
rtx xop0 = op0;
@@ -2695,8 +2652,8 @@ emit_unop_insn (icode, target, op0, code)
rtx op0;
enum rtx_code code;
{
- register rtx temp;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
+ rtx temp;
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
rtx pat;
temp = target = protect_from_queue (target, 1);
@@ -2711,10 +2668,10 @@ emit_unop_insn (icode, target, op0, code)
/* Now, if insn does not accept our operands, put them into pseudos. */
- if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
- if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
+ if (! (*insn_data[icode].operand[0].predicate) (temp, GET_MODE (temp))
|| (flag_force_mem && GET_CODE (temp) == MEM))
temp = gen_reg_rtx (GET_MODE (temp));
@@ -2783,7 +2740,8 @@ emit_no_conflict_block (insns, target, op0, op1, equiv)
next = NEXT_INSN (insn);
- if (GET_CODE (PATTERN (insn)) == SET)
+ if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE
+ || GET_CODE (PATTERN (insn)) == CLOBBER)
set = PATTERN (insn);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
@@ -2841,7 +2799,16 @@ emit_no_conflict_block (insns, target, op0, op1, equiv)
set_unique_reg_note (last, REG_EQUAL, equiv);
}
else
- last = get_last_insn ();
+ {
+ last = get_last_insn ();
+
+ /* Remove any existing REG_EQUAL note from "last", or else it will
+ be mistaken for a note referring to the full contents of the
+ alleged libcall value when found together with the REG_RETVAL
+ note added below. An existing note can come from an insn
+ expansion at "last". */
+ remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
+ }
if (prev == 0)
first = get_insns ();
@@ -2895,21 +2862,36 @@ emit_libcall_block (insns, target, result, equiv)
into a MEM later. Protect the libcall block from this change. */
if (! REG_P (target) || REG_USERVAR_P (target))
target = gen_reg_rtx (GET_MODE (target));
-
- /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
- reg note to indicate that this call cannot throw. (Unless there is
- already a REG_EH_REGION note.) */
-
- for (insn = insns; insn; insn = NEXT_INSN (insn))
+
+ /* If we're using non-call exceptions, a libcall corresponding to an
+ operation that may trap may also trap. */
+ if (flag_non_call_exceptions && may_trap_p (equiv))
{
- if (GET_CODE (insn) == CALL_INSN)
- {
- rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
- if (note == NULL_RTX)
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
- REG_NOTES (insn));
- }
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+
+ if (note != 0 && INTVAL (XEXP (note, 0)) <= 0)
+ remove_note (insn, note);
+ }
}
+ else
+ /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
+ reg note to indicate that this call cannot throw or execute a nonlocal
+ goto (unless there is already a REG_EH_REGION note, in which case
+ we update it). */
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+
+ if (note != 0)
+ XEXP (note, 0) = GEN_INT (-1);
+ else
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
+ REG_NOTES (insn));
+ }
/* First emit all insns that set pseudos. Remove them from the list as
we go. Avoid insns that set pseudos which were referenced in previous
@@ -2926,7 +2908,8 @@ emit_libcall_block (insns, target, result, equiv)
if (set != 0 && GET_CODE (SET_DEST (set)) == REG
&& REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
&& (insn == insns
- || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
+ || ((! INSN_P(insns)
+ || ! reg_mentioned_p (SET_DEST (set), PATTERN (insns)))
&& ! reg_used_between_p (SET_DEST (set), insns, insn)
&& ! modified_in_p (SET_SRC (set), insns)
&& ! modified_between_p (SET_SRC (set), insns, insn))))
@@ -2958,6 +2941,15 @@ emit_libcall_block (insns, target, result, equiv)
if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
!= CODE_FOR_nothing)
set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
+ else
+ {
+ /* Remove any existing REG_EQUAL note from "last", or else it will
+ be mistaken for a note referring to the full contents of the
+ libcall value when found together with the REG_RETVAL note added
+ below. An existing note can come from an insn expansion at
+ "last". */
+ remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
+ }
if (final_dest != target)
emit_move_insn (final_dest, target);
@@ -2968,9 +2960,13 @@ emit_libcall_block (insns, target, result, equiv)
first = NEXT_INSN (prev);
/* Encapsulate the block so it gets manipulated as a unit. */
- REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
- REG_NOTES (first));
- REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+ if (!flag_non_call_exceptions || !may_trap_p (equiv))
+ {
+ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
+ REG_NOTES (first));
+ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
+ REG_NOTES (last));
+ }
}
/* Generate code to store zero in X. */
@@ -2992,31 +2988,78 @@ emit_0_to_1_insn (x)
emit_move_insn (x, const1_rtx);
}
-/* Generate code to compare X with Y
- so that the condition codes are set.
+/* Nonzero if we can perform a comparison of mode MODE straightforwardly.
+ PURPOSE describes how this comparison will be used. CODE is the rtx
+ comparison code we will be using.
- MODE is the mode of the inputs (in case they are const_int).
- UNSIGNEDP nonzero says that X and Y are unsigned;
+ ??? Actually, CODE is slightly weaker than that. A target is still
+ required to implement all of the normal bcc operations, but not
+ required to implement all (or any) of the unordered bcc operations. */
+
+int
+can_compare_p (code, mode, purpose)
+ enum rtx_code code;
+ enum machine_mode mode;
+ enum can_compare_purpose purpose;
+{
+ do
+ {
+ if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ {
+ if (purpose == ccp_jump)
+ return bcc_gen_fctn[(int)code] != NULL;
+ else if (purpose == ccp_store_flag)
+ return setcc_gen_code[(int)code] != CODE_FOR_nothing;
+ else
+ /* There's only one cmov entry point, and it's allowed to fail. */
+ return 1;
+ }
+ if (purpose == ccp_jump
+ && cbranch_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ return 1;
+ if (purpose == ccp_cmov
+ && cmov_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ return 1;
+ if (purpose == ccp_store_flag
+ && cstore_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ return 1;
+
+ mode = GET_MODE_WIDER_MODE (mode);
+ }
+ while (mode != VOIDmode);
+
+ return 0;
+}
+
+/* This function is called when we are going to emit a compare instruction that
+ compares the values found in *PX and *PY, using the rtl operator COMPARISON.
+
+ *PMODE is the mode of the inputs (in case they are const_int).
+ *PUNSIGNEDP nonzero says that the operands are unsigned;
this matters if they need to be widened.
- If they have mode BLKmode, then SIZE specifies the size of both X and Y,
- and ALIGN specifies the known shared alignment of X and Y.
+ If they have mode BLKmode, then SIZE specifies the size of both operands.
- COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
- It is ignored for fixed-point and block comparisons;
- it is used only for floating-point comparisons. */
+ This function performs all the setup necessary so that the caller only has
+ to emit a single comparison insn. This setup can involve doing a BLKmode
+ comparison or emitting a library call to perform the comparison if no insn
+ is available to handle it.
+ The values which are passed in through pointers can be modified; the caller
+ should perform the comparison on the modified values. */
-void
-emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
- rtx x, y;
- enum rtx_code comparison;
+static void
+prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, purpose)
+ rtx *px, *py;
+ enum rtx_code *pcomparison;
rtx size;
- enum machine_mode mode;
- int unsignedp;
- int align;
+ enum machine_mode *pmode;
+ int *punsignedp;
+ enum can_compare_purpose purpose;
{
+ enum machine_mode mode = *pmode;
+ rtx x = *px, y = *py;
+ int unsignedp = *punsignedp;
enum mode_class class;
- enum machine_mode wider_mode;
class = GET_MODE_CLASS (mode);
@@ -3033,10 +3076,12 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
/* If we are inside an appropriately-short loop and one operand is an
expensive constant, force it into a register. */
- if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
+ if (CONSTANT_P (x) && preserve_subexpressions_p ()
+ && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
x = force_reg (mode, x);
- if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
+ if (CONSTANT_P (y) && preserve_subexpressions_p ()
+ && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
y = force_reg (mode, y);
#ifdef HAVE_cc0
@@ -3055,6 +3100,11 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
if (mode == BLKmode)
{
+ rtx result;
+ enum machine_mode result_mode;
+ rtx opalign ATTRIBUTE_UNUSED
+ = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
+
emit_queue ();
x = protect_from_queue (x, 0);
y = protect_from_queue (y, 0);
@@ -3066,12 +3116,9 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
{
- enum machine_mode result_mode
- = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
- rtx result = gen_reg_rtx (result_mode);
- emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
- emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
- result_mode, 0, 0);
+ result_mode = insn_data[(int) CODE_FOR_cmpstrqi].operand[0].mode;
+ result = gen_reg_rtx (result_mode);
+ emit_insn (gen_cmpstrqi (result, x, y, size, opalign));
}
else
#endif
@@ -3080,42 +3127,34 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
{
- enum machine_mode result_mode
- = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
- rtx result = gen_reg_rtx (result_mode);
- emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
- emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
- result_mode, 0, 0);
+ result_mode = insn_data[(int) CODE_FOR_cmpstrhi].operand[0].mode;
+ result = gen_reg_rtx (result_mode);
+ emit_insn (gen_cmpstrhi (result, x, y, size, opalign));
}
else
#endif
#ifdef HAVE_cmpstrsi
if (HAVE_cmpstrsi)
{
- enum machine_mode result_mode
- = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
- rtx result = gen_reg_rtx (result_mode);
+ result_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
+ result = gen_reg_rtx (result_mode);
size = protect_from_queue (size, 0);
emit_insn (gen_cmpstrsi (result, x, y,
convert_to_mode (SImode, size, 1),
- GEN_INT (align)));
- emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
- result_mode, 0, 0);
+ opalign));
}
else
#endif
{
- rtx result;
-
#ifdef TARGET_MEM_FUNCTIONS
- emit_library_call (memcmp_libfunc, 0,
+ emit_library_call (memcmp_libfunc, LCT_PURE_MAKE_BLOCK,
TYPE_MODE (integer_type_node), 3,
XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
convert_to_mode (TYPE_MODE (sizetype), size,
TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
#else
- emit_library_call (bcmp_libfunc, 0,
+ emit_library_call (bcmp_libfunc, LCT_PURE_MAKE_BLOCK,
TYPE_MODE (integer_type_node), 3,
XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
convert_to_mode (TYPE_MODE (integer_type_node),
@@ -3128,83 +3167,24 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
register so reload doesn't clobber the value if it needs
the return register for a spill reg. */
result = gen_reg_rtx (TYPE_MODE (integer_type_node));
+ result_mode = TYPE_MODE (integer_type_node);
emit_move_insn (result,
- hard_libcall_value (TYPE_MODE (integer_type_node)));
- emit_cmp_insn (result,
- const0_rtx, comparison, NULL_RTX,
- TYPE_MODE (integer_type_node), 0, 0);
+ hard_libcall_value (result_mode));
}
+ *px = result;
+ *py = const0_rtx;
+ *pmode = result_mode;
return;
}
- /* Handle some compares against zero. */
-
- if (y == CONST0_RTX (mode)
- && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- int icode = (int) tst_optab->handlers[(int) mode].insn_code;
-
- emit_queue ();
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
-
- /* Now, if insn does accept these operands, put them into pseudos. */
- if (! (*insn_operand_predicate[icode][0])
- (x, insn_operand_mode[icode][0]))
- x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
-
- emit_insn (GEN_FCN (icode) (x));
- return;
- }
-
- /* Handle compares for which there is a directly suitable insn. */
-
- if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
-
- emit_queue ();
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
-
- /* Now, if insn doesn't accept these operands, put them into pseudos. */
- if (! (*insn_operand_predicate[icode][0])
- (x, insn_operand_mode[icode][0]))
- x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
-
- if (! (*insn_operand_predicate[icode][1])
- (y, insn_operand_mode[icode][1]))
- y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
-
- emit_insn (GEN_FCN (icode) (x, y));
- return;
- }
-
- /* Try widening if we can find a direct insn that way. */
-
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
- {
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
- wider_mode = GET_MODE_WIDER_MODE (wider_mode))
- {
- if (cmp_optab->handlers[(int) wider_mode].insn_code
- != CODE_FOR_nothing)
- {
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
- x = convert_modes (wider_mode, mode, x, unsignedp);
- y = convert_modes (wider_mode, mode, y, unsignedp);
- emit_cmp_insn (x, y, comparison, NULL_RTX,
- wider_mode, unsignedp, align);
- return;
- }
- }
- }
+ *px = x;
+ *py = y;
+ if (can_compare_p (*pcomparison, mode, purpose))
+ return;
/* Handle a lib call just for the mode we are using. */
- if (cmp_optab->handlers[(int) mode].libfunc
- && class != MODE_FLOAT)
+ if (cmp_optab->handlers[(int) mode].libfunc && class != MODE_FLOAT)
{
rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
rtx result;
@@ -3214,8 +3194,8 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
libfunc = ucmp_optab->handlers[(int) mode].libfunc;
- emit_library_call (libfunc, 1,
- word_mode, 2, x, mode, y, mode);
+ emit_library_call (libfunc, LCT_CONST_MAKE_BLOCK, word_mode, 2, x, mode,
+ y, mode);
/* Immediately move the result of the libcall into a pseudo
register so reload doesn't clobber the value if it needs
@@ -3226,18 +3206,114 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
/* Integer comparison returns a result that must be compared against 1,
so that even if we do an unsigned compare afterward,
there is still a value that can represent the result "less than". */
- emit_cmp_insn (result, const1_rtx,
- comparison, NULL_RTX, word_mode, unsignedp, 0);
+ *px = result;
+ *py = const1_rtx;
+ *pmode = word_mode;
return;
}
if (class == MODE_FLOAT)
- emit_float_lib_cmp (x, y, comparison);
+ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
else
abort ();
}
+/* Before emitting an insn with code ICODE, make sure that X, which is going
+ to be used for operand OPNUM of the insn, is converted from mode MODE to
+ WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
+ that it is accepted by the operand predicate. Return the new value. */
+
+rtx
+prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp)
+ int icode;
+ rtx x;
+ int opnum;
+ enum machine_mode mode, wider_mode;
+ int unsignedp;
+{
+ x = protect_from_queue (x, 0);
+
+ if (mode != wider_mode)
+ x = convert_modes (wider_mode, mode, x, unsignedp);
+
+ if (! (*insn_data[icode].operand[opnum].predicate)
+ (x, insn_data[icode].operand[opnum].mode))
+ x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
+ return x;
+}
+
+/* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
+ we can do the comparison.
+ The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
+ be NULL_RTX which indicates that only a comparison is to be generated. */
+
+static void
+emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
+ rtx x, y;
+ enum machine_mode mode;
+ enum rtx_code comparison;
+ int unsignedp;
+ rtx label;
+{
+ rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
+ enum mode_class class = GET_MODE_CLASS (mode);
+ enum machine_mode wider_mode = mode;
+
+ /* Try combined insns first. */
+ do
+ {
+ enum insn_code icode;
+ PUT_MODE (test, wider_mode);
+
+ if (label)
+ {
+ icode = cbranch_optab->handlers[(int)wider_mode].insn_code;
+
+ if (icode != CODE_FOR_nothing
+ && (*insn_data[icode].operand[0].predicate) (test, wider_mode))
+ {
+ x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
+ y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
+ emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
+ return;
+ }
+ }
+
+ /* Handle some compares against zero. */
+ icode = (int) tst_optab->handlers[(int) wider_mode].insn_code;
+ if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
+ {
+ x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
+ emit_insn (GEN_FCN (icode) (x));
+ if (label)
+ emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
+ return;
+ }
+
+ /* Handle compares for which there is a directly suitable insn. */
+
+ icode = (int) cmp_optab->handlers[(int) wider_mode].insn_code;
+ if (icode != CODE_FOR_nothing)
+ {
+ x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
+ y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp);
+ emit_insn (GEN_FCN (icode) (x, y));
+ if (label)
+ emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
+ return;
+ }
+
+ if (class != MODE_INT && class != MODE_FLOAT
+ && class != MODE_COMPLEX_FLOAT)
+ break;
+
+ wider_mode = GET_MODE_WIDER_MODE (wider_mode);
+ } while (wider_mode != VOIDmode);
+
+ abort ();
+}
+
/* Generate code to compare X with Y so that the condition codes are
set and to jump to LABEL if the condition is true. If X is a
constant and Y is not a constant, then the comparison is swapped to
@@ -3247,8 +3323,7 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
the proper branch condition code.
- If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
- and ALIGN specifies the known shared alignment of X and Y.
+ If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
MODE is the mode of the inputs (in case they are const_int).
@@ -3257,30 +3332,27 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
void
-emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
+emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, label)
rtx x, y;
enum rtx_code comparison;
rtx size;
enum machine_mode mode;
int unsignedp;
- int align;
rtx label;
{
- rtx op0;
- rtx op1;
-
- if (CONSTANT_P (x))
+ rtx op0 = x, op1 = y;
+
+ /* Swap operands and condition to ensure canonical RTL. */
+ if (swap_commutative_operands_p (x, y))
{
- /* Swap operands and condition to ensure canonical RTL. */
- op0 = y;
- op1 = x;
+ /* If we're not emitting a branch, this means some caller
+ is out of sync. */
+ if (! label)
+ abort ();
+
+ op0 = y, op1 = x;
comparison = swap_condition (comparison);
}
- else
- {
- op0 = x;
- op1 = y;
- }
#ifdef HAVE_cc0
/* If OP0 is still a constant, then both X and Y must be constants. Force
@@ -3290,39 +3362,41 @@ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
op0 = force_reg (mode, op0);
#endif
- emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align);
-
+ emit_queue ();
if (unsignedp)
comparison = unsigned_condition (comparison);
- emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
-}
+ prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp,
+ ccp_jump);
+ emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
+}
-/* Nonzero if a compare of mode MODE can be done straightforwardly
- (without splitting it into pieces). */
+/* Like emit_cmp_and_jump_insns, but generate only the comparison. */
-int
-can_compare_p (mode)
+void
+emit_cmp_insn (x, y, comparison, size, mode, unsignedp)
+ rtx x, y;
+ enum rtx_code comparison;
+ rtx size;
enum machine_mode mode;
+ int unsignedp;
{
- do
- {
- if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
- return 1;
- mode = GET_MODE_WIDER_MODE (mode);
- } while (mode != VOIDmode);
-
- return 0;
+ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, 0);
}
/* Emit a library call comparison between floating point X and Y.
COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
-void
-emit_float_lib_cmp (x, y, comparison)
- rtx x, y;
- enum rtx_code comparison;
+static void
+prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
+ rtx *px, *py;
+ enum rtx_code *pcomparison;
+ enum machine_mode *pmode;
+ int *punsignedp;
{
+ enum rtx_code comparison = *pcomparison;
+ rtx x = *px = protect_from_queue (*px, 0);
+ rtx y = *py = protect_from_queue (*py, 0);
enum machine_mode mode = GET_MODE (x);
rtx libfunc = 0;
rtx result;
@@ -3354,6 +3428,10 @@ emit_float_lib_cmp (x, y, comparison)
libfunc = lehf2_libfunc;
break;
+ case UNORDERED:
+ libfunc = unordhf2_libfunc;
+ break;
+
default:
break;
}
@@ -3384,6 +3462,10 @@ emit_float_lib_cmp (x, y, comparison)
libfunc = lesf2_libfunc;
break;
+ case UNORDERED:
+ libfunc = unordsf2_libfunc;
+ break;
+
default:
break;
}
@@ -3414,6 +3496,10 @@ emit_float_lib_cmp (x, y, comparison)
libfunc = ledf2_libfunc;
break;
+ case UNORDERED:
+ libfunc = unorddf2_libfunc;
+ break;
+
default:
break;
}
@@ -3444,6 +3530,10 @@ emit_float_lib_cmp (x, y, comparison)
libfunc = lexf2_libfunc;
break;
+ case UNORDERED:
+ libfunc = unordxf2_libfunc;
+ break;
+
default:
break;
}
@@ -3474,6 +3564,10 @@ emit_float_lib_cmp (x, y, comparison)
libfunc = letf2_libfunc;
break;
+ case UNORDERED:
+ libfunc = unordtf2_libfunc;
+ break;
+
default:
break;
}
@@ -3490,9 +3584,9 @@ emit_float_lib_cmp (x, y, comparison)
{
x = protect_from_queue (x, 0);
y = protect_from_queue (y, 0);
- x = convert_to_mode (wider_mode, x, 0);
- y = convert_to_mode (wider_mode, y, 0);
- emit_float_lib_cmp (x, y, comparison);
+ *px = convert_to_mode (wider_mode, x, 0);
+ *py = convert_to_mode (wider_mode, y, 0);
+ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
return;
}
}
@@ -3502,17 +3596,24 @@ emit_float_lib_cmp (x, y, comparison)
if (libfunc == 0)
abort ();
- emit_library_call (libfunc, 1,
- word_mode, 2, x, mode, y, mode);
+ emit_library_call (libfunc, LCT_CONST_MAKE_BLOCK, word_mode, 2, x, mode, y,
+ mode);
/* Immediately move the result of the libcall into a pseudo
register so reload doesn't clobber the value if it needs
the return register for a spill reg. */
result = gen_reg_rtx (word_mode);
emit_move_insn (result, hard_libcall_value (word_mode));
-
- emit_cmp_insn (result, const0_rtx, comparison,
- NULL_RTX, word_mode, 0, 0);
+ *px = result;
+ *py = const0_rtx;
+ *pmode = word_mode;
+ if (comparison == UNORDERED)
+ *pcomparison = NE;
+#ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
+ else if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
+ *pcomparison = NE;
+#endif
+ *punsignedp = 0;
}
/* Generate code to indirectly jump to a location given in the rtx LOC. */
@@ -3521,7 +3622,7 @@ void
emit_indirect_jump (loc)
rtx loc;
{
- if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
+ if (! ((*insn_data[(int)CODE_FOR_indirect_jump].operand[0].predicate)
(loc, Pmode)))
loc = copy_to_mode_reg (Pmode, loc);
@@ -3558,12 +3659,12 @@ emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
{
rtx tem, subtarget, comparison, insn;
enum insn_code icode;
+ enum rtx_code reversed;
/* If one operand is constant, make it the second one. Only do this
if the other operand is not constant as well. */
- if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
- || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
+ if (swap_commutative_operands_p (op0, op1))
{
tem = op0;
op0 = op1;
@@ -3571,18 +3672,25 @@ emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
code = swap_condition (code);
}
+ /* get_condition will prefer to generate LT and GT even if the old
+ comparison was against zero, so undo that canonicalization here since
+ comparisons against zero are cheaper. */
+ if (code == LT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 1)
+ code = LE, op1 = const0_rtx;
+ else if (code == GT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == -1)
+ code = GE, op1 = const0_rtx;
+
if (cmode == VOIDmode)
cmode = GET_MODE (op0);
- if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
- || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
- && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
- || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math))
+ if (swap_commutative_operands_p (op2, op3)
+ && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
+ != UNKNOWN))
{
tem = op2;
op2 = op3;
op3 = tem;
- code = reverse_condition (code);
+ code = reversed;
}
if (mode == VOIDmode)
@@ -3613,28 +3721,30 @@ emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
/* If the insn doesn't accept these operands, put them in pseudos. */
- if (! (*insn_operand_predicate[icode][0])
- (subtarget, insn_operand_mode[icode][0]))
- subtarget = gen_reg_rtx (insn_operand_mode[icode][0]);
+ if (! (*insn_data[icode].operand[0].predicate)
+ (subtarget, insn_data[icode].operand[0].mode))
+ subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
- if (! (*insn_operand_predicate[icode][2])
- (op2, insn_operand_mode[icode][2]))
- op2 = copy_to_mode_reg (insn_operand_mode[icode][2], op2);
+ if (! (*insn_data[icode].operand[2].predicate)
+ (op2, insn_data[icode].operand[2].mode))
+ op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
- if (! (*insn_operand_predicate[icode][3])
- (op3, insn_operand_mode[icode][3]))
- op3 = copy_to_mode_reg (insn_operand_mode[icode][3], op3);
+ if (! (*insn_data[icode].operand[3].predicate)
+ (op3, insn_data[icode].operand[3].mode))
+ op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
/* Everything should now be in the suitable form, so emit the compare insn
and then the conditional move. */
comparison
- = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0);
+ = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);
/* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
+ /* We can get const0_rtx or const_true_rtx in some circumstances. Just
+ return NULL and let the caller figure out how best to deal with this
+ situation. */
if (GET_CODE (comparison) != code)
- /* This shouldn't happen. */
- abort ();
+ return NULL_RTX;
insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
@@ -3670,7 +3780,7 @@ can_conditionally_move_p (mode)
#endif /* HAVE_conditional_move */
-/* These three functions generate an insn body and return it
+/* These functions generate an insn body and return it
rather than emitting the insn.
They do not protect from queued increments,
@@ -3685,19 +3795,60 @@ gen_add2_insn (x, y)
{
int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
- if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
- || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
- || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
+ if (! ((*insn_data[icode].operand[0].predicate)
+ (x, insn_data[icode].operand[0].mode))
+ || ! ((*insn_data[icode].operand[1].predicate)
+ (x, insn_data[icode].operand[1].mode))
+ || ! ((*insn_data[icode].operand[2].predicate)
+ (y, insn_data[icode].operand[2].mode)))
abort ();
return (GEN_FCN (icode) (x, x, y));
}
+/* Generate and return an insn body to add r1 and c,
+ storing the result in r0. */
+rtx
+gen_add3_insn (r0, r1, c)
+ rtx r0, r1, c;
+{
+ int icode = (int) add_optab->handlers[(int) GET_MODE (r0)].insn_code;
+
+ if (icode == CODE_FOR_nothing
+ || ! ((*insn_data[icode].operand[0].predicate)
+ (r0, insn_data[icode].operand[0].mode))
+ || ! ((*insn_data[icode].operand[1].predicate)
+ (r1, insn_data[icode].operand[1].mode))
+ || ! ((*insn_data[icode].operand[2].predicate)
+ (c, insn_data[icode].operand[2].mode)))
+ return NULL_RTX;
+
+ return (GEN_FCN (icode) (r0, r1, c));
+}
+
int
-have_add2_insn (mode)
- enum machine_mode mode;
+have_add2_insn (x, y)
+ rtx x, y;
{
- return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
+ int icode;
+
+ if (GET_MODE (x) == VOIDmode)
+ abort ();
+
+ icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
+
+ if (icode == CODE_FOR_nothing)
+ return 0;
+
+ if (! ((*insn_data[icode].operand[0].predicate)
+ (x, insn_data[icode].operand[0].mode))
+ || ! ((*insn_data[icode].operand[1].predicate)
+ (x, insn_data[icode].operand[1].mode))
+ || ! ((*insn_data[icode].operand[2].predicate)
+ (y, insn_data[icode].operand[2].mode)))
+ return 0;
+
+ return 1;
}
/* Generate and return an insn body to subtract Y from X. */
@@ -3708,19 +3859,60 @@ gen_sub2_insn (x, y)
{
int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
- if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
- || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
- || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
+ if (! ((*insn_data[icode].operand[0].predicate)
+ (x, insn_data[icode].operand[0].mode))
+ || ! ((*insn_data[icode].operand[1].predicate)
+ (x, insn_data[icode].operand[1].mode))
+ || ! ((*insn_data[icode].operand[2].predicate)
+ (y, insn_data[icode].operand[2].mode)))
abort ();
return (GEN_FCN (icode) (x, x, y));
}
+/* Generate and return an insn body to subtract r1 and c,
+ storing the result in r0. */
+rtx
+gen_sub3_insn (r0, r1, c)
+ rtx r0, r1, c;
+{
+ int icode = (int) sub_optab->handlers[(int) GET_MODE (r0)].insn_code;
+
+ if (icode == CODE_FOR_nothing
+ || ! ((*insn_data[icode].operand[0].predicate)
+ (r0, insn_data[icode].operand[0].mode))
+ || ! ((*insn_data[icode].operand[1].predicate)
+ (r1, insn_data[icode].operand[1].mode))
+ || ! ((*insn_data[icode].operand[2].predicate)
+ (c, insn_data[icode].operand[2].mode)))
+ return NULL_RTX;
+
+ return (GEN_FCN (icode) (r0, r1, c));
+}
+
int
-have_sub2_insn (mode)
- enum machine_mode mode;
+have_sub2_insn (x, y)
+ rtx x, y;
{
- return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
+ int icode;
+
+ if (GET_MODE (x) == VOIDmode)
+ abort ();
+
+ icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
+
+ if (icode == CODE_FOR_nothing)
+ return 0;
+
+ if (! ((*insn_data[icode].operand[0].predicate)
+ (x, insn_data[icode].operand[0].mode))
+ || ! ((*insn_data[icode].operand[1].predicate)
+ (x, insn_data[icode].operand[1].mode))
+ || ! ((*insn_data[icode].operand[2].predicate)
+ (y, insn_data[icode].operand[2].mode)))
+ return 0;
+
+ return 1;
}
/* Generate the body of an instruction to copy Y into X.
@@ -3730,7 +3922,7 @@ rtx
gen_move_insn (x, y)
rtx x, y;
{
- register enum machine_mode mode = GET_MODE (x);
+ enum machine_mode mode = GET_MODE (x);
enum insn_code insn_code;
rtx seq;
@@ -3772,18 +3964,14 @@ gen_move_insn (x, y)
x = gen_lowpart_common (tmode, x1);
if (x == 0 && GET_CODE (x1) == MEM)
{
- x = gen_rtx_MEM (tmode, XEXP (x1, 0));
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
- MEM_COPY_ATTRIBUTES (x, x1);
+ x = adjust_address_nv (x1, tmode, 0);
copy_replacements (x1, x);
}
y = gen_lowpart_common (tmode, y1);
if (y == 0 && GET_CODE (y1) == MEM)
{
- y = gen_rtx_MEM (tmode, XEXP (y1, 0));
- RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
- MEM_COPY_ATTRIBUTES (y, y1);
+ y = adjust_address_nv (y1, tmode, 0);
copy_replacements (y1, y);
}
}
@@ -3813,7 +4001,12 @@ can_extend_p (to_mode, from_mode, unsignedp)
enum machine_mode to_mode, from_mode;
int unsignedp;
{
- return extendtab[(int) to_mode][(int) from_mode][unsignedp];
+#ifdef HAVE_ptr_extend
+ if (unsignedp < 0)
+ return CODE_FOR_ptr_extend;
+ else
+#endif
+ return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0];
}
/* Generate the body of an insn to extend Y (with mode MFROM)
@@ -3825,7 +4018,7 @@ gen_extend_insn (x, y, mto, mfrom, unsignedp)
enum machine_mode mto, mfrom;
int unsignedp;
{
- return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
+ return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp != 0]) (x, y));
}
/* can_fix_p and can_float_p say whether the target machine
@@ -3844,13 +4037,14 @@ can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
int *truncp_ptr;
{
*truncp_ptr = 0;
- if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
- return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
+ if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0]
+ != CODE_FOR_nothing)
+ return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0];
if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
{
*truncp_ptr = 1;
- return fixtab[(int) fltmode][(int) fixmode][unsignedp];
+ return fixtab[(int) fltmode][(int) fixmode][unsignedp != 0];
}
return CODE_FOR_nothing;
}
@@ -3860,7 +4054,7 @@ can_float_p (fltmode, fixmode, unsignedp)
enum machine_mode fixmode, fltmode;
int unsignedp;
{
- return floattab[(int) fltmode][(int) fixmode][unsignedp];
+ return floattab[(int) fltmode][(int) fixmode][unsignedp != 0];
}
/* Generate code to convert FROM to floating point
@@ -3875,7 +4069,7 @@ expand_float (to, from, unsignedp)
int unsignedp;
{
enum insn_code icode;
- register rtx target = to;
+ rtx target = to;
enum machine_mode fmode, imode;
/* Crash now, because we won't be able to decide which mode to use. */
@@ -3894,6 +4088,10 @@ expand_float (to, from, unsignedp)
{
int doing_unsigned = unsignedp;
+ if (fmode != GET_MODE (to)
+ && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
+ continue;
+
icode = can_float_p (fmode, imode, unsignedp);
if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
@@ -3969,8 +4167,8 @@ expand_float (to, from, unsignedp)
do_pending_stack_adjust ();
/* Test whether the sign bit is set. */
- emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0);
- emit_jump_insn (gen_blt (neglabel));
+ emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
+ 0, neglabel);
/* The sign bit is not set. Convert as signed. */
expand_float (target, from, 0);
@@ -4018,7 +4216,7 @@ expand_float (to, from, unsignedp)
do_pending_stack_adjust ();
emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
- 0, 0, label);
+ 0, label);
/* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
Rather than setting up a dconst_dot_5, let's hope SCO
@@ -4101,9 +4299,9 @@ expand_float (to, from, unsignedp)
start_sequence ();
- value = emit_library_call_value (libfcn, NULL_RTX, 1,
- GET_MODE (to),
- 1, from, GET_MODE (from));
+ value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
+ GET_MODE (to), 1, from,
+ GET_MODE (from));
insns = get_insns ();
end_sequence ();
@@ -4138,11 +4336,11 @@ ftruncify (x)
void
expand_fix (to, from, unsignedp)
- register rtx to, from;
+ rtx to, from;
int unsignedp;
{
enum insn_code icode;
- register rtx target = to;
+ rtx target = to;
enum machine_mode fmode, imode;
int must_trunc = 0;
rtx libfcn = 0;
@@ -4152,10 +4350,10 @@ expand_fix (to, from, unsignedp)
this conversion. If the integer mode is wider than the mode of TO,
we can do the conversion either signed or unsigned. */
- for (imode = GET_MODE (to); imode != VOIDmode;
- imode = GET_MODE_WIDER_MODE (imode))
- for (fmode = GET_MODE (from); fmode != VOIDmode;
- fmode = GET_MODE_WIDER_MODE (fmode))
+ for (fmode = GET_MODE (from); fmode != VOIDmode;
+ fmode = GET_MODE_WIDER_MODE (fmode))
+ for (imode = GET_MODE (to); imode != VOIDmode;
+ imode = GET_MODE_WIDER_MODE (imode))
{
int doing_unsigned = unsignedp;
@@ -4226,7 +4424,7 @@ expand_fix (to, from, unsignedp)
/* See if we need to do the subtraction. */
do_pending_stack_adjust ();
emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
- 0, 0, lab1);
+ 0, lab1);
/* If not, do the signed "fix" and branch around fixup code. */
expand_fix (to, from, 0);
@@ -4241,7 +4439,9 @@ expand_fix (to, from, unsignedp)
NULL_RTX, 0, OPTAB_LIB_WIDEN);
expand_fix (to, target, 0);
target = expand_binop (GET_MODE (to), xor_optab, to,
- GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
+ GEN_INT (trunc_int_for_mode
+ ((HOST_WIDE_INT) 1 << (bitsize - 1),
+ GET_MODE (to))),
to, 1, OPTAB_LIB_WIDEN);
if (target != to)
@@ -4260,6 +4460,7 @@ expand_fix (to, from, unsignedp)
GET_MODE (to),
copy_rtx (from)));
}
+
return;
}
#endif
@@ -4334,9 +4535,9 @@ expand_fix (to, from, unsignedp)
start_sequence ();
- value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to),
-
- 1, from, GET_MODE (from));
+ value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
+ GET_MODE (to), 1, from,
+ GET_MODE (from));
insns = get_insns ();
end_sequence ();
@@ -4354,22 +4555,53 @@ expand_fix (to, from, unsignedp)
}
}
-static optab
-init_optab (code)
+/* Report whether we have an instruction to perform the operation
+ specified by CODE on operands of mode MODE. */
+int
+have_insn_for (code, mode)
enum rtx_code code;
+ enum machine_mode mode;
+{
+ return (code_to_optab[(int) code] != 0
+ && (code_to_optab[(int) code]->handlers[(int) mode].insn_code
+ != CODE_FOR_nothing));
+}
+
+/* Create a blank optab. */
+static optab
+new_optab ()
{
int i;
optab op = (optab) xmalloc (sizeof (struct optab));
- op->code = code;
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
op->handlers[i].insn_code = CODE_FOR_nothing;
op->handlers[i].libfunc = 0;
}
- if (code != UNKNOWN)
- code_to_optab[(int) code] = op;
+ return op;
+}
+/* Same, but fill in its code as CODE, and write it into the
+ code_to_optab table. */
+static inline optab
+init_optab (code)
+ enum rtx_code code;
+{
+ optab op = new_optab ();
+ op->code = code;
+ code_to_optab[(int) code] = op;
+ return op;
+}
+
+/* Same, but fill in its code as CODE, and do _not_ write it into
+ the code_to_optab table. */
+static inline optab
+init_optabv (code)
+ enum rtx_code code;
+{
+ optab op = new_optab ();
+ op->code = code;
return op;
}
@@ -4392,24 +4624,23 @@ init_optab (code)
static void
init_libfuncs (optable, first_mode, last_mode, opname, suffix)
- register optab optable;
- register int first_mode;
- register int last_mode;
- register const char *opname;
- register int suffix;
+ optab optable;
+ int first_mode;
+ int last_mode;
+ const char *opname;
+ int suffix;
{
- register int mode;
- register unsigned opname_len = strlen (opname);
+ int mode;
+ unsigned opname_len = strlen (opname);
for (mode = first_mode; (int) mode <= (int) last_mode;
mode = (enum machine_mode) ((int) mode + 1))
{
- register char *mname = mode_name[(int) mode];
- register unsigned mname_len = strlen (mname);
- register char *libfunc_name
- = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
- register char *p;
- register const char *q;
+ const char *mname = GET_MODE_NAME(mode);
+ unsigned mname_len = strlen (mname);
+ char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
+ char *p;
+ const char *q;
p = libfunc_name;
*p++ = '_';
@@ -4417,11 +4648,13 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
for (q = opname; *q; )
*p++ = *q++;
for (q = mname; *q; q++)
- *p++ = tolower ((unsigned char)*q);
+ *p++ = TOLOWER (*q);
*p++ = suffix;
- *p++ = '\0';
+ *p = '\0';
+
optable->handlers[(int) mode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
+ = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (libfunc_name,
+ p - libfunc_name));
}
}
@@ -4432,9 +4665,9 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
static void
init_integral_libfuncs (optable, opname, suffix)
- register optab optable;
- register const char *opname;
- register int suffix;
+ optab optable;
+ const char *opname;
+ int suffix;
{
init_libfuncs (optable, SImode, TImode, opname, suffix);
}
@@ -4446,13 +4679,42 @@ init_integral_libfuncs (optable, opname, suffix)
static void
init_floating_libfuncs (optable, opname, suffix)
- register optab optable;
- register const char *opname;
- register int suffix;
+ optab optable;
+ const char *opname;
+ int suffix;
{
init_libfuncs (optable, SFmode, TFmode, opname, suffix);
}
+rtx
+init_one_libfunc (name)
+ const char *name;
+{
+ /* Create a FUNCTION_DECL that can be passed to ENCODE_SECTION_INFO. */
+ /* ??? We don't have any type information except for this is
+ a function. Pretend this is "int foo()". */
+ tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
+ build_function_type (integer_type_node, NULL_TREE));
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ TREE_PUBLIC (decl) = 1;
+
+ /* Return the symbol_ref from the mem rtx. */
+ 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. */
@@ -4460,34 +4722,29 @@ init_floating_libfuncs (optable, opname, suffix)
void
init_optabs ()
{
- int i;
-#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
- int j;
-#endif
-
- enum insn_code *p;
+ unsigned int i, j, k;
/* Start by initializing all tables to contain CODE_FOR_nothing. */
- for (p = fixtab[0][0];
- p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
- p++)
- *p = CODE_FOR_nothing;
+ for (i = 0; i < ARRAY_SIZE (fixtab); i++)
+ for (j = 0; j < ARRAY_SIZE (fixtab[0]); j++)
+ for (k = 0; k < ARRAY_SIZE (fixtab[0][0]); k++)
+ fixtab[i][j][k] = CODE_FOR_nothing;
- for (p = fixtrunctab[0][0];
- p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
- p++)
- *p = CODE_FOR_nothing;
+ for (i = 0; i < ARRAY_SIZE (fixtrunctab); i++)
+ for (j = 0; j < ARRAY_SIZE (fixtrunctab[0]); j++)
+ for (k = 0; k < ARRAY_SIZE (fixtrunctab[0][0]); k++)
+ fixtrunctab[i][j][k] = CODE_FOR_nothing;
- for (p = floattab[0][0];
- p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
- p++)
- *p = CODE_FOR_nothing;
+ for (i = 0; i < ARRAY_SIZE (floattab); i++)
+ for (j = 0; j < ARRAY_SIZE (floattab[0]); j++)
+ for (k = 0; k < ARRAY_SIZE (floattab[0][0]); k++)
+ floattab[i][j][k] = CODE_FOR_nothing;
- for (p = extendtab[0][0];
- p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
- p++)
- *p = CODE_FOR_nothing;
+ for (i = 0; i < ARRAY_SIZE (extendtab); i++)
+ for (j = 0; j < ARRAY_SIZE (extendtab[0]); j++)
+ for (k = 0; k < ARRAY_SIZE (extendtab[0][0]); k++)
+ extendtab[i][j][k] = CODE_FOR_nothing;
for (i = 0; i < NUM_RTX_CODE; i++)
setcc_gen_code[i] = CODE_FOR_nothing;
@@ -4498,19 +4755,22 @@ init_optabs ()
#endif
add_optab = init_optab (PLUS);
+ addv_optab = init_optabv (PLUS);
sub_optab = init_optab (MINUS);
+ subv_optab = init_optabv (MINUS);
smul_optab = init_optab (MULT);
+ smulv_optab = init_optabv (MULT);
smul_highpart_optab = init_optab (UNKNOWN);
umul_highpart_optab = init_optab (UNKNOWN);
smul_widen_optab = init_optab (UNKNOWN);
umul_widen_optab = init_optab (UNKNOWN);
sdiv_optab = init_optab (DIV);
+ sdivv_optab = init_optabv (DIV);
sdivmod_optab = init_optab (UNKNOWN);
udiv_optab = init_optab (UDIV);
udivmod_optab = init_optab (UNKNOWN);
smod_optab = init_optab (MOD);
umod_optab = init_optab (UMOD);
- flodiv_optab = init_optab (DIV);
ftrunc_optab = init_optab (UNKNOWN);
and_optab = init_optab (AND);
ior_optab = init_optab (IOR);
@@ -4524,19 +4784,29 @@ init_optabs ()
smax_optab = init_optab (SMAX);
umin_optab = init_optab (UMIN);
umax_optab = init_optab (UMAX);
- mov_optab = init_optab (UNKNOWN);
- movstrict_optab = init_optab (UNKNOWN);
- cmp_optab = init_optab (UNKNOWN);
+
+ /* These three have codes assigned exclusively for the sake of
+ have_insn_for. */
+ mov_optab = init_optab (SET);
+ movstrict_optab = init_optab (STRICT_LOW_PART);
+ cmp_optab = init_optab (COMPARE);
+
ucmp_optab = init_optab (UNKNOWN);
tst_optab = init_optab (UNKNOWN);
neg_optab = init_optab (NEG);
+ negv_optab = init_optabv (NEG);
abs_optab = init_optab (ABS);
+ absv_optab = init_optabv (ABS);
one_cmpl_optab = init_optab (NOT);
ffs_optab = init_optab (FFS);
sqrt_optab = init_optab (SQRT);
sin_optab = init_optab (UNKNOWN);
cos_optab = init_optab (UNKNOWN);
strlen_optab = init_optab (UNKNOWN);
+ cbranch_optab = init_optab (UNKNOWN);
+ cmov_optab = init_optab (UNKNOWN);
+ cstore_optab = init_optab (UNKNOWN);
+ push_optab = init_optab (UNKNOWN);
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
@@ -4559,24 +4829,27 @@ init_optabs ()
fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
#endif
-#ifdef EXTRA_CC_MODES
- init_mov_optab ();
-#endif
-
/* Initialize the optabs with the names of the library functions. */
init_integral_libfuncs (add_optab, "add", '3');
init_floating_libfuncs (add_optab, "add", '3');
+ init_integral_libfuncs (addv_optab, "addv", '3');
+ init_floating_libfuncs (addv_optab, "add", '3');
init_integral_libfuncs (sub_optab, "sub", '3');
init_floating_libfuncs (sub_optab, "sub", '3');
+ init_integral_libfuncs (subv_optab, "subv", '3');
+ init_floating_libfuncs (subv_optab, "sub", '3');
init_integral_libfuncs (smul_optab, "mul", '3');
init_floating_libfuncs (smul_optab, "mul", '3');
+ init_integral_libfuncs (smulv_optab, "mulv", '3');
+ init_floating_libfuncs (smulv_optab, "mul", '3');
init_integral_libfuncs (sdiv_optab, "div", '3');
+ init_floating_libfuncs (sdiv_optab, "div", '3');
+ init_integral_libfuncs (sdivv_optab, "divv", '3');
init_integral_libfuncs (udiv_optab, "udiv", '3');
init_integral_libfuncs (sdivmod_optab, "divmod", '4');
init_integral_libfuncs (udivmod_optab, "udivmod", '4');
init_integral_libfuncs (smod_optab, "mod", '3');
init_integral_libfuncs (umod_optab, "umod", '3');
- init_floating_libfuncs (flodiv_optab, "div", '3');
init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
init_integral_libfuncs (and_optab, "and", '3');
init_integral_libfuncs (ior_optab, "ior", '3');
@@ -4592,6 +4865,8 @@ init_optabs ()
init_integral_libfuncs (umax_optab, "umax", '3');
init_integral_libfuncs (neg_optab, "neg", '2');
init_floating_libfuncs (neg_optab, "neg", '2');
+ init_integral_libfuncs (negv_optab, "negv", '2');
+ init_floating_libfuncs (negv_optab, "neg", '2');
init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
init_integral_libfuncs (ffs_optab, "ffs", '2');
@@ -4602,189 +4877,185 @@ init_optabs ()
#ifdef MULSI3_LIBCALL
smul_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, MULSI3_LIBCALL);
+ = init_one_libfunc (MULSI3_LIBCALL);
#endif
#ifdef MULDI3_LIBCALL
smul_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, MULDI3_LIBCALL);
+ = init_one_libfunc (MULDI3_LIBCALL);
#endif
#ifdef DIVSI3_LIBCALL
sdiv_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, DIVSI3_LIBCALL);
+ = init_one_libfunc (DIVSI3_LIBCALL);
#endif
#ifdef DIVDI3_LIBCALL
sdiv_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, DIVDI3_LIBCALL);
+ = init_one_libfunc (DIVDI3_LIBCALL);
#endif
#ifdef UDIVSI3_LIBCALL
udiv_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, UDIVSI3_LIBCALL);
+ = init_one_libfunc (UDIVSI3_LIBCALL);
#endif
#ifdef UDIVDI3_LIBCALL
udiv_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, UDIVDI3_LIBCALL);
+ = init_one_libfunc (UDIVDI3_LIBCALL);
#endif
#ifdef MODSI3_LIBCALL
smod_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, MODSI3_LIBCALL);
+ = init_one_libfunc (MODSI3_LIBCALL);
#endif
#ifdef MODDI3_LIBCALL
smod_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, MODDI3_LIBCALL);
+ = init_one_libfunc (MODDI3_LIBCALL);
#endif
#ifdef UMODSI3_LIBCALL
umod_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, UMODSI3_LIBCALL);
+ = init_one_libfunc (UMODSI3_LIBCALL);
#endif
#ifdef UMODDI3_LIBCALL
umod_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, UMODDI3_LIBCALL);
+ = init_one_libfunc (UMODDI3_LIBCALL);
#endif
/* Use cabs for DC complex abs, since systems generally have cabs.
Don't define any libcall for SCmode, so that cabs will be used. */
abs_optab->handlers[(int) DCmode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, "cabs");
+ = init_one_libfunc ("cabs");
/* The ffs function operates on `int'. */
-#ifndef INT_TYPE_SIZE
-#define INT_TYPE_SIZE BITS_PER_WORD
-#endif
- ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
- = gen_rtx_SYMBOL_REF (Pmode, "ffs");
-
- extendsfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfdf2");
- extendsfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfxf2");
- extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsftf2");
- extenddfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddfxf2");
- extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddftf2");
-
- truncdfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncdfsf2");
- truncxfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfsf2");
- trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfsf2");
- truncxfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfdf2");
- trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfdf2");
-
- memcpy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcpy");
- bcopy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bcopy");
- memcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcmp");
- bcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gcc_bcmp");
- memset_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memset");
- bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero");
-
- throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw");
- rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow");
- sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow");
- sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow");
- terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate");
- eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match");
+ ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
+ = init_one_libfunc ("ffs");
+
+ extendsfdf2_libfunc = init_one_libfunc ("__extendsfdf2");
+ extendsfxf2_libfunc = init_one_libfunc ("__extendsfxf2");
+ extendsftf2_libfunc = init_one_libfunc ("__extendsftf2");
+ extenddfxf2_libfunc = init_one_libfunc ("__extenddfxf2");
+ extenddftf2_libfunc = init_one_libfunc ("__extenddftf2");
+
+ truncdfsf2_libfunc = init_one_libfunc ("__truncdfsf2");
+ truncxfsf2_libfunc = init_one_libfunc ("__truncxfsf2");
+ trunctfsf2_libfunc = init_one_libfunc ("__trunctfsf2");
+ truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2");
+ trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2");
+
+ memcpy_libfunc = init_one_libfunc ("memcpy");
+ memmove_libfunc = init_one_libfunc ("memmove");
+ bcopy_libfunc = init_one_libfunc ("bcopy");
+ memcmp_libfunc = init_one_libfunc ("memcmp");
+ bcmp_libfunc = init_one_libfunc ("__gcc_bcmp");
+ memset_libfunc = init_one_libfunc ("memset");
+ bzero_libfunc = init_one_libfunc ("bzero");
+
+ unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+ ? "_Unwind_SjLj_Resume"
+ : "_Unwind_Resume");
#ifndef DONT_USE_BUILTIN_SETJMP
- setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp");
- longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp");
+ setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
+ longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
#else
- setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "setjmp");
- longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "longjmp");
+ setjmp_libfunc = init_one_libfunc ("setjmp");
+ longjmp_libfunc = init_one_libfunc ("longjmp");
#endif
-
- eqhf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqhf2");
- nehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nehf2");
- gthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gthf2");
- gehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gehf2");
- lthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lthf2");
- lehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lehf2");
-
- eqsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqsf2");
- nesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nesf2");
- gtsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtsf2");
- gesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gesf2");
- ltsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltsf2");
- lesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lesf2");
-
- eqdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqdf2");
- nedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nedf2");
- gtdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtdf2");
- gedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gedf2");
- ltdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltdf2");
- ledf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ledf2");
-
- eqxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqxf2");
- nexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nexf2");
- gtxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtxf2");
- gexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gexf2");
- ltxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltxf2");
- lexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lexf2");
-
- eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqtf2");
- netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__netf2");
- gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gttf2");
- getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__getf2");
- lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lttf2");
- letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__letf2");
-
- floatsisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsisf");
- floatdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdisf");
- floattisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattisf");
-
- floatsidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsidf");
- floatdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdidf");
- floattidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattidf");
-
- floatsixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsixf");
- floatdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdixf");
- floattixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattixf");
-
- floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf");
- floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf");
- floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf");
-
- fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi");
- fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi");
- fixsfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfti");
-
- fixdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfsi");
- fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfdi");
- fixdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfti");
-
- fixxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfsi");
- fixxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfdi");
- fixxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfti");
-
- fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfsi");
- fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfdi");
- fixtfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfti");
-
- fixunssfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfsi");
- fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfdi");
- fixunssfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfti");
-
- fixunsdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfsi");
- fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfdi");
- fixunsdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfti");
-
- fixunsxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfsi");
- fixunsxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfdi");
- fixunsxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfti");
-
- fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfsi");
- fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfdi");
- fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti");
-
- /* For check-memory-usage. */
- chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr");
- chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right");
- chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap");
- chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec");
- chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str");
+ unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
+ unwind_sjlj_unregister_libfunc
+ = init_one_libfunc ("_Unwind_SjLj_Unregister");
+
+ eqhf2_libfunc = init_one_libfunc ("__eqhf2");
+ nehf2_libfunc = init_one_libfunc ("__nehf2");
+ gthf2_libfunc = init_one_libfunc ("__gthf2");
+ gehf2_libfunc = init_one_libfunc ("__gehf2");
+ lthf2_libfunc = init_one_libfunc ("__lthf2");
+ lehf2_libfunc = init_one_libfunc ("__lehf2");
+ unordhf2_libfunc = init_one_libfunc ("__unordhf2");
+
+ eqsf2_libfunc = init_one_libfunc ("__eqsf2");
+ nesf2_libfunc = init_one_libfunc ("__nesf2");
+ gtsf2_libfunc = init_one_libfunc ("__gtsf2");
+ gesf2_libfunc = init_one_libfunc ("__gesf2");
+ ltsf2_libfunc = init_one_libfunc ("__ltsf2");
+ lesf2_libfunc = init_one_libfunc ("__lesf2");
+ unordsf2_libfunc = init_one_libfunc ("__unordsf2");
+
+ eqdf2_libfunc = init_one_libfunc ("__eqdf2");
+ nedf2_libfunc = init_one_libfunc ("__nedf2");
+ gtdf2_libfunc = init_one_libfunc ("__gtdf2");
+ gedf2_libfunc = init_one_libfunc ("__gedf2");
+ ltdf2_libfunc = init_one_libfunc ("__ltdf2");
+ ledf2_libfunc = init_one_libfunc ("__ledf2");
+ unorddf2_libfunc = init_one_libfunc ("__unorddf2");
+
+ eqxf2_libfunc = init_one_libfunc ("__eqxf2");
+ nexf2_libfunc = init_one_libfunc ("__nexf2");
+ gtxf2_libfunc = init_one_libfunc ("__gtxf2");
+ gexf2_libfunc = init_one_libfunc ("__gexf2");
+ ltxf2_libfunc = init_one_libfunc ("__ltxf2");
+ lexf2_libfunc = init_one_libfunc ("__lexf2");
+ unordxf2_libfunc = init_one_libfunc ("__unordxf2");
+
+ eqtf2_libfunc = init_one_libfunc ("__eqtf2");
+ netf2_libfunc = init_one_libfunc ("__netf2");
+ gttf2_libfunc = init_one_libfunc ("__gttf2");
+ getf2_libfunc = init_one_libfunc ("__getf2");
+ lttf2_libfunc = init_one_libfunc ("__lttf2");
+ letf2_libfunc = init_one_libfunc ("__letf2");
+ unordtf2_libfunc = init_one_libfunc ("__unordtf2");
+
+ floatsisf_libfunc = init_one_libfunc ("__floatsisf");
+ floatdisf_libfunc = init_one_libfunc ("__floatdisf");
+ floattisf_libfunc = init_one_libfunc ("__floattisf");
+
+ floatsidf_libfunc = init_one_libfunc ("__floatsidf");
+ floatdidf_libfunc = init_one_libfunc ("__floatdidf");
+ floattidf_libfunc = init_one_libfunc ("__floattidf");
+
+ floatsixf_libfunc = init_one_libfunc ("__floatsixf");
+ floatdixf_libfunc = init_one_libfunc ("__floatdixf");
+ floattixf_libfunc = init_one_libfunc ("__floattixf");
+
+ floatsitf_libfunc = init_one_libfunc ("__floatsitf");
+ floatditf_libfunc = init_one_libfunc ("__floatditf");
+ floattitf_libfunc = init_one_libfunc ("__floattitf");
+
+ fixsfsi_libfunc = init_one_libfunc ("__fixsfsi");
+ fixsfdi_libfunc = init_one_libfunc ("__fixsfdi");
+ fixsfti_libfunc = init_one_libfunc ("__fixsfti");
+
+ fixdfsi_libfunc = init_one_libfunc ("__fixdfsi");
+ fixdfdi_libfunc = init_one_libfunc ("__fixdfdi");
+ fixdfti_libfunc = init_one_libfunc ("__fixdfti");
+
+ fixxfsi_libfunc = init_one_libfunc ("__fixxfsi");
+ fixxfdi_libfunc = init_one_libfunc ("__fixxfdi");
+ fixxfti_libfunc = init_one_libfunc ("__fixxfti");
+
+ fixtfsi_libfunc = init_one_libfunc ("__fixtfsi");
+ fixtfdi_libfunc = init_one_libfunc ("__fixtfdi");
+ fixtfti_libfunc = init_one_libfunc ("__fixtfti");
+
+ fixunssfsi_libfunc = init_one_libfunc ("__fixunssfsi");
+ fixunssfdi_libfunc = init_one_libfunc ("__fixunssfdi");
+ fixunssfti_libfunc = init_one_libfunc ("__fixunssfti");
+
+ fixunsdfsi_libfunc = init_one_libfunc ("__fixunsdfsi");
+ fixunsdfdi_libfunc = init_one_libfunc ("__fixunsdfdi");
+ fixunsdfti_libfunc = init_one_libfunc ("__fixunsdfti");
+
+ fixunsxfsi_libfunc = init_one_libfunc ("__fixunsxfsi");
+ fixunsxfdi_libfunc = init_one_libfunc ("__fixunsxfdi");
+ fixunsxfti_libfunc = init_one_libfunc ("__fixunsxfti");
+
+ fixunstfsi_libfunc = init_one_libfunc ("__fixunstfsi");
+ fixunstfdi_libfunc = init_one_libfunc ("__fixunstfdi");
+ fixunstfti_libfunc = init_one_libfunc ("__fixunstfti");
/* For function entry/exit instrumentation. */
profile_function_entry_libfunc
- = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter");
+ = init_one_libfunc ("__cyg_profile_func_enter");
profile_function_exit_libfunc
- = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit");
+ = init_one_libfunc ("__cyg_profile_func_exit");
#ifdef HAVE_conditional_trap
init_traps ();
@@ -4794,39 +5065,27 @@ init_optabs ()
/* Allow the target to add more libcalls or rename some, etc. */
INIT_TARGET_OPTABS;
#endif
-}
-
-#ifdef BROKEN_LDEXP
-
-/* SCO 3.2 apparently has a broken ldexp. */
-double
-ldexp(x,n)
- double x;
- int n;
-{
- if (n > 0)
- while (n--)
- x *= 2;
-
- return x;
+ /* Add these GC roots. */
+ ggc_add_root (optab_table, OTI_MAX, sizeof(optab), mark_optab);
+ ggc_add_rtx_root (libfunc_table, LTI_MAX);
}
-#endif /* BROKEN_LDEXP */
#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.
-
- ??? Will need to change to support garbage collection. */
+ 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);
+ {
+ trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
+ ggc_add_rtx_root (&trap_rtx, 1);
+ }
}
#endif
@@ -4848,11 +5107,17 @@ gen_cond_trap (code, op1, op2, tcode)
&& cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
rtx insn;
+ start_sequence();
emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
PUT_CODE (trap_rtx, code);
insn = gen_conditional_trap (trap_rtx, tcode);
if (insn)
- return insn;
+ {
+ emit_insn (insn);
+ insn = gen_sequence ();
+ }
+ end_sequence();
+ return insn;
}
#endif
OpenPOWER on IntegriCloud