]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/optabs.c
rtl.c: Define CONST_DOUBLE_FORMAT to the appropriate format for a CONST_DOUBLE...
[gcc.git] / gcc / optabs.c
index 2a321690dc4e8f9254d24de2ec26e44375795b6e..82bfc6a4e12c745f4466031ce9fe228c52be49df 100644 (file)
@@ -1,5 +1,5 @@
 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
-   Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -21,13 +21,18 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "toplev.h"
+
+/* Include insn-config.h before expr.h so that HAVE_conditional_move
+   is properly defined. */
+#include "insn-config.h"
 #include "rtl.h"
 #include "tree.h"
 #include "flags.h"
 #include "insn-flags.h"
 #include "insn-codes.h"
+#include "function.h"
 #include "expr.h"
-#include "insn-config.h"
 #include "recog.h"
 #include "reload.h"
 
@@ -119,6 +124,7 @@ rtx memset_libfunc;
 rtx bzero_libfunc;
 
 rtx throw_libfunc;
+rtx rethrow_libfunc;
 rtx sjthrow_libfunc;
 rtx sjpopnthrow_libfunc;
 rtx terminate_libfunc;
@@ -241,18 +247,35 @@ enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
 static int add_equal_note      PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
 static rtx widen_operand       PROTO((rtx, enum machine_mode,
                                       enum machine_mode, int, int));
+static int expand_cmplxdiv_straight PROTO((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,
+                                      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,
                                       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, char *, int));
-static void init_integral_libfuncs PROTO((optab, char *, int));
-static void init_floating_libfuncs PROTO((optab, char *, int));
+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));
 #ifdef HAVE_conditional_trap
 static void init_traps PROTO((void));
 #endif
+static int cmp_available_p PROTO((enum machine_mode, enum rtx_code, int));
+static void emit_cmp_and_jump_insn_1 PROTO((rtx, rtx, enum machine_mode,
+                                           enum rtx_code, int, rtx));
+static void prepare_cmp_insn PROTO((rtx *, rtx *, enum rtx_code *, rtx,
+                                   enum machine_mode *, int *, int));
+static rtx prepare_operand PROTO((int, rtx, int, enum machine_mode,
+                                 enum machine_mode, int));
+static void prepare_float_lib_cmp PROTO((rtx *, rtx *, enum rtx_code *,
+                                        enum machine_mode *, int *));
 \f
 /* 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
@@ -301,9 +324,7 @@ add_equal_note (seq, target, code, op0, op1)
   else
     note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
 
-  REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
-    = gen_rtx_EXPR_LIST (REG_EQUAL, note,
-                        REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
+  set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note);
 
   return 1;
 }
@@ -345,6 +366,379 @@ widen_operand (op, mode, oldmode, unsignedp, no_extend)
   return result;
 }
 \f
+/* Generate code to perform a straightforward complex divide.  */
+
+static int
+expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
+                         unsignedp, methods, class, binoptab)
+  rtx real0, real1, imag0, imag1, realr, imagr;
+  enum machine_mode submode;
+  int unsignedp;
+  enum optab_methods methods;
+  enum mode_class class;
+  optab binoptab;
+{
+  rtx divisor;
+  rtx real_t, imag_t;
+  rtx temp1, temp2;
+  rtx res;
+             
+  /* Don't fetch these from memory more than once.  */
+  real0 = force_reg (submode, real0);
+  real1 = force_reg (submode, real1);
+
+  if (imag0 != 0)
+    imag0 = force_reg (submode, imag0);
+
+  imag1 = force_reg (submode, imag1);
+
+  /* Divisor: c*c + d*d.  */
+  temp1 = expand_binop (submode, smul_optab, real1, real1,
+                       NULL_RTX, unsignedp, methods);
+
+  temp2 = expand_binop (submode, smul_optab, imag1, imag1,
+                       NULL_RTX, unsignedp, methods);
+
+  if (temp1 == 0 || temp2 == 0)
+    return 0;
+
+  divisor = expand_binop (submode, add_optab, temp1, temp2,
+                         NULL_RTX, unsignedp, methods);
+  if (divisor == 0)
+    return 0;
+
+  if (imag0 == 0)
+    {
+      /* Mathematically, ((a)(c-id))/divisor.  */
+      /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)).  */
+
+      /* Calculate the dividend.  */
+      real_t = expand_binop (submode, smul_optab, real0, real1,
+                            NULL_RTX, unsignedp, methods);
+                 
+      imag_t = expand_binop (submode, smul_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,
+                           NULL_RTX, unsignedp);
+    }
+  else
+    {
+      /* Mathematically, ((a+ib)(c-id))/divider.  */
+      /* Calculate the dividend.  */
+      temp1 = expand_binop (submode, smul_optab, real0, real1,
+                           NULL_RTX, unsignedp, methods);
+
+      temp2 = expand_binop (submode, smul_optab, imag0, imag1,
+                           NULL_RTX, unsignedp, methods);
+
+      if (temp1 == 0 || temp2 == 0)
+       return 0;
+
+      real_t = expand_binop (submode, add_optab, temp1, temp2,
+                            NULL_RTX, unsignedp, methods);
+                 
+      temp1 = expand_binop (submode, smul_optab, imag0, real1,
+                           NULL_RTX, unsignedp, methods);
+
+      temp2 = expand_binop (submode, smul_optab, real0, imag1,
+                           NULL_RTX, unsignedp, methods);
+
+      if (temp1 == 0 || temp2 == 0)
+       return 0;
+
+      imag_t = expand_binop (submode, sub_optab, temp1, temp2,
+                            NULL_RTX, unsignedp, methods);
+
+      if (real_t == 0 || imag_t == 0)
+       return 0;
+    }
+
+  if (class == MODE_COMPLEX_FLOAT)
+    res = expand_binop (submode, binoptab, real_t, divisor,
+                       realr, unsignedp, methods);
+  else
+    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+                        real_t, divisor, realr, unsignedp);
+
+  if (res == 0)
+    return 0;
+
+  if (res != realr)
+    emit_move_insn (realr, res);
+
+  if (class == MODE_COMPLEX_FLOAT)
+    res = expand_binop (submode, binoptab, imag_t, divisor,
+                       imagr, unsignedp, methods);
+  else
+    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+                        imag_t, divisor, imagr, unsignedp);
+
+  if (res == 0)
+    return 0;
+
+  if (res != imagr)
+    emit_move_insn (imagr, res);
+
+  return 1;
+}
+\f
+/* Generate code to perform a wide-input-range-acceptable complex divide.  */
+
+static int
+expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
+                     unsignedp, methods, class, binoptab)
+  rtx real0, real1, imag0, imag1, realr, imagr;
+  enum machine_mode submode;
+  int unsignedp;
+  enum optab_methods methods;
+  enum mode_class class;
+  optab binoptab;
+{
+  rtx ratio, divisor;
+  rtx real_t, imag_t;
+  rtx temp1, temp2, lab1, lab2;
+  enum machine_mode mode;
+  int align;
+  rtx res;
+             
+  /* Don't fetch these from memory more than once.  */
+  real0 = force_reg (submode, real0);
+  real1 = force_reg (submode, real1);
+
+  if (imag0 != 0)
+    imag0 = force_reg (submode, imag0);
+
+  imag1 = force_reg (submode, imag1);
+
+  /* XXX What's an "unsigned" complex number?  */
+  if (unsignedp)
+    {
+      temp1 = real1;
+      temp2 = imag1;
+    }
+  else
+    {
+      temp1 = expand_abs (submode, real1, NULL_RTX, 1);
+      temp2 = expand_abs (submode, imag1, NULL_RTX, 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);
+
+  /* |c| >= |d|; use ratio d/c to scale dividend and divisor.  */
+
+  if (class == MODE_COMPLEX_FLOAT)
+    ratio = expand_binop (submode, binoptab, imag1, real1,
+                         NULL_RTX, unsignedp, methods);
+  else
+    ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+                          imag1, real1, NULL_RTX, unsignedp);
+
+  if (ratio == 0)
+    return 0;
+
+  /* Calculate divisor.  */
+
+  temp1 = expand_binop (submode, smul_optab, imag1, ratio,
+                       NULL_RTX, unsignedp, methods);
+
+  if (temp1 == 0)
+    return 0;
+
+  divisor = expand_binop (submode, add_optab, temp1, real1,
+                         NULL_RTX, unsignedp, methods);
+
+  if (divisor == 0)
+    return 0;
+
+  /* Calculate dividend.  */
+
+  if (imag0 == 0)
+    {
+      real_t = real0;
+
+      /* 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,
+                            NULL_RTX, unsignedp, methods);
+
+      if (imag_t == 0)
+       return 0;
+
+      imag_t = expand_unop (submode, neg_optab, imag_t,
+                           NULL_RTX, unsignedp);
+
+      if (real_t == 0 || imag_t == 0)
+       return 0;
+    }
+  else
+    {
+      /* 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,
+                           NULL_RTX, unsignedp, methods);
+
+      if (temp1 == 0)
+       return 0;
+
+      real_t = expand_binop (submode, add_optab, temp1, real0,
+                            NULL_RTX, unsignedp, methods);
+
+      temp1 = expand_binop (submode, smul_optab, real0, ratio,
+                           NULL_RTX, unsignedp, methods);
+
+      if (temp1 == 0)
+       return 0;
+
+      imag_t = expand_binop (submode, sub_optab, imag0, temp1,
+                            NULL_RTX, unsignedp, methods);
+
+      if (real_t == 0 || imag_t == 0)
+       return 0;
+    }
+
+  if (class == MODE_COMPLEX_FLOAT)
+    res = expand_binop (submode, binoptab, real_t, divisor,
+                       realr, unsignedp, methods);
+  else
+    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+                        real_t, divisor, realr, unsignedp);
+
+  if (res == 0)
+    return 0;
+
+  if (res != realr)
+    emit_move_insn (realr, res);
+
+  if (class == MODE_COMPLEX_FLOAT)
+    res = expand_binop (submode, binoptab, imag_t, divisor,
+                       imagr, unsignedp, methods);
+  else
+    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+                        imag_t, divisor, imagr, unsignedp);
+
+  if (res == 0)
+    return 0;
+
+  if (res != imagr)
+    emit_move_insn (imagr, res);
+
+  lab2 = gen_label_rtx ();
+  emit_jump_insn (gen_jump (lab2));
+  emit_barrier ();
+
+  emit_label (lab1);
+
+  /* |d| > |c|; use ratio c/d to scale dividend and divisor.  */
+
+  if (class == MODE_COMPLEX_FLOAT)
+    ratio = expand_binop (submode, binoptab, real1, imag1,
+                         NULL_RTX, unsignedp, methods);
+  else
+    ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+                          real1, imag1, NULL_RTX, unsignedp);
+
+  if (ratio == 0)
+    return 0;
+
+  /* Calculate divisor.  */
+
+  temp1 = expand_binop (submode, smul_optab, real1, ratio,
+                       NULL_RTX, unsignedp, methods);
+
+  if (temp1 == 0)
+    return 0;
+
+  divisor = expand_binop (submode, add_optab, temp1, imag1,
+                         NULL_RTX, unsignedp, methods);
+
+  if (divisor == 0)
+    return 0;
+
+  /* Calculate dividend.  */
+
+  if (imag0 == 0)
+    {
+      /* 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,
+                            NULL_RTX, unsignedp, methods);
+
+      imag_t = expand_unop (submode, neg_optab, real0,
+                           NULL_RTX, unsignedp);
+
+      if (real_t == 0 || imag_t == 0)
+       return 0;
+    }
+  else
+    {
+      /* 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,
+                           NULL_RTX, unsignedp, methods);
+
+      if (temp1 == 0)
+       return 0;
+
+      real_t = expand_binop (submode, add_optab, temp1, imag0,
+                            NULL_RTX, unsignedp, methods);
+
+      temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+                           NULL_RTX, unsignedp, methods);
+
+      if (temp1 == 0)
+       return 0;
+
+      imag_t = expand_binop (submode, sub_optab, temp1, real0,
+                            NULL_RTX, unsignedp, methods);
+
+      if (real_t == 0 || imag_t == 0)
+       return 0;
+    }
+
+  if (class == MODE_COMPLEX_FLOAT)
+    res = expand_binop (submode, binoptab, real_t, divisor,
+                       realr, unsignedp, methods);
+  else
+    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+                        real_t, divisor, realr, unsignedp);
+
+  if (res == 0)
+    return 0;
+
+  if (res != realr)
+    emit_move_insn (realr, res);
+
+  if (class == MODE_COMPLEX_FLOAT)
+    res = expand_binop (submode, binoptab, imag_t, divisor,
+                       imagr, unsignedp, methods);
+  else
+    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+                        imag_t, divisor, imagr, unsignedp);
+
+  if (res == 0)
+    return 0;
+
+  if (res != imagr)
+    emit_move_insn (imagr, res);
+
+  emit_label (lab2);
+
+  return 1;
+}
+\f
 /* Generate code to perform an operation specified by BINOPTAB
    on operands OP0 and OP1, with result having machine-mode MODE.
 
@@ -895,7 +1289,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
       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;
-      rtx carry_in, carry_out;
+      rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
       rtx xop0, xop1;
 
       /* We can handle either a 1 or -1 value for the carry.  If STORE_FLAG
@@ -941,7 +1335,7 @@ 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);
            }
@@ -964,7 +1358,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
                  /* Get out carry from adding/subtracting carry in.  */
                  carry_tmp = emit_store_flag_force (carry_tmp,
                                                     binoptab == add_optab
-                                                    ? LTU : GTU,
+                                                    ? LT : GT,
                                                     x, carry_in,
                                                     word_mode, 1, normalizep);
 
@@ -986,12 +1380,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
            {
              rtx temp = emit_move_insn (target, target);
 
-             REG_NOTES (temp)
-               = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                    gen_rtx_fmt_ee (binoptab->code, mode,
-                                                    copy_rtx (xop0),
-                                                    copy_rtx (xop1)),
-                                    REG_NOTES (temp));
+             set_unique_reg_note (temp,
+                                  REG_EQUAL,
+                                  gen_rtx_fmt_ee (binoptab->code, mode,
+                                                  copy_rtx (xop0),
+                                                  copy_rtx (xop1)));
            }
          return target;
        }
@@ -1066,8 +1459,8 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
       rtx op1_high = operand_subword_force (op1, high, mode);
       rtx op1_low = operand_subword_force (op1, low, mode);
       rtx product = 0;
-      rtx op0_xhigh;
-      rtx op1_xhigh;
+      rtx op0_xhigh = NULL_RTX;
+      rtx op1_xhigh = NULL_RTX;
 
       /* If the target is the same as one of the inputs, don't use it.  This
         prevents problems with the REG_EQUAL note.  */
@@ -1169,12 +1562,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
              if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                {
                  temp = emit_move_insn (product, product);
-                 REG_NOTES (temp)
-                   = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                        gen_rtx_fmt_ee (MULT, mode,
-                                                        copy_rtx (op0),
-                                                        copy_rtx (op1)),
-                                        REG_NOTES (temp));
+                 set_unique_reg_note (temp,
+                                      REG_EQUAL,
+                                      gen_rtx_fmt_ee (MULT, mode,
+                                                      copy_rtx (op0),
+                                                      copy_rtx (op1)));
                }
              return product;
            }
@@ -1218,12 +1610,12 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
 
       start_sequence ();
 
-      realr = gen_realpart  (submode, target);
+      realr = gen_realpart (submode, target);
       imagr = gen_imagpart (submode, target);
 
       if (GET_MODE (op0) == mode)
        {
-         real0 = gen_realpart  (submode, op0);
+         real0 = gen_realpart (submode, op0);
          imag0 = gen_imagpart (submode, op0);
        }
       else
@@ -1231,7 +1623,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
 
       if (GET_MODE (op1) == mode)
        {
-         real1 = gen_realpart  (submode, op1);
+         real1 = gen_realpart (submode, op1);
          imag1 = gen_imagpart (submode, op1);
        }
       else
@@ -1389,111 +1781,25 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
            }
          else
            {
-             /* Divisor is of complex type:
-                X/(a+ib) */
-             rtx divisor;
-             rtx real_t, imag_t;
-             rtx temp1, temp2;
-             
-             /* Don't fetch these from memory more than once.  */
-             real0 = force_reg (submode, real0);
-             real1 = force_reg (submode, real1);
-
-             if (imag0 != 0)
-               imag0 = force_reg (submode, imag0);
-
-             imag1 = force_reg (submode, imag1);
-
-             /* Divisor: c*c + d*d */
-             temp1 = expand_binop (submode, smul_optab, real1, real1,
-                                   NULL_RTX, unsignedp, methods);
-
-             temp2 = expand_binop (submode, smul_optab, imag1, imag1,
-                                   NULL_RTX, unsignedp, methods);
-
-             if (temp1 == 0 || temp2 == 0)
-               break;
-
-             divisor = expand_binop (submode, add_optab, temp1, temp2,
-                                     NULL_RTX, unsignedp, methods);
-             if (divisor == 0)
-               break;
-
-             if (imag0 == 0)
-               {
-                 /* ((a)(c-id))/divisor */
-                 /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
-
-                 /* Calculate the dividend */
-                 real_t = expand_binop (submode, smul_optab, real0, real1,
-                                        NULL_RTX, unsignedp, methods);
-                 
-                 imag_t = expand_binop (submode, smul_optab, real0, imag1,
-                                        NULL_RTX, unsignedp, methods);
-
-                 if (real_t == 0 || imag_t == 0)
-                   break;
-
-                 imag_t = expand_unop (submode, neg_optab, imag_t,
-                                       NULL_RTX, unsignedp);
-               }
-             else
+             switch (flag_complex_divide_method)
                {
-                 /* ((a+ib)(c-id))/divider */
-                 /* Calculate the dividend */
-                 temp1 = expand_binop (submode, smul_optab, real0, real1,
-                                       NULL_RTX, unsignedp, methods);
-
-                 temp2 = expand_binop (submode, smul_optab, imag0, imag1,
-                                       NULL_RTX, unsignedp, methods);
-
-                 if (temp1 == 0 || temp2 == 0)
-                   break;
-
-                 real_t = expand_binop (submode, add_optab, temp1, temp2,
-                                        NULL_RTX, unsignedp, methods);
-                 
-                 temp1 = expand_binop (submode, smul_optab, imag0, real1,
-                                       NULL_RTX, unsignedp, methods);
-
-                 temp2 = expand_binop (submode, smul_optab, real0, imag1,
-                                       NULL_RTX, unsignedp, methods);
-
-                 if (temp1 == 0 || temp2 == 0)
-                   break;
+               case 0:
+                 ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
+                                                realr, imagr, submode,
+                                                unsignedp, methods,
+                                                class, binoptab);
+                 break;
 
-                 imag_t = expand_binop (submode, sub_optab, temp1, temp2,
-                                        NULL_RTX, unsignedp, methods);
+               case 1:
+                 ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
+                                            realr, imagr, submode,
+                                            unsignedp, methods,
+                                            class, binoptab);
+                 break;
 
-                 if (real_t == 0 || imag_t == 0)
-                   break;
+               default:
+                 abort ();
                }
-
-             if (class == MODE_COMPLEX_FLOAT)
-               res = expand_binop (submode, binoptab, real_t, divisor,
-                                   realr, unsignedp, methods);
-             else
-               res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-                                    real_t, divisor, realr, unsignedp);
-
-             if (res == 0)
-               break;
-             else if (res != realr)
-               emit_move_insn (realr, res);
-
-             if (class == MODE_COMPLEX_FLOAT)
-               res = expand_binop (submode, binoptab, imag_t, divisor,
-                                   imagr, unsignedp, methods);
-             else
-               res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-                                    imag_t, divisor, imagr, unsignedp);
-
-             if (res == 0)
-               break;
-             else if (res != imagr)
-               emit_move_insn (imagr, res);
-
-             ok = 1;
            }
          break;
          
@@ -2105,14 +2411,13 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
    MODE is the mode of the operand; the mode of the result is
    different but can be deduced from MODE.
 
  UNSIGNEDP is relevant if extension is needed.  */
+ */
 
 rtx
-expand_abs (mode, op0, target, unsignedp, safe)
+expand_abs (mode, op0, target, safe)
      enum machine_mode mode;
      rtx op0;
      rtx target;
-     int unsignedp;
      int safe;
 {
   rtx temp, op1;
@@ -2167,19 +2472,8 @@ expand_abs (mode, op0, target, unsignedp, safe)
     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, 0, NULL_RTX, op1);
 
   op0 = expand_unop (mode, neg_optab, target, target, 0);
   if (op0 != target)
@@ -2542,8 +2836,7 @@ emit_no_conflict_block (insns, target, op0, op1, equiv)
     {
       last = emit_move_insn (target, target);
       if (equiv)
-       REG_NOTES (last)
-         = gen_rtx_EXPR_LIST (REG_EQUAL, equiv, REG_NOTES (last));
+       set_unique_reg_note (last, REG_EQUAL, equiv);
     }
   else
     last = get_last_insn ();
@@ -2595,6 +2888,21 @@ emit_libcall_block (insns, target, result, equiv)
 {
   rtx prev, next, first, last, insn;
 
+  /* 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 (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));
+        }
+    }
+
   /* 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
      insns.  These can be generated by move_by_pieces, for example,
@@ -2641,8 +2949,7 @@ emit_libcall_block (insns, target, result, equiv)
   last = emit_move_insn (target, result);
   if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
       != CODE_FOR_nothing)
-    REG_NOTES (last) = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (equiv),
-                                         REG_NOTES (last));
+    set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
 
   if (prev == 0)
     first = get_insns ();
@@ -2674,31 +2981,58 @@ 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 for a conditional jump
+   straightforwardly.  */
 
-   MODE is the mode of the inputs (in case they are const_int).
-   UNSIGNEDP nonzero says that X and Y are unsigned;
+static int
+cmp_available_p (mode, code, can_use_tst_p)
+     enum machine_mode mode;
+     enum rtx_code code;
+     int can_use_tst_p;
+{
+  do
+    {
+      if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing
+         || (can_use_tst_p
+             && tst_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,
+   and ALIGN specifies the known shared alignment of the 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, align)
+     rtx *px, *py;
+     enum rtx_code *pcomparison;
      rtx size;
-     enum machine_mode mode;
-     int unsignedp;
+     enum machine_mode *pmode;
+     int *punsignedp;
      int align;
 {
+  enum rtx_code comparison = *pcomparison;
+  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);
 
@@ -2721,6 +3055,14 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
   if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
     y = force_reg (mode, y);
 
+#ifdef HAVE_cc0
+  /* Abort if we have a non-canonical comparison.  The RTL documentation
+     states that canonical comparisons are required only for targets which
+     have cc0.  */
+  if (CONSTANT_P (x) && ! CONSTANT_P (y))
+    abort();
+#endif
+
   /* Don't let both operands fail to indicate the mode.  */
   if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
     x = force_reg (mode, x);
@@ -2729,6 +3071,9 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
 
   if (mode == BLKmode)
     {
+      rtx result;
+      enum machine_mode result_mode;
+
       emit_queue ();
       x = protect_from_queue (x, 0);
       y = protect_from_queue (y, 0);
@@ -2740,12 +3085,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);
+         result_mode = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
+         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);
        }
       else
 #endif
@@ -2754,33 +3096,25 @@ 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);
+         result_mode = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
+         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);
        }
       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_operand_mode[(int) CODE_FOR_cmpstrsi][0];
+         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);
        }
       else
 #endif
        {
-         rtx result;
-
 #ifdef TARGET_MEM_FUNCTIONS
          emit_library_call (memcmp_libfunc, 0,
                             TYPE_MODE (integer_type_node), 3,
@@ -2802,83 +3136,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 (cmp_available_p (mode, comparison, y == CONST0_RTX (mode)))
+    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;
@@ -2900,18 +3175,173 @@ 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 a unsigned conversion), and
+   that it is accepted by the operand predicate.  Return the new value.  */
+static 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_operand_predicate[icode][opnum])
+      (x, insn_operand_mode[icode][opnum]))
+    x = copy_to_mode_reg (insn_operand_mode[icode][opnum], 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);
+
+      /* 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
+   ensure that the comparison RTL has the canonical form.
+
+   UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
+   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. 
+
+   MODE is the mode of the inputs (in case they are const_int).
+
+   COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  It will
+   be passed unchanged to emit_cmp_insn, then potentially converted into an
+   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)
+     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) && ! CONSTANT_P (y))
+      || (GET_CODE (x) == CONST_INT && GET_CODE (y) != CONST_INT))
+    {
+      /* Swap operands and condition to ensure canonical RTL.  */
+      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
+     X into a register to avoid aborting in emit_cmp_insn due to non-canonical
+     RTL.  */
+  if (CONSTANT_P (op0))
+    op0 = force_reg (mode, op0);
+#endif
+
+  emit_queue ();
+  if (unsignedp)
+    comparison = unsigned_condition (comparison);
+  prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align);
+  emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
+}
+
+/* Like emit_cmp_and_jump_insns, but generate only the comparison.  */
+void
+emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
+     rtx x, y;
+     enum rtx_code comparison;
+     rtx size;
+     enum machine_mode mode;
+     int unsignedp;
+     int align;
+{
+  emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, 0);
+}
+
+
 /* Nonzero if a compare of mode MODE can be done straightforwardly
    (without splitting it into pieces).  */
 
@@ -2932,11 +3362,15 @@ can_compare_p (mode)
 /* 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, y = *py;
   enum machine_mode mode = GET_MODE (x);
   rtx libfunc = 0;
   rtx result;
@@ -3104,9 +3538,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;
            }
        }
@@ -3124,9 +3558,14 @@ emit_float_lib_cmp (x, y, comparison)
      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;
+#ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
+  if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
+    *pcomparison = NE;
+#endif
+  *punsignedp = 0;
 }
 \f
 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
@@ -3388,8 +3827,7 @@ gen_move_insn (x, y)
            {
              x = gen_rtx_MEM (tmode, XEXP (x1, 0));
              RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
-             MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
-             MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
+             MEM_COPY_ATTRIBUTES (x, x1);
              copy_replacements (x1, x);
            }
 
@@ -3398,8 +3836,7 @@ gen_move_insn (x, y)
            {
              y = gen_rtx_MEM (tmode, XEXP (y1, 0));
              RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
-             MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
-             MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
+             MEM_COPY_ATTRIBUTES (y, y1);
              copy_replacements (y1, y);
            }
        }
@@ -3633,8 +4070,8 @@ expand_float (to, from, unsignedp)
         correct its value by 2**bitwidth.  */
 
       do_pending_stack_adjust ();
-      emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
-      emit_jump_insn (gen_bge (label));
+      emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
+                               0, 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
@@ -3841,8 +4278,8 @@ expand_fix (to, from, unsignedp)
 
          /* See if we need to do the subtraction.  */
          do_pending_stack_adjust ();
-         emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
-         emit_jump_insn (gen_bge (lab1));
+         emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
+                                  0, 0, lab1);
 
          /* If not, do the signed "fix" and branch around fixup code.  */
          expand_fix (to, from, 0);
@@ -3870,12 +4307,11 @@ expand_fix (to, from, unsignedp)
            {
              /* Make a place for a REG_NOTE and add it.  */
              insn = emit_move_insn (to, to);
-             REG_NOTES (insn)
-               = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                    gen_rtx_fmt_e (UNSIGNED_FIX,
-                                                   GET_MODE (to),
-                                                   copy_rtx (from)),
-                                    REG_NOTES (insn));
+             set_unique_reg_note (insn,
+                                  REG_EQUAL,
+                                  gen_rtx_fmt_e (UNSIGNED_FIX,
+                                                 GET_MODE (to),
+                                                 copy_rtx (from)));
            }
          return;
        }
@@ -4012,7 +4448,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
     register optab optable;
     register int first_mode;
     register int last_mode;
-    register char *opname;
+    register const char *opname;
     register int suffix;
 {
   register int mode;
@@ -4021,12 +4457,12 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
   for (mode = first_mode; (int) mode <= (int) last_mode;
        mode = (enum machine_mode) ((int) mode + 1))
     {
-      register char *mname = mode_name[(int) mode];
+      register const char *mname = GET_MODE_NAME(mode);
       register unsigned mname_len = strlen (mname);
       register char *libfunc_name
        = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
       register char *p;
-      register char *q;
+      register const char *q;
 
       p = libfunc_name;
       *p++ = '_';
@@ -4034,7 +4470,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
       for (q = opname; *q; )
        *p++ = *q++;
       for (q = mname; *q; q++)
-       *p++ = tolower (*q);
+       *p++ = tolower ((unsigned char)*q);
       *p++ = suffix;
       *p++ = '\0';
       optable->handlers[(int) mode].libfunc
@@ -4050,7 +4486,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
 static void
 init_integral_libfuncs (optable, opname, suffix)
     register optab optable;
-    register char *opname;
+    register const char *opname;
     register int suffix;
 {
   init_libfuncs (optable, SImode, TImode, opname, suffix);
@@ -4064,7 +4500,7 @@ init_integral_libfuncs (optable, opname, suffix)
 static void
 init_floating_libfuncs (optable, opname, suffix)
     register optab optable;
-    register char *opname;
+    register const char *opname;
     register int suffix;
 {
   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
@@ -4176,10 +4612,6 @@ 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');
@@ -4294,6 +4726,7 @@ init_optabs ()
   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");
@@ -4451,8 +4884,8 @@ init_traps ()
 
 rtx
 gen_cond_trap (code, op1, op2, tcode)
-     enum rtx_code code;
-     rtx op1, op2, tcode;
+  enum rtx_code code ATTRIBUTE_UNUSED;
+  rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
 {
   enum machine_mode mode = GET_MODE (op1);
 
This page took 0.064207 seconds and 5 git commands to generate.