function.h: Flatten file.
[platform/upstream/gcc.git] / gcc / config / sparc / sparc.c
index 0b494bf..42d14e9 100644 (file)
@@ -38,6 +38,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "output.h"
 #include "insn-attr.h"
 #include "flags.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "vec.h"
+#include "machmode.h"
+#include "input.h"
 #include "function.h"
 #include "except.h"
 #include "expr.h"
@@ -50,9 +55,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "target-def.h"
 #include "common/common-target.h"
-#include "pointer-set.h"
 #include "hash-table.h"
-#include "vec.h"
 #include "basic-block.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
@@ -69,6 +72,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "opts.h"
 #include "tree-pass.h"
 #include "context.h"
+#include "wide-int.h"
+#include "builtins.h"
+#include "rtl-iter.h"
 
 /* Processor costs */
 
@@ -499,9 +505,6 @@ struct GTY(()) machine_function
   rtx frame_base_reg;
   HOST_WIDE_INT frame_base_offset;
 
-  /* Some local-dynamic TLS symbol name.  */
-  const char *some_ld_name;
-
   /* Number of global or FP registers to be saved (as 4-byte quantities).  */
   int n_global_fp_regs;
 
@@ -536,8 +539,8 @@ static void scan_record_type (const_tree, int *, int *, int *);
 static int function_arg_slotno (const CUMULATIVE_ARGS *, enum machine_mode,
                                const_tree, bool, bool, int *, int *);
 
-static int supersparc_adjust_cost (rtx, rtx, rtx, int);
-static int hypersparc_adjust_cost (rtx, rtx, rtx, int);
+static int supersparc_adjust_cost (rtx_insn *, rtx, rtx_insn *, int);
+static int hypersparc_adjust_cost (rtx_insn *, rtx, rtx_insn *, int);
 
 static void sparc_emit_set_const32 (rtx, rtx);
 static void sparc_emit_set_const64 (rtx, rtx);
@@ -549,14 +552,14 @@ static bool sparc_legitimate_constant_p (enum machine_mode, rtx);
 static rtx sparc_builtin_saveregs (void);
 static int epilogue_renumber (rtx *, int);
 static bool sparc_assemble_integer (rtx, unsigned int, int);
-static int set_extends (rtx);
+static int set_extends (rtx_insn *);
 static void sparc_asm_function_prologue (FILE *, HOST_WIDE_INT);
 static void sparc_asm_function_epilogue (FILE *, HOST_WIDE_INT);
 #ifdef TARGET_SOLARIS
 static void sparc_solaris_elf_asm_named_section (const char *, unsigned int,
                                                 tree) ATTRIBUTE_UNUSED;
 #endif
-static int sparc_adjust_cost (rtx, rtx, rtx, int);
+static int sparc_adjust_cost (rtx_insn *, rtx, rtx_insn *, int);
 static int sparc_issue_rate (void);
 static void sparc_sched_init (FILE *, int, int);
 static int sparc_use_sched_lookahead (void);
@@ -583,8 +586,6 @@ static struct machine_function * sparc_init_machine_status (void);
 static bool sparc_cannot_force_const_mem (enum machine_mode, rtx);
 static rtx sparc_tls_get_addr (void);
 static rtx sparc_tls_got (void);
-static const char *get_some_local_dynamic_name (void);
-static int get_some_local_dynamic_name_1 (rtx *, void *);
 static int sparc_register_move_cost (enum machine_mode,
                                     reg_class_t, reg_class_t);
 static bool sparc_rtx_costs (rtx, int, int, int, int *, bool);
@@ -871,17 +872,10 @@ mem_ref (rtx x)
    pass runs as late as possible.  The pass is inserted in the pass pipeline
    at the end of sparc_option_override.  */
 
-static bool
-sparc_gate_work_around_errata (void)
-{
-  /* The only errata we handle are those of the AT697F and UT699.  */
-  return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0;
-}
-
 static unsigned int
 sparc_do_work_around_errata (void)
 {
-  rtx insn, next;
+  rtx_insn *insn, *next;
 
   /* Force all instructions to be split into their final form.  */
   split_all_insns_noflow ();
@@ -893,8 +887,9 @@ sparc_do_work_around_errata (void)
       rtx set;
 
       /* Look into the instruction in a delay slot.  */
-      if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
-       insn = XVECEXP (PATTERN (insn), 0, 1);
+      if (NONJUMP_INSN_P (insn))
+       if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
+         insn = seq->insn (1);
 
       /* Look for a single-word load into an odd-numbered FP register.  */
       if (sparc_fix_at697f
@@ -907,15 +902,15 @@ sparc_do_work_around_errata (void)
          && REGNO (SET_DEST (set)) % 2 != 0)
        {
          /* The wrong dependency is on the enclosing double register.  */
-         unsigned int x = REGNO (SET_DEST (set)) - 1;
+         const unsigned int x = REGNO (SET_DEST (set)) - 1;
          unsigned int src1, src2, dest;
          int code;
 
-         /* If the insn has a delay slot, then it cannot be problematic.  */
          next = next_active_insn (insn);
          if (!next)
            break;
-         if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+         /* If the insn is a branch, then it cannot be problematic.  */
+         if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE)
            continue;
 
          extract_insn (next);
@@ -979,11 +974,11 @@ sparc_do_work_around_errata (void)
             dependency on the first single-cycle load.  */
          rtx x = SET_DEST (set);
 
-         /* If the insn has a delay slot, then it cannot be problematic.  */
          next = next_active_insn (insn);
          if (!next)
            break;
-         if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+         /* If the insn is a branch, then it cannot be problematic.  */
+         if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE)
            continue;
 
          /* Look for a second memory access to/from an integer register.  */
@@ -1001,17 +996,118 @@ sparc_do_work_around_errata (void)
                insert_nop = true;
 
              /* STD is *not* affected.  */
-             else if ((mem = mem_ref (dest)) != NULL_RTX
-                      && GET_MODE_SIZE (GET_MODE (mem)) <= 4
-                      && (src == const0_rtx
+             else if (MEM_P (dest)
+                      && GET_MODE_SIZE (GET_MODE (dest)) <= 4
+                      && (src == CONST0_RTX (GET_MODE (dest))
                           || (REG_P (src)
                               && REGNO (src) < 32
                               && REGNO (src) != REGNO (x)))
-                      && !reg_mentioned_p (x, XEXP (mem, 0)))
+                      && !reg_mentioned_p (x, XEXP (dest, 0)))
                insert_nop = true;
            }
        }
 
+      /* Look for a single-word load/operation into an FP register.  */
+      else if (sparc_fix_ut699
+              && NONJUMP_INSN_P (insn)
+              && (set = single_set (insn)) != NULL_RTX
+              && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
+              && REG_P (SET_DEST (set))
+              && REGNO (SET_DEST (set)) > 31)
+       {
+         /* Number of instructions in the problematic window.  */
+         const int n_insns = 4;
+         /* The problematic combination is with the sibling FP register.  */
+         const unsigned int x = REGNO (SET_DEST (set));
+         const unsigned int y = x ^ 1;
+         rtx_insn *after;
+         int i;
+
+         next = next_active_insn (insn);
+         if (!next)
+           break;
+         /* If the insn is a branch, then it cannot be problematic.  */
+         if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE)
+           continue;
+
+         /* Look for a second load/operation into the sibling FP register.  */
+         if (!((set = single_set (next)) != NULL_RTX
+               && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
+               && REG_P (SET_DEST (set))
+               && REGNO (SET_DEST (set)) == y))
+           continue;
+
+         /* Look for a (possible) store from the FP register in the next N
+            instructions, but bail out if it is again modified or if there
+            is a store from the sibling FP register before this store.  */
+         for (after = next, i = 0; i < n_insns; i++)
+           {
+             bool branch_p;
+
+             after = next_active_insn (after);
+             if (!after)
+               break;
+
+             /* This is a branch with an empty delay slot.  */
+             if (!NONJUMP_INSN_P (after))
+               {
+                 if (++i == n_insns)
+                   break;
+                 branch_p = true;
+                 after = NULL;
+               }
+             /* This is a branch with a filled delay slot.  */
+             else if (rtx_sequence *seq =
+                        dyn_cast <rtx_sequence *> (PATTERN (after)))
+               {
+                 if (++i == n_insns)
+                   break;
+                 branch_p = true;
+                 after = seq->insn (1);
+               }
+             /* This is a regular instruction.  */
+             else
+               branch_p = false;
+
+             if (after && (set = single_set (after)) != NULL_RTX)
+               {
+                 const rtx src = SET_SRC (set);
+                 const rtx dest = SET_DEST (set);
+                 const unsigned int size = GET_MODE_SIZE (GET_MODE (dest));
+
+                 /* If the FP register is again modified before the store,
+                    then the store isn't affected.  */
+                 if (REG_P (dest)
+                     && (REGNO (dest) == x
+                         || (REGNO (dest) == y && size == 8)))
+                   break;
+
+                 if (MEM_P (dest) && REG_P (src))
+                   {
+                     /* If there is a store from the sibling FP register
+                        before the store, then the store is not affected.  */
+                     if (REGNO (src) == y || (REGNO (src) == x && size == 8))
+                       break;
+
+                     /* Otherwise, the store is affected.  */
+                     if (REGNO (src) == x && size == 4)
+                       {
+                         insert_nop = true;
+                         break;
+                       }
+                   }
+               }
+
+             /* If we have a branch in the first M instructions, then we
+                cannot see the (M+2)th instruction so we play safe.  */
+             if (branch_p && i <= (n_insns - 2))
+               {
+                 insert_nop = true;
+                 break;
+               }
+           }
+       }
+
       else
        next = NEXT_INSN (insn);
 
@@ -1029,14 +1125,12 @@ const pass_data pass_data_work_around_errata =
   RTL_PASS, /* type */
   "errata", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
   TV_MACH_DEP, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
   0, /* properties_destroyed */
   0, /* todo_flags_start */
-  TODO_verify_rtl_sharing, /* todo_flags_finish */
+  0, /* todo_flags_finish */
 };
 
 class pass_work_around_errata : public rtl_opt_pass
@@ -1047,8 +1141,16 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return sparc_gate_work_around_errata (); }
-  unsigned int execute () { return sparc_do_work_around_errata (); }
+  virtual bool gate (function *)
+    {
+      /* The only errata we handle are those of the AT697F and UT699.  */
+      return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0;
+    }
+
+  virtual unsigned int execute (function *)
+    {
+      return sparc_do_work_around_errata ();
+    }
 
 }; // class pass_work_around_errata
 
@@ -3325,7 +3427,7 @@ emit_tfmode_cvt (enum rtx_code code, rtx *operands)
    nop into its delay slot.  */
 
 int
-empty_delay_slot (rtx insn)
+empty_delay_slot (rtx_insn *insn)
 {
   rtx seq;
 
@@ -3381,10 +3483,13 @@ emit_cbcond_nop (rtx insn)
 /* Return nonzero if TRIAL can go into the call delay slot.  */
 
 int
-tls_call_delay (rtx trial)
+eligible_for_call_delay (rtx_insn *trial)
 {
   rtx pat;
 
+  if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE)
+    return 0;
+
   /* Binutils allows
        call __tls_get_addr, %tgd_call (foo)
         add %l7, %o0, %o0, %tgd_add (foo)
@@ -3466,11 +3571,7 @@ eligible_for_restore_insn (rtx trial, bool return_p)
 
   /* If we have the 'return' instruction, anything that does not use
      local or output registers and can go into a delay slot wins.  */
-  else if (return_p
-          && TARGET_V9
-          && !epilogue_renumber (&pat, 1)
-          && get_attr_in_uncond_branch_delay (trial)
-              == IN_UNCOND_BRANCH_DELAY_TRUE)
+  else if (return_p && TARGET_V9 && !epilogue_renumber (&pat, 1))
     return 1;
 
   /* The 'restore src1,src2,dest' pattern for SImode.  */
@@ -3508,26 +3609,25 @@ eligible_for_restore_insn (rtx trial, bool return_p)
 /* Return nonzero if TRIAL can go into the function return's delay slot.  */
 
 int
-eligible_for_return_delay (rtx trial)
+eligible_for_return_delay (rtx_insn *trial)
 {
   int regno;
   rtx pat;
 
-  if (! NONJUMP_INSN_P (trial))
-    return 0;
-
-  if (get_attr_length (trial) != 1)
-    return 0;
-
   /* If the function uses __builtin_eh_return, the eh_return machinery
      occupies the delay slot.  */
   if (crtl->calls_eh_return)
     return 0;
 
+  if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE)
+    return 0;
+
   /* In the case of a leaf or flat function, anything can go into the slot.  */
   if (sparc_leaf_function_p || TARGET_FLAT)
-    return
-      get_attr_in_uncond_branch_delay (trial) == IN_UNCOND_BRANCH_DELAY_TRUE;
+    return 1;
+
+  if (!NONJUMP_INSN_P (trial))
+    return 0;
 
   pat = PATTERN (trial);
   if (GET_CODE (pat) == PARALLEL)
@@ -3547,9 +3647,7 @@ eligible_for_return_delay (rtx trial)
          if (regno >= 8 && regno < 24)
            return 0;
        }
-      return !epilogue_renumber (&pat, 1)
-       && (get_attr_in_uncond_branch_delay (trial)
-           == IN_UNCOND_BRANCH_DELAY_TRUE);
+      return !epilogue_renumber (&pat, 1);
     }
 
   if (GET_CODE (pat) != SET)
@@ -3569,10 +3667,7 @@ eligible_for_return_delay (rtx trial)
      instruction, it can probably go in.  But restore will not work
      with FP_REGS.  */
   if (! SPARC_INT_REG_P (regno))
-    return (TARGET_V9
-           && !epilogue_renumber (&pat, 1)
-           && get_attr_in_uncond_branch_delay (trial)
-              == IN_UNCOND_BRANCH_DELAY_TRUE);
+    return TARGET_V9 && !epilogue_renumber (&pat, 1);
 
   return eligible_for_restore_insn (trial, true);
 }
@@ -3580,14 +3675,14 @@ eligible_for_return_delay (rtx trial)
 /* Return nonzero if TRIAL can go into the sibling call's delay slot.  */
 
 int
-eligible_for_sibcall_delay (rtx trial)
+eligible_for_sibcall_delay (rtx_insn *trial)
 {
   rtx pat;
 
-  if (! NONJUMP_INSN_P (trial) || GET_CODE (PATTERN (trial)) != SET)
+  if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE)
     return 0;
 
-  if (get_attr_length (trial) != 1)
+  if (!NONJUMP_INSN_P (trial))
     return 0;
 
   pat = PATTERN (trial);
@@ -3606,6 +3701,9 @@ eligible_for_sibcall_delay (rtx trial)
       return 1;
     }
 
+  if (GET_CODE (pat) != SET)
+    return 0;
+
   /* Otherwise, only operations which can be done in tandem with
      a `restore' insn can go into the delay slot.  */
   if (GET_CODE (SET_DEST (pat)) != REG
@@ -4007,7 +4105,8 @@ sparc_tls_referenced_p (rtx x)
 static rtx
 sparc_legitimize_tls_address (rtx addr)
 {
-  rtx temp1, temp2, temp3, ret, o0, got, insn;
+  rtx temp1, temp2, temp3, ret, o0, got;
+  rtx_insn *insn;
 
   gcc_assert (can_create_pseudo_p ());
 
@@ -4160,7 +4259,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
       || (GET_CODE (orig) == LABEL_REF && !can_use_mov_pic_label_ref (orig)))
     {
       rtx pic_ref, address;
-      rtx insn;
+      rtx_insn *insn;
 
       if (reg == 0)
        {
@@ -4504,7 +4603,7 @@ load_got_register (void)
 void
 sparc_emit_call_insn (rtx pat, rtx addr)
 {
-  rtx insn;
+  rtx_insn *insn;
 
   insn = emit_call_insn (pat);
 
@@ -4725,47 +4824,50 @@ sparc_init_modes (void)
 
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
-      switch (GET_MODE_CLASS (i))
+      enum machine_mode m = (enum machine_mode) i;
+      unsigned int size = GET_MODE_SIZE (m);
+
+      switch (GET_MODE_CLASS (m))
        {
        case MODE_INT:
        case MODE_PARTIAL_INT:
        case MODE_COMPLEX_INT:
-         if (GET_MODE_SIZE (i) < 4)
+         if (size < 4)
            sparc_mode_class[i] = 1 << (int) H_MODE;
-         else if (GET_MODE_SIZE (i) == 4)
+         else if (size == 4)
            sparc_mode_class[i] = 1 << (int) S_MODE;
-         else if (GET_MODE_SIZE (i) == 8)
+         else if (size == 8)
            sparc_mode_class[i] = 1 << (int) D_MODE;
-         else if (GET_MODE_SIZE (i) == 16)
+         else if (size == 16)
            sparc_mode_class[i] = 1 << (int) T_MODE;
-         else if (GET_MODE_SIZE (i) == 32)
+         else if (size == 32)
            sparc_mode_class[i] = 1 << (int) O_MODE;
          else
            sparc_mode_class[i] = 0;
          break;
        case MODE_VECTOR_INT:
-         if (GET_MODE_SIZE (i) == 4)
+         if (size == 4)
            sparc_mode_class[i] = 1 << (int) SF_MODE;
-         else if (GET_MODE_SIZE (i) == 8)
+         else if (size == 8)
            sparc_mode_class[i] = 1 << (int) DF_MODE;
          else
            sparc_mode_class[i] = 0;
          break;
        case MODE_FLOAT:
        case MODE_COMPLEX_FLOAT:
-         if (GET_MODE_SIZE (i) == 4)
+         if (size == 4)
            sparc_mode_class[i] = 1 << (int) SF_MODE;
-         else if (GET_MODE_SIZE (i) == 8)
+         else if (size == 8)
            sparc_mode_class[i] = 1 << (int) DF_MODE;
-         else if (GET_MODE_SIZE (i) == 16)
+         else if (size == 16)
            sparc_mode_class[i] = 1 << (int) TF_MODE;
-         else if (GET_MODE_SIZE (i) == 32)
+         else if (size == 32)
            sparc_mode_class[i] = 1 << (int) OF_MODE;
          else
            sparc_mode_class[i] = 0;
          break;
        case MODE_CC:
-         if (i == (int) CCFPmode || i == (int) CCFPEmode)
+         if (m == CCFPmode || m == CCFPEmode)
            sparc_mode_class[i] = 1 << (int) CCFP_MODE;
          else
            sparc_mode_class[i] = 1 << (int) CC_MODE;
@@ -5148,7 +5250,8 @@ emit_save_or_restore_regs (unsigned int low, unsigned int high, rtx base,
                           sorr_act_t action_true, sorr_act_t action_false)
 {
   unsigned int i;
-  rtx mem, insn;
+  rtx mem;
+  rtx_insn *insn;
 
   if (TARGET_ARCH64 && high <= 32)
     {
@@ -5307,10 +5410,10 @@ emit_save_or_restore_local_in_regs (rtx base, int offset, sorr_act_t action)
 
 /* Emit a window_save insn.  */
 
-static rtx
+static rtx_insn *
 emit_window_save (rtx increment)
 {
-  rtx insn = emit_insn (gen_window_save (increment));
+  rtx_insn *insn = emit_insn (gen_window_save (increment));
   RTX_FRAME_RELATED_P (insn) = 1;
 
   /* The incoming return address (%o7) is saved in %i7.  */
@@ -5351,7 +5454,7 @@ void
 sparc_expand_prologue (void)
 {
   HOST_WIDE_INT size;
-  rtx insn;
+  rtx_insn *insn;
 
   /* Compute a snapshot of crtl->uses_only_leaf_regs.  Relying
      on the final value of the flag means deferring the prologue/epilogue
@@ -5485,7 +5588,7 @@ void
 sparc_flat_expand_prologue (void)
 {
   HOST_WIDE_INT size;
-  rtx insn;
+  rtx_insn *insn;
 
   sparc_leaf_function_p = optimize > 0 && crtl->is_leaf;
 
@@ -5793,7 +5896,7 @@ output_restore (rtx pat)
 /* Output a return.  */
 
 const char *
-output_return (rtx insn)
+output_return (rtx_insn *insn)
 {
   if (crtl->calls_eh_return)
     {
@@ -5880,7 +5983,7 @@ output_return (rtx insn)
 /* Output a sibling call.  */
 
 const char *
-output_sibcall (rtx insn, rtx call_operand)
+output_sibcall (rtx_insn *insn, rtx call_operand)
 {
   rtx operands[1];
 
@@ -5915,7 +6018,7 @@ output_sibcall (rtx insn, rtx call_operand)
 
       if (final_sequence)
        {
-         rtx delay = NEXT_INSN (insn);
+         rtx_insn *delay = NEXT_INSN (insn);
          gcc_assert (delay);
 
          output_restore (PATTERN (delay));
@@ -7163,7 +7266,7 @@ sparc_struct_value_rtx (tree fndecl, int incoming)
             provided.  */
          rtx ret_reg = gen_rtx_REG (Pmode, 31);
          rtx scratch = gen_reg_rtx (SImode);
-         rtx endlab = gen_label_rtx ();
+         rtx_code_label *endlab = gen_label_rtx ();
 
          /* Calculate the return object size */
          tree size = TYPE_SIZE_UNIT (TREE_TYPE (fndecl));
@@ -7487,7 +7590,7 @@ sparc_preferred_simd_mode (enum machine_mode mode)
    DEST is the destination insn (i.e. the label), INSN is the source.  */
 
 const char *
-output_ubranch (rtx dest, rtx insn)
+output_ubranch (rtx dest, rtx_insn *insn)
 {
   static char string[64];
   bool v9_form = false;
@@ -7561,7 +7664,7 @@ output_ubranch (rtx dest, rtx insn)
 
 const char *
 output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
-               rtx insn)
+               rtx_insn *insn)
 {
   static char string[64];
   enum rtx_code code = GET_CODE (op);
@@ -7951,12 +8054,12 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
 void
 sparc_emit_floatunsdi (rtx *operands, enum machine_mode mode)
 {
-  rtx neglab, donelab, i0, i1, f0, in, out;
+  rtx i0, i1, f0, in, out;
 
   out = operands[0];
   in = force_reg (DImode, operands[1]);
-  neglab = gen_label_rtx ();
-  donelab = gen_label_rtx ();
+  rtx_code_label *neglab = gen_label_rtx ();
+  rtx_code_label *donelab = gen_label_rtx ();
   i0 = gen_reg_rtx (DImode);
   i1 = gen_reg_rtx (DImode);
   f0 = gen_reg_rtx (mode);
@@ -7984,12 +8087,12 @@ sparc_emit_floatunsdi (rtx *operands, enum machine_mode mode)
 void
 sparc_emit_fixunsdi (rtx *operands, enum machine_mode mode)
 {
-  rtx neglab, donelab, i0, i1, f0, in, out, limit;
+  rtx i0, i1, f0, in, out, limit;
 
   out = operands[0];
   in = force_reg (mode, operands[1]);
-  neglab = gen_label_rtx ();
-  donelab = gen_label_rtx ();
+  rtx_code_label *neglab = gen_label_rtx ();
+  rtx_code_label *donelab = gen_label_rtx ();
   i0 = gen_reg_rtx (DImode);
   i1 = gen_reg_rtx (DImode);
   limit = gen_reg_rtx (mode);
@@ -8024,7 +8127,7 @@ sparc_emit_fixunsdi (rtx *operands, enum machine_mode mode)
    and OP is the conditional expression.  */
 
 const char *
-output_cbcond (rtx op, rtx dest, rtx insn)
+output_cbcond (rtx op, rtx dest, rtx_insn *insn)
 {
   enum machine_mode mode = GET_MODE (XEXP (op, 0));
   enum rtx_code code = GET_CODE (op);
@@ -8151,7 +8254,7 @@ output_cbcond (rtx op, rtx dest, rtx insn)
 
 const char *
 output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
-                int annul, rtx insn)
+                int annul, rtx_insn *insn)
 {
   static char string[64];
   enum rtx_code code = GET_CODE (op);
@@ -8443,22 +8546,6 @@ sparc_split_regreg_legitimate (rtx reg1, rtx reg2)
   return 0;
 }
 
-/* Return 1 if x and y are some kind of REG and they refer to
-   different hard registers.  This test is guaranteed to be
-   run after reload.  */
-
-int
-sparc_absnegfloat_split_legitimate (rtx x, rtx y)
-{
-  if (GET_CODE (x) != REG)
-    return 0;
-  if (GET_CODE (y) != REG)
-    return 0;
-  if (REGNO (x) == REGNO (y))
-    return 0;
-  return 1;
-}
-
 /* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
    This makes them candidates for using ldd and std insns.
 
@@ -8704,7 +8791,11 @@ sparc_print_operand (FILE *file, rtx x, int code)
       return;
     case '&':
       /* Print some local dynamic TLS name.  */
-      assemble_name (file, get_some_local_dynamic_name ());
+      if (const char *name = get_some_local_dynamic_name ())
+       assemble_name (file, name);
+      else
+       output_operand_lossage ("'%%&' used without any "
+                               "local dynamic TLS references");
       return;
 
     case 'Y':
@@ -9322,7 +9413,7 @@ sparc_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
 
 static int
-supersparc_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
+supersparc_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
 {
   enum attr_type insn_type;
 
@@ -9383,7 +9474,7 @@ supersparc_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
 }
 
 static int
-hypersparc_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
+hypersparc_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
 {
   enum attr_type insn_type, dep_type;
   rtx pat = PATTERN(insn);
@@ -9460,7 +9551,7 @@ hypersparc_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
 }
 
 static int
-sparc_adjust_cost(rtx insn, rtx link, rtx dep, int cost)
+sparc_adjust_cost(rtx_insn *insn, rtx link, rtx_insn *dep, int cost)
 {
   switch (sparc_cpu)
     {
@@ -9528,7 +9619,7 @@ sparc_issue_rate (void)
 }
 
 static int
-set_extends (rtx insn)
+set_extends (rtx_insn *insn)
 {
   register rtx pat = PATTERN (insn);
 
@@ -9694,7 +9785,7 @@ sparc_output_deferred_case_vectors (void)
    unknown.  Return 1 if the high bits are zero, -1 if the register is
    sign extended.  */
 int
-sparc_check_64 (rtx x, rtx insn)
+sparc_check_64 (rtx x, rtx_insn *insn)
 {
   /* If a register is set only once it is safe to ignore insns this
      code does not know how to handle.  The loop will either recognize
@@ -9754,7 +9845,7 @@ sparc_check_64 (rtx x, rtx insn)
    OPERANDS are its operands and OPCODE is the mnemonic to be used.  */
 
 const char *
-output_v8plus_shift (rtx insn, rtx *operands, const char *opcode)
+output_v8plus_shift (rtx_insn *insn, rtx *operands, const char *opcode)
 {
   static char asm_code[60];
 
@@ -10831,30 +10922,30 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
          && TREE_CODE (arg2) == INTEGER_CST)
        {
          bool overflow = false;
-         double_int result = TREE_INT_CST (arg2);
-         double_int tmp;
+         widest_int result = wi::to_widest (arg2);
+         widest_int tmp;
          unsigned i;
 
          for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
            {
-             double_int e0 = TREE_INT_CST (VECTOR_CST_ELT (arg0, i));
-             double_int e1 = TREE_INT_CST (VECTOR_CST_ELT (arg1, i));
+             tree e0 = VECTOR_CST_ELT (arg0, i);
+             tree e1 = VECTOR_CST_ELT (arg1, i);
 
              bool neg1_ovf, neg2_ovf, add1_ovf, add2_ovf;
 
-             tmp = e1.neg_with_overflow (&neg1_ovf);
-             tmp = e0.add_with_sign (tmp, false, &add1_ovf);
-             if (tmp.is_negative ())
-               tmp = tmp.neg_with_overflow (&neg2_ovf);
+             tmp = wi::neg (wi::to_widest (e1), &neg1_ovf);
+             tmp = wi::add (wi::to_widest (e0), tmp, SIGNED, &add1_ovf);
+             if (wi::neg_p (tmp))
+               tmp = wi::neg (tmp, &neg2_ovf);
              else
                neg2_ovf = false;
-             result = result.add_with_sign (tmp, false, &add2_ovf);
+             result = wi::add (result, tmp, SIGNED, &add2_ovf);
              overflow |= neg1_ovf | neg2_ovf | add1_ovf | add2_ovf;
            }
 
          gcc_assert (!overflow);
 
-         return build_int_cst_wide (rtype, result.low, result.high);
+         return wide_int_to_tree (rtype, result);
        }
 
     default:
@@ -11181,7 +11272,8 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
                       HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
                       tree function)
 {
-  rtx this_rtx, insn, funexp;
+  rtx this_rtx, funexp;
+  rtx_insn *insn;
   unsigned int int_arg_first;
 
   reload_completed = 1;
@@ -11394,42 +11486,7 @@ sparc_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
 static struct machine_function *
 sparc_init_machine_status (void)
 {
-  return ggc_alloc_cleared_machine_function ();
-}
-
-/* Locate some local-dynamic symbol still in use by this function
-   so that we can print its name in local-dynamic base patterns.  */
-
-static const char *
-get_some_local_dynamic_name (void)
-{
-  rtx insn;
-
-  if (cfun->machine->some_ld_name)
-    return cfun->machine->some_ld_name;
-
-  for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
-    if (INSN_P (insn)
-       && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
-      return cfun->machine->some_ld_name;
-
-  gcc_unreachable ();
-}
-
-static int
-get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
-{
-  rtx x = *px;
-
-  if (x
-      && GET_CODE (x) == SYMBOL_REF
-      && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
-    {
-      cfun->machine->some_ld_name = XSTR (x, 0);
-      return 1;
-    }
-
-  return 0;
+  return ggc_cleared_alloc<machine_function> ();
 }
 
 /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
@@ -11641,7 +11698,7 @@ sparc_expand_compare_and_swap_12 (rtx bool_result, rtx result, rtx mem,
   rtx newvalue = gen_reg_rtx (SImode);
   rtx res = gen_reg_rtx (SImode);
   rtx resv = gen_reg_rtx (SImode);
-  rtx memsi, val, mask, end_label, loop_label, cc;
+  rtx memsi, val, mask, cc;
 
   emit_insn (gen_rtx_SET (VOIDmode, addr,
                          gen_rtx_AND (Pmode, addr1, GEN_INT (-4))));
@@ -11691,8 +11748,8 @@ sparc_expand_compare_and_swap_12 (rtx bool_result, rtx result, rtx mem,
   emit_insn (gen_rtx_SET (VOIDmode, newv,
                          gen_rtx_AND (SImode, newv, mask)));
 
-  end_label = gen_label_rtx ();
-  loop_label = gen_label_rtx ();
+  rtx_code_label *end_label = gen_label_rtx ();
+  rtx_code_label *loop_label = gen_label_rtx ();
   emit_label (loop_label);
 
   emit_insn (gen_rtx_SET (VOIDmode, oldvalue,
@@ -12037,7 +12094,7 @@ sparc_preferred_reload_class (rtx x, reg_class_t rclass)
    OPERANDS are its operands and OPCODE is the mnemonic to be used.  */
 
 const char *
-output_v8plus_mult (rtx insn, rtx *operands, const char *opcode)
+output_v8plus_mult (rtx_insn *insn, rtx *operands, const char *opcode)
 {
   char mulstr[32];