OSDN Git Service

* config/usegld.h: New file.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 464de16..71ba002 100644 (file)
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "debug.h"
 #include "target.h"
+#include "common/common-target.h"
 #include "langhooks.h"
 #include "hashtab.h"
 #include "cgraph.h"
@@ -154,7 +155,7 @@ dwarf2out_do_frame (void)
     return true;
 
   if ((flag_unwind_tables || flag_exceptions)
-      && targetm.except_unwind_info (&global_options) == UI_DWARF2)
+      && targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
     return true;
 
   return false;
@@ -190,7 +191,7 @@ dwarf2out_do_cfi_asm (void)
      dwarf2 unwind info for exceptions, then emit .debug_frame by hand.  */
   if (!HAVE_GAS_CFI_SECTIONS_DIRECTIVE
       && !flag_unwind_tables && !flag_exceptions
-      && targetm.except_unwind_info (&global_options) != UI_DWARF2)
+      && targetm_common.except_unwind_info (&global_options) != UI_DWARF2)
     return false;
 
   saved_do_cfi_asm = true;
@@ -4081,7 +4082,7 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
      call-site information.  We must emit this label if it might be used.  */
   if (!do_frame
       && (!flag_exceptions
-         || targetm.except_unwind_info (&global_options) != UI_TARGET))
+         || targetm_common.except_unwind_info (&global_options) != UI_TARGET))
     return;
 
   fnsec = function_section (current_function_decl);
@@ -4244,7 +4245,7 @@ dwarf2out_frame_init (void)
   dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
 
   if (targetm.debug_unwind_info () == UI_DWARF2
-      || targetm.except_unwind_info (&global_options) == UI_DWARF2)
+      || targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
     initial_return_save (INCOMING_RETURN_ADDR_RTX);
 }
 
@@ -4257,7 +4258,7 @@ dwarf2out_frame_finish (void)
 
   /* Output another copy for the unwinder.  */
   if ((flag_unwind_tables || flag_exceptions)
-      && targetm.except_unwind_info (&global_options) == UI_DWARF2)
+      && targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
     output_call_frame_info (1);
 }
 
@@ -4466,6 +4467,9 @@ typedef struct GTY(()) dw_loc_list_struct {
   /* True if this list has been replaced by dw_loc_next.  */
   bool replaced;
   bool emitted;
+  /* True if the range should be emitted even if begin and end
+     are the same.  */
+  bool force;
 } dw_loc_list_node;
 
 static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
@@ -6471,6 +6475,7 @@ static GTY(()) VEC(tree,gc) *generic_type_instances;
 /* Offset from the "steady-state frame pointer" to the frame base,
    within the current function.  */
 static HOST_WIDE_INT frame_pointer_fb_offset;
+static bool frame_pointer_fb_offset_valid;
 
 static VEC (dw_die_ref, heap) *base_types;
 
@@ -8619,7 +8624,30 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
   else
     temp = (var_loc_list *) *slot;
 
-  if (temp->last)
+  /* For PARM_DECLs try to keep around the original incoming value,
+     even if that means we'll emit a zero-range .debug_loc entry.  */
+  if (temp->last
+      && temp->first == temp->last
+      && TREE_CODE (decl) == PARM_DECL
+      && GET_CODE (temp->first->loc) == NOTE
+      && NOTE_VAR_LOCATION_DECL (temp->first->loc) == decl
+      && DECL_INCOMING_RTL (decl)
+      && NOTE_VAR_LOCATION_LOC (temp->first->loc)
+      && GET_CODE (NOTE_VAR_LOCATION_LOC (temp->first->loc))
+        == GET_CODE (DECL_INCOMING_RTL (decl))
+      && prev_real_insn (temp->first->loc) == NULL_RTX
+      && (bitsize != -1
+         || !rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->first->loc),
+                          NOTE_VAR_LOCATION_LOC (loc_note))
+         || (NOTE_VAR_LOCATION_STATUS (temp->first->loc)
+             != NOTE_VAR_LOCATION_STATUS (loc_note))))
+    {
+      loc = ggc_alloc_cleared_var_loc_node ();
+      temp->first->next = loc;
+      temp->last = loc;
+      loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
+    }
+  else if (temp->last)
     {
       struct var_loc_node *last = temp->last, *unused = NULL;
       rtx *piece_loc = NULL, last_loc_note;
@@ -8665,7 +8693,9 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
            }
          else
            {
-             gcc_assert (temp->first == temp->last);
+             gcc_assert (temp->first == temp->last
+                         || (temp->first->next == temp->last
+                             && TREE_CODE (decl) == PARM_DECL));
              memset (temp->last, '\0', sizeof (*temp->last));
              temp->last->loc = construct_piece_list (loc_note, bitpos, bitsize);
              return temp->last;
@@ -11392,7 +11422,7 @@ output_loc_list (dw_loc_list_ref list_head)
     {
       unsigned long size;
       /* Don't output an entry that starts and ends at the same address.  */
-      if (strcmp (curr->begin, curr->end) == 0)
+      if (strcmp (curr->begin, curr->end) == 0 && !curr->force)
        continue;
       if (!have_multiple_function_sections)
        {
@@ -13613,6 +13643,7 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset,
              return new_reg_loc_descr (base_reg, offset);
            }
 
+         gcc_assert (frame_pointer_fb_offset_valid);
          offset += frame_pointer_fb_offset;
          return new_loc_descr (DW_OP_fbreg, offset, 0);
        }
@@ -13855,6 +13886,627 @@ convert_descriptor_to_signed (enum machine_mode mode, dw_loc_descr_ref op)
   return op;
 }
 
+/* Return location descriptor for comparison OP with operands OP0 and OP1.  */
+
+static dw_loc_descr_ref
+compare_loc_descriptor (enum dwarf_location_atom op, dw_loc_descr_ref op0,
+                       dw_loc_descr_ref op1)
+{
+  dw_loc_descr_ref ret = op0;
+  add_loc_descr (&ret, op1);
+  add_loc_descr (&ret, new_loc_descr (op, 0, 0));
+  if (STORE_FLAG_VALUE != 1)
+    {
+      add_loc_descr (&ret, int_loc_descriptor (STORE_FLAG_VALUE));
+      add_loc_descr (&ret, new_loc_descr (DW_OP_mul, 0, 0));
+    }
+  return ret;
+}
+
+/* Return location descriptor for signed comparison OP RTL.  */
+
+static dw_loc_descr_ref
+scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
+                        enum machine_mode mem_mode)
+{
+  enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
+  dw_loc_descr_ref op0, op1;
+  int shift;
+
+  if (op_mode == VOIDmode)
+    op_mode = GET_MODE (XEXP (rtl, 1));
+  if (op_mode == VOIDmode)
+    return NULL;
+
+  if (dwarf_strict
+      && (GET_MODE_CLASS (op_mode) != MODE_INT
+         || GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE))
+    return NULL;
+
+  op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+
+  if (op0 == NULL || op1 == NULL)
+    return NULL;
+
+  if (GET_MODE_CLASS (op_mode) != MODE_INT
+      || GET_MODE_SIZE (op_mode) >= DWARF2_ADDR_SIZE)
+    return compare_loc_descriptor (op, op0, op1);
+
+  shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (op_mode)) * BITS_PER_UNIT;
+  /* For eq/ne, if the operands are known to be zero-extended,
+     there is no need to do the fancy shifting up.  */
+  if (op == DW_OP_eq || op == DW_OP_ne)
+    {
+      dw_loc_descr_ref last0, last1;
+      for (last0 = op0; last0->dw_loc_next != NULL; last0 = last0->dw_loc_next)
+       ;
+      for (last1 = op1; last1->dw_loc_next != NULL; last1 = last1->dw_loc_next)
+       ;
+      /* deref_size zero extends, and for constants we can check
+        whether they are zero extended or not.  */
+      if (((last0->dw_loc_opc == DW_OP_deref_size
+           && last0->dw_loc_oprnd1.v.val_int <= GET_MODE_SIZE (op_mode))
+          || (CONST_INT_P (XEXP (rtl, 0))
+              && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 0))
+                 == (INTVAL (XEXP (rtl, 0)) & GET_MODE_MASK (op_mode))))
+         && ((last1->dw_loc_opc == DW_OP_deref_size
+              && last1->dw_loc_oprnd1.v.val_int <= GET_MODE_SIZE (op_mode))
+             || (CONST_INT_P (XEXP (rtl, 1))
+                 && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 1))
+                    == (INTVAL (XEXP (rtl, 1)) & GET_MODE_MASK (op_mode)))))
+       return compare_loc_descriptor (op, op0, op1);
+    }
+  add_loc_descr (&op0, int_loc_descriptor (shift));
+  add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
+  if (CONST_INT_P (XEXP (rtl, 1)))
+    op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) << shift);
+  else
+    {
+      add_loc_descr (&op1, int_loc_descriptor (shift));
+      add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0));
+    }
+  return compare_loc_descriptor (op, op0, op1);
+}
+
+/* Return location descriptor for unsigned comparison OP RTL.  */
+
+static dw_loc_descr_ref
+ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
+                        enum machine_mode mem_mode)
+{
+  enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
+  dw_loc_descr_ref op0, op1;
+
+  if (op_mode == VOIDmode)
+    op_mode = GET_MODE (XEXP (rtl, 1));
+  if (op_mode == VOIDmode)
+    return NULL;
+  if (GET_MODE_CLASS (op_mode) != MODE_INT)
+    return NULL;
+
+  if (dwarf_strict && GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)
+    return NULL;
+
+  if (op_mode != VOIDmode && GET_MODE_CLASS (op_mode) != MODE_INT)
+    return NULL;
+
+  op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+
+  if (op0 == NULL || op1 == NULL)
+    return NULL;
+
+  if (GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE)
+    {
+      HOST_WIDE_INT mask = GET_MODE_MASK (op_mode);
+      dw_loc_descr_ref last0, last1;
+      for (last0 = op0; last0->dw_loc_next != NULL; last0 = last0->dw_loc_next)
+       ;
+      for (last1 = op1; last1->dw_loc_next != NULL; last1 = last1->dw_loc_next)
+       ;
+      if (CONST_INT_P (XEXP (rtl, 0)))
+       op0 = int_loc_descriptor (INTVAL (XEXP (rtl, 0)) & mask);
+      /* deref_size zero extends, so no need to mask it again.  */
+      else if (last0->dw_loc_opc != DW_OP_deref_size
+              || last0->dw_loc_oprnd1.v.val_int > GET_MODE_SIZE (op_mode))
+       {
+         add_loc_descr (&op0, int_loc_descriptor (mask));
+         add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
+       }
+      if (CONST_INT_P (XEXP (rtl, 1)))
+       op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) & mask);
+      /* deref_size zero extends, so no need to mask it again.  */
+      else if (last1->dw_loc_opc != DW_OP_deref_size
+              || last1->dw_loc_oprnd1.v.val_int > GET_MODE_SIZE (op_mode))
+       {
+         add_loc_descr (&op1, int_loc_descriptor (mask));
+         add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0));
+       }
+    }
+  else if (GET_MODE_SIZE (op_mode) == DWARF2_ADDR_SIZE)
+    {
+      HOST_WIDE_INT bias = 1;
+      bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1);
+      add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0));
+      if (CONST_INT_P (XEXP (rtl, 1)))
+       op1 = int_loc_descriptor ((unsigned HOST_WIDE_INT) bias
+                                 + INTVAL (XEXP (rtl, 1)));
+      else
+       add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst,
+                                           bias, 0));
+    }
+  else
+    {
+      dw_die_ref type_die = base_type_for_mode (op_mode, 1);
+      dw_loc_descr_ref cvt;
+
+      if (type_die == NULL)
+       return NULL;
+      cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+      cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+      cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
+      cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
+      add_loc_descr (&op0, cvt);
+      cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+      cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+      cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
+      cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
+      add_loc_descr (&op1, cvt);
+    }
+  return compare_loc_descriptor (op, op0, op1);
+}
+
+/* Return location descriptor for {U,S}{MIN,MAX}.  */
+
+static dw_loc_descr_ref
+minmax_loc_descriptor (rtx rtl, enum machine_mode mode,
+                      enum machine_mode mem_mode)
+{
+  enum dwarf_location_atom op;
+  dw_loc_descr_ref op0, op1, ret;
+  dw_loc_descr_ref bra_node, drop_node;
+
+  if (dwarf_strict
+      && (GET_MODE_CLASS (mode) != MODE_INT
+         || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE))
+    return NULL;
+
+  op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+
+  if (op0 == NULL || op1 == NULL)
+    return NULL;
+
+  add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0));
+  add_loc_descr (&op1, new_loc_descr (DW_OP_swap, 0, 0));
+  add_loc_descr (&op1, new_loc_descr (DW_OP_over, 0, 0));
+  if (GET_CODE (rtl) == UMIN || GET_CODE (rtl) == UMAX)
+    {
+      if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
+       {
+         HOST_WIDE_INT mask = GET_MODE_MASK (mode);
+         add_loc_descr (&op0, int_loc_descriptor (mask));
+         add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
+         add_loc_descr (&op1, int_loc_descriptor (mask));
+         add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0));
+       }
+      else if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE)
+       {
+         HOST_WIDE_INT bias = 1;
+         bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1);
+         add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0));
+         add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, bias, 0));
+       }
+      else
+       {
+         dw_die_ref type_die = base_type_for_mode (mode, 1);
+         dw_loc_descr_ref cvt;
+         if (type_die == NULL)
+           return NULL;
+         cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+         cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+         cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
+         cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
+         add_loc_descr (&op0, cvt);
+         cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+         cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+         cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
+         cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
+         add_loc_descr (&op1, cvt);
+       }
+    }
+  else if (GET_MODE_CLASS (mode) == MODE_INT
+          && GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
+    {
+      int shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (mode)) * BITS_PER_UNIT;
+      add_loc_descr (&op0, int_loc_descriptor (shift));
+      add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
+      add_loc_descr (&op1, int_loc_descriptor (shift));
+      add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0));
+    }
+
+  if (GET_CODE (rtl) == SMIN || GET_CODE (rtl) == UMIN)
+    op = DW_OP_lt;
+  else
+    op = DW_OP_gt;
+  ret = op0;
+  add_loc_descr (&ret, op1);
+  add_loc_descr (&ret, new_loc_descr (op, 0, 0));
+  bra_node = new_loc_descr (DW_OP_bra, 0, 0);
+  add_loc_descr (&ret, bra_node);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  drop_node = new_loc_descr (DW_OP_drop, 0, 0);
+  add_loc_descr (&ret, drop_node);
+  bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  bra_node->dw_loc_oprnd1.v.val_loc = drop_node;
+  return ret;
+}
+
+/* CLZ (where constV is CLZ_DEFINED_VALUE_AT_ZERO computed value,
+   const0 is DW_OP_lit0 or corresponding typed constant,
+   const1 is DW_OP_lit1 or corresponding typed constant
+   and constMSB is constant with just the MSB bit set
+   for the mode):
+       DW_OP_dup DW_OP_bra <L1> DW_OP_drop constV DW_OP_skip <L4>
+   L1: const0 DW_OP_swap
+   L2: DW_OP_dup constMSB DW_OP_and DW_OP_bra <L3> const1 DW_OP_shl
+       DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip <L2>
+   L3: DW_OP_drop
+   L4: DW_OP_nop
+
+   CTZ is similar:
+       DW_OP_dup DW_OP_bra <L1> DW_OP_drop constV DW_OP_skip <L4>
+   L1: const0 DW_OP_swap
+   L2: DW_OP_dup const1 DW_OP_and DW_OP_bra <L3> const1 DW_OP_shr
+       DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip <L2>
+   L3: DW_OP_drop
+   L4: DW_OP_nop
+
+   FFS is similar:
+       DW_OP_dup DW_OP_bra <L1> DW_OP_drop const0 DW_OP_skip <L4>
+   L1: const1 DW_OP_swap
+   L2: DW_OP_dup const1 DW_OP_and DW_OP_bra <L3> const1 DW_OP_shr
+       DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip <L2>
+   L3: DW_OP_drop
+   L4: DW_OP_nop  */
+
+static dw_loc_descr_ref
+clz_loc_descriptor (rtx rtl, enum machine_mode mode,
+                   enum machine_mode mem_mode)
+{
+  dw_loc_descr_ref op0, ret, tmp;
+  HOST_WIDE_INT valv;
+  dw_loc_descr_ref l1jump, l1label;
+  dw_loc_descr_ref l2jump, l2label;
+  dw_loc_descr_ref l3jump, l3label;
+  dw_loc_descr_ref l4jump, l4label;
+  rtx msb;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT
+      || GET_MODE (XEXP (rtl, 0)) != mode
+      || (GET_CODE (rtl) == CLZ
+         && GET_MODE_BITSIZE (mode) > 2 * HOST_BITS_PER_WIDE_INT))
+    return NULL;
+
+  op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (op0 == NULL)
+    return NULL;
+  ret = op0;
+  if (GET_CODE (rtl) == CLZ)
+    {
+      if (!CLZ_DEFINED_VALUE_AT_ZERO (mode, valv))
+       valv = GET_MODE_BITSIZE (mode);
+    }
+  else if (GET_CODE (rtl) == FFS)
+    valv = 0;
+  else if (!CTZ_DEFINED_VALUE_AT_ZERO (mode, valv))
+    valv = GET_MODE_BITSIZE (mode);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_dup, 0, 0));
+  l1jump = new_loc_descr (DW_OP_bra, 0, 0);
+  add_loc_descr (&ret, l1jump);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_drop, 0, 0));
+  tmp = mem_loc_descriptor (GEN_INT (valv), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (tmp == NULL)
+    return NULL;
+  add_loc_descr (&ret, tmp);
+  l4jump = new_loc_descr (DW_OP_skip, 0, 0);
+  add_loc_descr (&ret, l4jump);
+  l1label = mem_loc_descriptor (GET_CODE (rtl) == FFS
+                               ? const1_rtx : const0_rtx,
+                               mode, mem_mode,
+                               VAR_INIT_STATUS_INITIALIZED);
+  if (l1label == NULL)
+    return NULL;
+  add_loc_descr (&ret, l1label);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  l2label = new_loc_descr (DW_OP_dup, 0, 0);
+  add_loc_descr (&ret, l2label);
+  if (GET_CODE (rtl) != CLZ)
+    msb = const1_rtx;
+  else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+    msb = GEN_INT ((unsigned HOST_WIDE_INT) 1
+                  << (GET_MODE_BITSIZE (mode) - 1));
+  else
+    msb = immed_double_const (0, (unsigned HOST_WIDE_INT) 1
+                                 << (GET_MODE_BITSIZE (mode)
+                                     - HOST_BITS_PER_WIDE_INT - 1), mode);
+  if (GET_CODE (msb) == CONST_INT && INTVAL (msb) < 0)
+    tmp = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32
+                        ? DW_OP_const4u : HOST_BITS_PER_WIDE_INT == 64
+                        ? DW_OP_const8u : DW_OP_constu, INTVAL (msb), 0);
+  else
+    tmp = mem_loc_descriptor (msb, mode, mem_mode,
+                             VAR_INIT_STATUS_INITIALIZED);
+  if (tmp == NULL)
+    return NULL;
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_and, 0, 0));
+  l3jump = new_loc_descr (DW_OP_bra, 0, 0);
+  add_loc_descr (&ret, l3jump);
+  tmp = mem_loc_descriptor (const1_rtx, mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (tmp == NULL)
+    return NULL;
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (GET_CODE (rtl) == CLZ
+                                     ? DW_OP_shl : DW_OP_shr, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, 1, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  l2jump = new_loc_descr (DW_OP_skip, 0, 0);
+  add_loc_descr (&ret, l2jump);
+  l3label = new_loc_descr (DW_OP_drop, 0, 0);
+  add_loc_descr (&ret, l3label);
+  l4label = new_loc_descr (DW_OP_nop, 0, 0);
+  add_loc_descr (&ret, l4label);
+  l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  l1jump->dw_loc_oprnd1.v.val_loc = l1label;
+  l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  l2jump->dw_loc_oprnd1.v.val_loc = l2label;
+  l3jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  l3jump->dw_loc_oprnd1.v.val_loc = l3label;
+  l4jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  l4jump->dw_loc_oprnd1.v.val_loc = l4label;
+  return ret;
+}
+
+/* POPCOUNT (const0 is DW_OP_lit0 or corresponding typed constant,
+   const1 is DW_OP_lit1 or corresponding typed constant):
+       const0 DW_OP_swap
+   L1: DW_OP_dup DW_OP_bra <L2> DW_OP_dup DW_OP_rot const1 DW_OP_and
+       DW_OP_plus DW_OP_swap const1 DW_OP_shr DW_OP_skip <L1>
+   L2: DW_OP_drop
+
+   PARITY is similar:
+   L1: DW_OP_dup DW_OP_bra <L2> DW_OP_dup DW_OP_rot const1 DW_OP_and
+       DW_OP_xor DW_OP_swap const1 DW_OP_shr DW_OP_skip <L1>
+   L2: DW_OP_drop  */
+
+static dw_loc_descr_ref
+popcount_loc_descriptor (rtx rtl, enum machine_mode mode,
+                        enum machine_mode mem_mode)
+{
+  dw_loc_descr_ref op0, ret, tmp;
+  dw_loc_descr_ref l1jump, l1label;
+  dw_loc_descr_ref l2jump, l2label;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT
+      || GET_MODE (XEXP (rtl, 0)) != mode)
+    return NULL;
+
+  op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (op0 == NULL)
+    return NULL;
+  ret = op0;
+  tmp = mem_loc_descriptor (const0_rtx, mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (tmp == NULL)
+    return NULL;
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  l1label = new_loc_descr (DW_OP_dup, 0, 0);
+  add_loc_descr (&ret, l1label);
+  l2jump = new_loc_descr (DW_OP_bra, 0, 0);
+  add_loc_descr (&ret, l2jump);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_dup, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_rot, 0, 0));
+  tmp = mem_loc_descriptor (const1_rtx, mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (tmp == NULL)
+    return NULL;
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_and, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (GET_CODE (rtl) == POPCOUNT
+                                     ? DW_OP_plus : DW_OP_xor, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  tmp = mem_loc_descriptor (const1_rtx, mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_shr, 0, 0));
+  l1jump = new_loc_descr (DW_OP_skip, 0, 0);
+  add_loc_descr (&ret, l1jump);
+  l2label = new_loc_descr (DW_OP_drop, 0, 0);
+  add_loc_descr (&ret, l2label);
+  l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  l1jump->dw_loc_oprnd1.v.val_loc = l1label;
+  l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  l2jump->dw_loc_oprnd1.v.val_loc = l2label;
+  return ret;
+}
+
+/* BSWAP (constS is initial shift count, either 56 or 24):
+       constS const0
+   L1: DW_OP_pick <2> constS DW_OP_pick <3> DW_OP_minus DW_OP_shr
+       const255 DW_OP_and DW_OP_pick <2> DW_OP_shl DW_OP_or
+       DW_OP_swap DW_OP_dup const0 DW_OP_eq DW_OP_bra <L2> const8
+       DW_OP_minus DW_OP_swap DW_OP_skip <L1>
+   L2: DW_OP_drop DW_OP_swap DW_OP_drop  */
+
+static dw_loc_descr_ref
+bswap_loc_descriptor (rtx rtl, enum machine_mode mode,
+                     enum machine_mode mem_mode)
+{
+  dw_loc_descr_ref op0, ret, tmp;
+  dw_loc_descr_ref l1jump, l1label;
+  dw_loc_descr_ref l2jump, l2label;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT
+      || BITS_PER_UNIT != 8
+      || (GET_MODE_BITSIZE (mode) != 32
+         &&  GET_MODE_BITSIZE (mode) != 64))
+    return NULL;
+
+  op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (op0 == NULL)
+    return NULL;
+
+  ret = op0;
+  tmp = mem_loc_descriptor (GEN_INT (GET_MODE_BITSIZE (mode) - 8),
+                           mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (tmp == NULL)
+    return NULL;
+  add_loc_descr (&ret, tmp);
+  tmp = mem_loc_descriptor (const0_rtx, mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (tmp == NULL)
+    return NULL;
+  add_loc_descr (&ret, tmp);
+  l1label = new_loc_descr (DW_OP_pick, 2, 0);
+  add_loc_descr (&ret, l1label);
+  tmp = mem_loc_descriptor (GEN_INT (GET_MODE_BITSIZE (mode) - 8),
+                           mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_pick, 3, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_minus, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_shr, 0, 0));
+  tmp = mem_loc_descriptor (GEN_INT (255), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (tmp == NULL)
+    return NULL;
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_and, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_pick, 2, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_shl, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_or, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_dup, 0, 0));
+  tmp = mem_loc_descriptor (const0_rtx, mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_eq, 0, 0));
+  l2jump = new_loc_descr (DW_OP_bra, 0, 0);
+  add_loc_descr (&ret, l2jump);
+  tmp = mem_loc_descriptor (GEN_INT (8), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  add_loc_descr (&ret, tmp);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_minus, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  l1jump = new_loc_descr (DW_OP_skip, 0, 0);
+  add_loc_descr (&ret, l1jump);
+  l2label = new_loc_descr (DW_OP_drop, 0, 0);
+  add_loc_descr (&ret, l2label);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_drop, 0, 0));
+  l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  l1jump->dw_loc_oprnd1.v.val_loc = l1label;
+  l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  l2jump->dw_loc_oprnd1.v.val_loc = l2label;
+  return ret;
+}
+
+/* ROTATE (constMASK is mode mask, BITSIZE is bitsize of mode):
+   DW_OP_over DW_OP_over DW_OP_shl [ constMASK DW_OP_and ] DW_OP_rot
+   [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_neg
+   DW_OP_plus_uconst <BITSIZE> DW_OP_shr DW_OP_or
+
+   ROTATERT is similar:
+   DW_OP_over DW_OP_over DW_OP_neg DW_OP_plus_uconst <BITSIZE>
+   DW_OP_shl [ constMASK DW_OP_and ] DW_OP_rot
+   [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_shr DW_OP_or  */
+
+static dw_loc_descr_ref
+rotate_loc_descriptor (rtx rtl, enum machine_mode mode,
+                      enum machine_mode mem_mode)
+{
+  rtx rtlop1 = XEXP (rtl, 1);
+  dw_loc_descr_ref op0, op1, ret, mask[2] = { NULL, NULL };
+  int i;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT)
+    return NULL;
+
+  if (GET_MODE (rtlop1) != VOIDmode
+      && GET_MODE_BITSIZE (GET_MODE (rtlop1)) < GET_MODE_BITSIZE (mode))
+    rtlop1 = gen_rtx_ZERO_EXTEND (mode, rtlop1);
+  op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  op1 = mem_loc_descriptor (rtlop1, mode, mem_mode,
+                           VAR_INIT_STATUS_INITIALIZED);
+  if (op0 == NULL || op1 == NULL)
+    return NULL;
+  if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
+    for (i = 0; i < 2; i++)
+      {
+       if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
+         mask[i] = mem_loc_descriptor (GEN_INT (GET_MODE_MASK (mode)),
+                                       mode, mem_mode,
+                                       VAR_INIT_STATUS_INITIALIZED);
+       else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)
+         mask[i] = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32
+                                  ? DW_OP_const4u
+                                  : HOST_BITS_PER_WIDE_INT == 64
+                                  ? DW_OP_const8u : DW_OP_constu,
+                                  GET_MODE_MASK (mode), 0);
+       else
+         mask[i] = NULL;
+       if (mask[i] == NULL)
+         return NULL;
+       add_loc_descr (&mask[i], new_loc_descr (DW_OP_and, 0, 0));
+      }
+  ret = op0;
+  add_loc_descr (&ret, op1);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_over, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_over, 0, 0));
+  if (GET_CODE (rtl) == ROTATERT)
+    {
+      add_loc_descr (&ret, new_loc_descr (DW_OP_neg, 0, 0));
+      add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst,
+                                         GET_MODE_BITSIZE (mode), 0));
+    }
+  add_loc_descr (&ret, new_loc_descr (DW_OP_shl, 0, 0));
+  if (mask[0] != NULL)
+    add_loc_descr (&ret, mask[0]);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_rot, 0, 0));
+  if (mask[1] != NULL)
+    {
+      add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+      add_loc_descr (&ret, mask[1]);
+      add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0));
+    }
+  if (GET_CODE (rtl) == ROTATE)
+    {
+      add_loc_descr (&ret, new_loc_descr (DW_OP_neg, 0, 0));
+      add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst,
+                                         GET_MODE_BITSIZE (mode), 0));
+    }
+  add_loc_descr (&ret, new_loc_descr (DW_OP_shr, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_or, 0, 0));
+  return ret;
+}
+
 /* The following routine converts the RTL for a variable or parameter
    (resident in memory) into an equivalent Dwarf representation of a
    mechanism for getting the address of that same variable onto the top of a
@@ -14283,6 +14935,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
       goto do_shift;
 
     do_shift:
+      if (GET_MODE_CLASS (mode) != MODE_INT)
+       break;
       op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
                                VAR_INIT_STATUS_INITIALIZED);
       {
@@ -14491,218 +15145,44 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
       break;
 
     case EQ:
-      op = DW_OP_eq;
-      goto do_scompare;
+      mem_loc_result = scompare_loc_descriptor (DW_OP_eq, rtl, mem_mode);
+      break;
 
     case GE:
-      op = DW_OP_ge;
-      goto do_scompare;
+      mem_loc_result = scompare_loc_descriptor (DW_OP_ge, rtl, mem_mode);
+      break;
 
     case GT:
-      op = DW_OP_gt;
-      goto do_scompare;
+      mem_loc_result = scompare_loc_descriptor (DW_OP_gt, rtl, mem_mode);
+      break;
 
     case LE:
-      op = DW_OP_le;
-      goto do_scompare;
+      mem_loc_result = scompare_loc_descriptor (DW_OP_le, rtl, mem_mode);
+      break;
 
     case LT:
-      op = DW_OP_lt;
-      goto do_scompare;
+      mem_loc_result = scompare_loc_descriptor (DW_OP_lt, rtl, mem_mode);
+      break;
 
     case NE:
-      op = DW_OP_ne;
-      goto do_scompare;
-
-    do_scompare:
-      {
-       enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
-
-       if (op_mode == VOIDmode)
-         op_mode = GET_MODE (XEXP (rtl, 1));
-       if (op_mode == VOIDmode)
-         break;
-
-       if (dwarf_strict
-           && (GET_MODE_CLASS (op_mode) != MODE_INT
-               || GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE))
-         break;
-
-       op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode,
-                                 VAR_INIT_STATUS_INITIALIZED);
-       op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode,
-                                 VAR_INIT_STATUS_INITIALIZED);
-
-       if (op0 == 0 || op1 == 0)
-         break;
-
-       if (GET_MODE_CLASS (op_mode) == MODE_INT
-           && GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE)
-         {
-           int shift = DWARF2_ADDR_SIZE - GET_MODE_SIZE (op_mode);
-           shift *= BITS_PER_UNIT;
-           /* For eq/ne, if the operands are known to be zero-extended,
-              there is no need to do the fancy shifting up.  */
-           if (op == DW_OP_eq || op == DW_OP_ne)
-             {
-               dw_loc_descr_ref last0, last1;
-               for (last0 = op0;
-                    last0->dw_loc_next != NULL;
-                    last0 = last0->dw_loc_next)
-                 ;
-               for (last1 = op1;
-                    last1->dw_loc_next != NULL;
-                    last1 = last1->dw_loc_next)
-                 ;
-               /* deref_size zero extends, and for constants we can check
-                  whether they are zero extended or not.  */
-               if (((last0->dw_loc_opc == DW_OP_deref_size
-                     && last0->dw_loc_oprnd1.v.val_int
-                        <= GET_MODE_SIZE (op_mode))
-                    || (CONST_INT_P (XEXP (rtl, 0))
-                        && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 0))
-                            == (INTVAL (XEXP (rtl, 0))
-                                & GET_MODE_MASK (op_mode))))
-                   && ((last1->dw_loc_opc == DW_OP_deref_size
-                        && last1->dw_loc_oprnd1.v.val_int
-                           <= GET_MODE_SIZE (op_mode))
-                       || (CONST_INT_P (XEXP (rtl, 1))
-                           && (unsigned HOST_WIDE_INT)
-                              INTVAL (XEXP (rtl, 1))
-                              == (INTVAL (XEXP (rtl, 1))
-                                  & GET_MODE_MASK (op_mode)))))
-                 goto do_compare;
-             }
-           add_loc_descr (&op0, int_loc_descriptor (shift));
-           add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
-           if (CONST_INT_P (XEXP (rtl, 1)))
-             op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) << shift);
-           else
-             {
-               add_loc_descr (&op1, int_loc_descriptor (shift));
-               add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0));
-             }
-         }
-      }
-
-    do_compare:
-      mem_loc_result = op0;
-      add_loc_descr (&mem_loc_result, op1);
-      add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
-      if (STORE_FLAG_VALUE != 1)
-       {
-         add_loc_descr (&mem_loc_result,
-                        int_loc_descriptor (STORE_FLAG_VALUE));
-         add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
-       }
+      mem_loc_result = scompare_loc_descriptor (DW_OP_ne, rtl, mem_mode);
       break;
 
     case GEU:
-      op = DW_OP_ge;
-      goto do_ucompare;
+      mem_loc_result = ucompare_loc_descriptor (DW_OP_ge, rtl, mem_mode);
+      break;
 
     case GTU:
-      op = DW_OP_gt;
-      goto do_ucompare;
+      mem_loc_result = ucompare_loc_descriptor (DW_OP_gt, rtl, mem_mode);
+      break;
 
     case LEU:
-      op = DW_OP_le;
-      goto do_ucompare;
+      mem_loc_result = ucompare_loc_descriptor (DW_OP_le, rtl, mem_mode);
+      break;
 
     case LTU:
-      op = DW_OP_lt;
-      goto do_ucompare;
-
-    do_ucompare:
-      {
-       enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
-
-       if (op_mode == VOIDmode)
-         op_mode = GET_MODE (XEXP (rtl, 1));
-       if (op_mode == VOIDmode)
-         break;
-       if (GET_MODE_CLASS (op_mode) != MODE_INT)
-         break;
-
-       if (dwarf_strict && GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)
-         break;
-
-       if (op_mode != VOIDmode && GET_MODE_CLASS (op_mode) != MODE_INT)
-           break;
-
-       op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode,
-                                 VAR_INIT_STATUS_INITIALIZED);
-       op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode,
-                                 VAR_INIT_STATUS_INITIALIZED);
-
-       if (op0 == 0 || op1 == 0)
-         break;
-
-       if (GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE)
-         {
-           HOST_WIDE_INT mask = GET_MODE_MASK (op_mode);
-           dw_loc_descr_ref last0, last1;
-           for (last0 = op0;
-                last0->dw_loc_next != NULL;
-                last0 = last0->dw_loc_next)
-             ;
-           for (last1 = op1;
-                last1->dw_loc_next != NULL;
-                last1 = last1->dw_loc_next)
-             ;
-           if (CONST_INT_P (XEXP (rtl, 0)))
-             op0 = int_loc_descriptor (INTVAL (XEXP (rtl, 0)) & mask);
-           /* deref_size zero extends, so no need to mask it again.  */
-           else if (last0->dw_loc_opc != DW_OP_deref_size
-                    || last0->dw_loc_oprnd1.v.val_int
-                       > GET_MODE_SIZE (op_mode))
-             {
-               add_loc_descr (&op0, int_loc_descriptor (mask));
-               add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
-             }
-           if (CONST_INT_P (XEXP (rtl, 1)))
-             op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) & mask);
-           /* deref_size zero extends, so no need to mask it again.  */
-           else if (last1->dw_loc_opc != DW_OP_deref_size
-                    || last1->dw_loc_oprnd1.v.val_int
-                       > GET_MODE_SIZE (op_mode))
-             {
-               add_loc_descr (&op1, int_loc_descriptor (mask));
-               add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0));
-             }
-         }
-       else if (GET_MODE_SIZE (op_mode) == DWARF2_ADDR_SIZE)
-         {
-           HOST_WIDE_INT bias = 1;
-           bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1);
-           add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0));
-           if (CONST_INT_P (XEXP (rtl, 1)))
-             op1 = int_loc_descriptor ((unsigned HOST_WIDE_INT) bias
-                                       + INTVAL (XEXP (rtl, 1)));
-           else
-             add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst,
-                                                 bias, 0));
-         }
-       else
-         {
-           dw_die_ref type_die = base_type_for_mode (mode, 1);
-           dw_loc_descr_ref cvt;
-
-           if (type_die == NULL)
-             break;
-           cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
-           cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
-           cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
-           cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
-           add_loc_descr (&op0, cvt);
-           cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
-           cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
-           cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
-           cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
-           add_loc_descr (&op1, cvt);
-         }
-      }
-      goto do_compare;
+      mem_loc_result = ucompare_loc_descriptor (DW_OP_lt, rtl, mem_mode);
+      break;
 
     case UMIN:
     case UMAX:
@@ -14711,87 +15191,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
       /* FALLTHRU */
     case SMIN:
     case SMAX:
-      if (dwarf_strict
-         && (GET_MODE_CLASS (mode) != MODE_INT
-             || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE))
-       break;
-
-      op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
-                               VAR_INIT_STATUS_INITIALIZED);
-      op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, mem_mode,
-                               VAR_INIT_STATUS_INITIALIZED);
-
-      if (op0 == 0 || op1 == 0)
-       break;
-
-      add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0));
-      add_loc_descr (&op1, new_loc_descr (DW_OP_swap, 0, 0));
-      add_loc_descr (&op1, new_loc_descr (DW_OP_over, 0, 0));
-      if (GET_CODE (rtl) == UMIN || GET_CODE (rtl) == UMAX)
-       {
-         if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
-           {
-             HOST_WIDE_INT mask = GET_MODE_MASK (mode);
-             add_loc_descr (&op0, int_loc_descriptor (mask));
-             add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
-             add_loc_descr (&op1, int_loc_descriptor (mask));
-             add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0));
-           }
-         else if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE)
-           {
-             HOST_WIDE_INT bias = 1;
-             bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1);
-             add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0));
-             add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, bias, 0));
-           }
-         else
-           {
-             dw_die_ref type_die = base_type_for_mode (mode, 1);
-             dw_loc_descr_ref cvt;
-
-             if (type_die == NULL)
-               break;
-             cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
-             cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
-             cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
-             cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
-             add_loc_descr (&op0, cvt);
-             cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
-             cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
-             cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
-             cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
-             add_loc_descr (&op1, cvt);
-           }
-       }
-      else if (GET_MODE_CLASS (mode) == MODE_INT
-              && GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
-       {
-         int shift = DWARF2_ADDR_SIZE - GET_MODE_SIZE (mode);
-         shift *= BITS_PER_UNIT;
-         add_loc_descr (&op0, int_loc_descriptor (shift));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
-         add_loc_descr (&op1, int_loc_descriptor (shift));
-         add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0));
-       }
-
-      if (GET_CODE (rtl) == SMIN || GET_CODE (rtl) == UMIN)
-       op = DW_OP_lt;
-      else
-       op = DW_OP_gt;
-      mem_loc_result = op0;
-      add_loc_descr (&mem_loc_result, op1);
-      add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
-      {
-       dw_loc_descr_ref bra_node, drop_node;
-
-       bra_node = new_loc_descr (DW_OP_bra, 0, 0);
-       add_loc_descr (&mem_loc_result, bra_node);
-       add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_swap, 0, 0));
-       drop_node = new_loc_descr (DW_OP_drop, 0, 0);
-       add_loc_descr (&mem_loc_result, drop_node);
-       bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
-       bra_node->dw_loc_oprnd1.v.val_loc = drop_node;
-      }
+      mem_loc_result = minmax_loc_descriptor (rtl, mode, mem_mode);
       break;
 
     case ZERO_EXTRACT:
@@ -14916,345 +15316,21 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
     case CLZ:
     case CTZ:
     case FFS:
-      /* CLZ (where constV is CLZ_DEFINED_VALUE_AT_ZERO computed value,
-             const0 is DW_OP_lit0 or corresponding typed constant,
-             const1 is DW_OP_lit1 or corresponding typed constant
-             and constMSB is constant with just the MSB bit set
-             for the mode):
-          DW_OP_dup DW_OP_bra <L1> DW_OP_drop constV DW_OP_skip <L4>
-        L1: const0 DW_OP_swap
-        L2: DW_OP_dup constMSB DW_OP_and DW_OP_bra <L3> const1 DW_OP_shl
-            DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip <L2>
-        L3: DW_OP_drop
-        L4: DW_OP_nop
-
-        CTZ is similar:
-          DW_OP_dup DW_OP_bra <L1> DW_OP_drop constV DW_OP_skip <L4>
-        L1: const0 DW_OP_swap
-        L2: DW_OP_dup const1 DW_OP_and DW_OP_bra <L3> const1 DW_OP_shr
-            DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip <L2>
-        L3: DW_OP_drop
-        L4: DW_OP_nop
-
-        FFS is similar:
-          DW_OP_dup DW_OP_bra <L1> DW_OP_drop const0 DW_OP_skip <L4>
-        L1: const1 DW_OP_swap
-        L2: DW_OP_dup const1 DW_OP_and DW_OP_bra <L3> const1 DW_OP_shr
-            DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip <L2>
-        L3: DW_OP_drop
-        L4: DW_OP_nop  */
-      if (GET_MODE_CLASS (mode) == MODE_INT
-         && GET_MODE (XEXP (rtl, 0)) == mode
-         && (GET_CODE (rtl) != CLZ
-             || GET_MODE_BITSIZE (mode) <= 2 * HOST_BITS_PER_WIDE_INT))
-       {
-         HOST_WIDE_INT valv;
-         dw_loc_descr_ref l1jump, l1label;
-         dw_loc_descr_ref l2jump, l2label;
-         dw_loc_descr_ref l3jump, l3label;
-         dw_loc_descr_ref l4jump, l4label;
-         rtx msb;
-
-         op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op0 == NULL)
-           break;
-         if (GET_CODE (rtl) == CLZ)
-           {
-             if (!CLZ_DEFINED_VALUE_AT_ZERO (mode, valv))
-               valv = GET_MODE_BITSIZE (mode);
-           }
-         else if (GET_CODE (rtl) == FFS)
-           valv = 0;
-         else if (!CTZ_DEFINED_VALUE_AT_ZERO (mode, valv))
-           valv = GET_MODE_BITSIZE (mode);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0));
-         l1jump = new_loc_descr (DW_OP_bra, 0, 0);
-         add_loc_descr (&op0, l1jump);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_drop, 0, 0));
-         op1 = mem_loc_descriptor (GEN_INT (valv), mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op1 == NULL)
-           break;
-         add_loc_descr (&op0, op1);
-         l4jump = new_loc_descr (DW_OP_skip, 0, 0);
-         add_loc_descr (&op0, l4jump);
-         l1label = mem_loc_descriptor (GET_CODE (rtl) == FFS
-                                       ? const1_rtx : const0_rtx,
-                                       mode, mem_mode,
-                                       VAR_INIT_STATUS_INITIALIZED);
-         if (l1label == NULL)
-           break;
-         add_loc_descr (&op0, l1label);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-         l2label = new_loc_descr (DW_OP_dup, 0, 0);
-         add_loc_descr (&op0, l2label);
-         if (GET_CODE (rtl) != CLZ)
-           msb = const1_rtx;
-         else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
-           msb = GEN_INT ((unsigned HOST_WIDE_INT) 1
-                          << (GET_MODE_BITSIZE (mode) - 1));
-         else
-           msb = immed_double_const (0, (unsigned HOST_WIDE_INT) 1
-                                        << (GET_MODE_BITSIZE (mode)
-                                            - HOST_BITS_PER_WIDE_INT - 1),
-                                     mode);
-         if (GET_CODE (msb) == CONST_INT && INTVAL (msb) < 0)
-           op1 = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32
-                                ? DW_OP_const4u
-                                : HOST_BITS_PER_WIDE_INT == 64
-                                ? DW_OP_const8u : DW_OP_constu,
-                                INTVAL (msb), 0);
-         else
-           op1 = mem_loc_descriptor (msb, mode, mem_mode,
-                                     VAR_INIT_STATUS_INITIALIZED);
-         if (op1 == NULL)
-           break;
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
-         l3jump = new_loc_descr (DW_OP_bra, 0, 0);
-         add_loc_descr (&op0, l3jump);
-         op1 = mem_loc_descriptor (const1_rtx, mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op1 == NULL)
-           break;
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (GET_CODE (rtl) == CLZ
-                                             ? DW_OP_shl : DW_OP_shr, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, 1, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-         l2jump = new_loc_descr (DW_OP_skip, 0, 0);
-         add_loc_descr (&op0, l2jump);
-         l3label = new_loc_descr (DW_OP_drop, 0, 0);
-         add_loc_descr (&op0, l3label);
-         l4label = new_loc_descr (DW_OP_nop, 0, 0);
-         add_loc_descr (&op0, l4label);
-         l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
-         l1jump->dw_loc_oprnd1.v.val_loc = l1label;
-         l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
-         l2jump->dw_loc_oprnd1.v.val_loc = l2label;
-         l3jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
-         l3jump->dw_loc_oprnd1.v.val_loc = l3label;
-         l4jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
-         l4jump->dw_loc_oprnd1.v.val_loc = l4label;
-         mem_loc_result = op0;
-       }
+      mem_loc_result = clz_loc_descriptor (rtl, mode, mem_mode);
       break;
 
     case POPCOUNT:
     case PARITY:
-      /* POPCOUNT (const0 is DW_OP_lit0 or corresponding typed constant,
-                  const1 is DW_OP_lit1 or corresponding typed constant):
-            const0 DW_OP_swap
-        L1: DW_OP_dup DW_OP_bra <L2> DW_OP_dup DW_OP_rot const1 DW_OP_and
-            DW_OP_plus DW_OP_swap const1 DW_OP_shr DW_OP_skip <L1>
-        L2: DW_OP_drop
-
-        PARITY is similar:
-        L1: DW_OP_dup DW_OP_bra <L2> DW_OP_dup DW_OP_rot const1 DW_OP_and
-            DW_OP_xor DW_OP_swap const1 DW_OP_shr DW_OP_skip <L1>
-        L2: DW_OP_drop  */
-      if (GET_MODE_CLASS (mode) == MODE_INT
-         && GET_MODE (XEXP (rtl, 0)) == mode)
-       {
-         dw_loc_descr_ref l1jump, l1label;
-         dw_loc_descr_ref l2jump, l2label;
-
-         op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op0 == NULL)
-           break;
-         op1 = mem_loc_descriptor (const0_rtx, mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op1 == NULL)
-           break;
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-         l1label = new_loc_descr (DW_OP_dup, 0, 0);
-         add_loc_descr (&op0, l1label);
-         l2jump = new_loc_descr (DW_OP_bra, 0, 0);
-         add_loc_descr (&op0, l2jump);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_rot, 0, 0));
-         op1 = mem_loc_descriptor (const1_rtx, mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op1 == NULL)
-           break;
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (GET_CODE (rtl) == POPCOUNT
-                                             ? DW_OP_plus : DW_OP_xor, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-         op1 = mem_loc_descriptor (const1_rtx, mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_shr, 0, 0));
-         l1jump = new_loc_descr (DW_OP_skip, 0, 0);
-         add_loc_descr (&op0, l1jump);
-         l2label = new_loc_descr (DW_OP_drop, 0, 0);
-         add_loc_descr (&op0, l2label);
-         l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
-         l1jump->dw_loc_oprnd1.v.val_loc = l1label;
-         l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
-         l2jump->dw_loc_oprnd1.v.val_loc = l2label;
-         mem_loc_result = op0;
-       }
+      mem_loc_result = popcount_loc_descriptor (rtl, mode, mem_mode);
       break;
 
     case BSWAP:
-      /* BSWAP (constS is initial shift count, either 56 or 24):
-            constS const0
-        L1: DW_OP_pick <2> constS DW_OP_pick <3> DW_OP_minus DW_OP_shr
-            const255 DW_OP_and DW_OP_pick <2> DW_OP_shl DW_OP_or
-            DW_OP_swap DW_OP_dup const0 DW_OP_eq DW_OP_bra <L2> const8
-            DW_OP_minus DW_OP_swap DW_OP_skip <L1>
-        L2: DW_OP_drop DW_OP_swap DW_OP_drop  */
-      if (GET_MODE_CLASS (mode) == MODE_INT
-         && BITS_PER_UNIT == 8
-         && (GET_MODE_BITSIZE (mode) == 32
-             || GET_MODE_BITSIZE (mode) == 64))
-       {
-         dw_loc_descr_ref l1jump, l1label;
-         dw_loc_descr_ref l2jump, l2label;
-
-         op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op0 == NULL)
-           break;
-
-         op1 = mem_loc_descriptor (GEN_INT (GET_MODE_BITSIZE (mode) - 8),
-                                   mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op1 == NULL)
-           break;
-         add_loc_descr (&op0, op1);
-         op1 = mem_loc_descriptor (const0_rtx, mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op1 == NULL)
-           break;
-         add_loc_descr (&op0, op1);
-         l1label = new_loc_descr (DW_OP_pick, 2, 0);
-         add_loc_descr (&op0, l1label);
-         op1 = mem_loc_descriptor (GEN_INT (GET_MODE_BITSIZE (mode) - 8),
-                                   mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_pick, 3, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_minus, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_shr, 0, 0));
-         op1 = mem_loc_descriptor (GEN_INT (255), mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op1 == NULL)
-           break;
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_pick, 2, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_or, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0));
-         op1 = mem_loc_descriptor (const0_rtx, mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_eq, 0, 0));
-         l2jump = new_loc_descr (DW_OP_bra, 0, 0);
-         add_loc_descr (&op0, l2jump);
-         op1 = mem_loc_descriptor (GEN_INT (8), mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_minus, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-         l1jump = new_loc_descr (DW_OP_skip, 0, 0);
-         add_loc_descr (&op0, l1jump);
-         l2label = new_loc_descr (DW_OP_drop, 0, 0);
-         add_loc_descr (&op0, l2label);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_drop, 0, 0));
-         l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
-         l1jump->dw_loc_oprnd1.v.val_loc = l1label;
-         l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc;
-         l2jump->dw_loc_oprnd1.v.val_loc = l2label;
-         mem_loc_result = op0;
-       }
+      mem_loc_result = bswap_loc_descriptor (rtl, mode, mem_mode);
       break;
 
     case ROTATE:
     case ROTATERT:
-      /* ROTATE (constMASK is mode mask, BITSIZE is bitsize of mode):
-            DW_OP_over DW_OP_over DW_OP_shl [ constMASK DW_OP_and ] DW_OP_rot
-            [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_neg
-            DW_OP_plus_uconst <BITSIZE> DW_OP_shr DW_OP_or
-
-        ROTATERT is similar:
-            DW_OP_over DW_OP_over DW_OP_neg DW_OP_plus_uconst <BITSIZE>
-            DW_OP_shl [ constMASK DW_OP_and ] DW_OP_rot
-            [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_shr DW_OP_or
-        */
-      if (GET_MODE_CLASS (mode) == MODE_INT)
-       {
-         rtx rtlop1 = XEXP (rtl, 1);
-         dw_loc_descr_ref mask[2] = { NULL, NULL };
-         int i;
-
-         if (GET_MODE (rtlop1) != VOIDmode
-             && GET_MODE_BITSIZE (GET_MODE (rtlop1))
-                < GET_MODE_BITSIZE (mode))
-           rtlop1 = gen_rtx_ZERO_EXTEND (mode, rtlop1);
-         op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         op1 = mem_loc_descriptor (rtlop1, mode, mem_mode,
-                                   VAR_INIT_STATUS_INITIALIZED);
-         if (op0 == NULL || op1 == NULL)
-           break;
-         if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
-           for (i = 0; i < 2; i++)
-             {
-               if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
-                 mask[i] = mem_loc_descriptor (GEN_INT (GET_MODE_MASK (mode)),
-                                               mode, mem_mode,
-                                               VAR_INIT_STATUS_INITIALIZED);
-               else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)
-                 mask[i] = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32
-                                          ? DW_OP_const4u
-                                          : HOST_BITS_PER_WIDE_INT == 64
-                                          ? DW_OP_const8u : DW_OP_constu,
-                                          GET_MODE_MASK (mode), 0);
-               else
-                 mask[i] = NULL;
-               if (mask[i] == NULL)
-                 return NULL;
-               add_loc_descr (&mask[i], new_loc_descr (DW_OP_and, 0, 0));
-             }
-         add_loc_descr (&op0, op1);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_over, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_over, 0, 0));
-         if (GET_CODE (rtl) == ROTATERT)
-           {
-             add_loc_descr (&op0, new_loc_descr (DW_OP_neg, 0, 0));
-             add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst,
-                                                 GET_MODE_BITSIZE (mode), 0));
-           }
-         add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
-         if (mask[0] != NULL)
-           add_loc_descr (&op0, mask[0]);
-         add_loc_descr (&op0, new_loc_descr (DW_OP_rot, 0, 0));
-         if (mask[1] != NULL)
-           {
-             add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-             add_loc_descr (&op0, mask[1]);
-             add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0));
-           }
-         if (GET_CODE (rtl) == ROTATE)
-           {
-             add_loc_descr (&op0, new_loc_descr (DW_OP_neg, 0, 0));
-             add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst,
-                                                 GET_MODE_BITSIZE (mode), 0));
-           }
-         add_loc_descr (&op0, new_loc_descr (DW_OP_shr, 0, 0));
-         add_loc_descr (&op0, new_loc_descr (DW_OP_or, 0, 0));
-         mem_loc_result = op0;
-       }
+      mem_loc_result = rotate_loc_descriptor (rtl, mode, mem_mode);
       break;
 
     case COMPARE:
@@ -16042,6 +16118,11 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
              }
 
            *listp = new_loc_list (descr, node->label, endname, secname);
+           if (TREE_CODE (decl) == PARM_DECL
+               && node == loc_list->first
+               && GET_CODE (node->loc) == NOTE
+               && strcmp (node->label, endname) == 0)
+             (*listp)->force = true;
            listp = &(*listp)->dw_loc_next;
 
            if (range_across_switch)
@@ -18020,7 +18101,7 @@ native_encode_initializer (tree init, unsigned char *array, int size)
                {
                  int count = tree_low_cst (TREE_OPERAND (index, 1), 0)
                              - tree_low_cst (TREE_OPERAND (index, 0), 0);
-                 while (count > 0)
+                 while (count-- > 0)
                    {
                      if (val)
                        memcpy (array + curpos, array + pos, fieldsize);
@@ -18291,14 +18372,20 @@ compute_frame_pointer_to_fb_displacement (HOST_WIDE_INT offset)
       elim = XEXP (elim, 0);
     }
 
-  gcc_assert ((SUPPORTS_STACK_ALIGNMENT
-              && (elim == hard_frame_pointer_rtx
-                  || elim == stack_pointer_rtx))
-             || elim == (frame_pointer_needed
-                         ? hard_frame_pointer_rtx
-                         : stack_pointer_rtx));
-
   frame_pointer_fb_offset = -offset;
+
+  /* ??? AVR doesn't set up valid eliminations when there is no stack frame
+     in which to eliminate.  This is because it's stack pointer isn't 
+     directly accessible as a register within the ISA.  To work around
+     this, assume that while we cannot provide a proper value for
+     frame_pointer_fb_offset, we won't need one either.  */
+  frame_pointer_fb_offset_valid
+    = ((SUPPORTS_STACK_ALIGNMENT
+       && (elim == hard_frame_pointer_rtx
+           || elim == stack_pointer_rtx))
+       || elim == (frame_pointer_needed
+                  ? hard_frame_pointer_rtx
+                  : stack_pointer_rtx));
 }
 
 /* Generate a DW_AT_name attribute given some string value to be included as
@@ -23485,7 +23572,7 @@ dwarf2out_assembly_start (void)
   if (HAVE_GAS_CFI_SECTIONS_DIRECTIVE
       && dwarf2out_do_cfi_asm ()
       && (!(flag_unwind_tables || flag_exceptions)
-         || targetm.except_unwind_info (&global_options) != UI_DWARF2))
+         || targetm_common.except_unwind_info (&global_options) != UI_DWARF2))
     fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n");
 }