t-aarch64-linux (MULTILIB_OSDIRNAMES): Handle multi-arch for ilp32.
[gcc.git] / gcc / var-tracking.c
index 8e500b144712a2007f8f171486bfb201498663ad..77281fb45ee228e8cb802bcf61aff989c9b2c580 100644 (file)
@@ -395,8 +395,9 @@ struct variable
 static inline HOST_WIDE_INT
 int_mem_offset (const_rtx mem)
 {
-  if (MEM_OFFSET_KNOWN_P (mem))
-    return MEM_OFFSET (mem);
+  HOST_WIDE_INT offset;
+  if (MEM_OFFSET_KNOWN_P (mem) && MEM_OFFSET (mem).is_constant (&offset))
+    return offset;
   return 0;
 }
 
@@ -673,7 +674,6 @@ static bool dataflow_set_different (dataflow_set *, dataflow_set *);
 static void dataflow_set_destroy (dataflow_set *);
 
 static bool track_expr_p (tree, bool);
-static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
 static void add_uses_1 (rtx *, void *);
 static void add_stores (rtx, const_rtx, void *);
 static bool compute_bb_dataflow (basic_block);
@@ -704,7 +704,6 @@ static void delete_variable_part (dataflow_set *, rtx,
 static void emit_notes_in_bb (basic_block, dataflow_set *);
 static void vt_emit_notes (void);
 
-static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
 static void vt_add_function_parameters (void);
 static bool vt_initialize (void);
 static void vt_finalize (void);
@@ -1850,6 +1849,32 @@ var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
   set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
 }
 
+/* Return true if we should track a location that is OFFSET bytes from
+   a variable.  Store the constant offset in *OFFSET_OUT if so.  */
+
+static bool
+track_offset_p (poly_int64 offset, HOST_WIDE_INT *offset_out)
+{
+  HOST_WIDE_INT const_offset;
+  if (!offset.is_constant (&const_offset)
+      || !IN_RANGE (const_offset, 0, MAX_VAR_PARTS - 1))
+    return false;
+  *offset_out = const_offset;
+  return true;
+}
+
+/* Return the offset of a register that track_offset_p says we
+   should track.  */
+
+static HOST_WIDE_INT
+get_tracked_reg_offset (rtx loc)
+{
+  HOST_WIDE_INT offset;
+  if (!track_offset_p (REG_OFFSET (loc), &offset))
+    gcc_unreachable ();
+  return offset;
+}
+
 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  */
 
 static void
@@ -1857,7 +1882,7 @@ var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
             rtx set_src)
 {
   tree decl = REG_EXPR (loc);
-  HOST_WIDE_INT offset = REG_OFFSET (loc);
+  HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
 
   var_reg_decl_set (set, loc, initialized,
                    dv_from_decl (decl), offset, set_src, INSERT);
@@ -1903,7 +1928,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
                        enum var_init_status initialized, rtx set_src)
 {
   tree decl = REG_EXPR (loc);
-  HOST_WIDE_INT offset = REG_OFFSET (loc);
+  HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
   attrs *node, *next;
   attrs **nextp;
 
@@ -1944,10 +1969,10 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
   attrs **nextp = &set->regs[REGNO (loc)];
   attrs *node, *next;
 
-  if (clobber)
+  HOST_WIDE_INT offset;
+  if (clobber && track_offset_p (REG_OFFSET (loc), &offset))
     {
       tree decl = REG_EXPR (loc);
-      HOST_WIDE_INT offset = REG_OFFSET (loc);
 
       decl = var_debug_decl (decl);
 
@@ -3497,6 +3522,12 @@ loc_cmp (rtx x, rtx y)
        else
          return 1;
 
+      case 'p':
+       r = compare_sizes_for_sort (SUBREG_BYTE (x), SUBREG_BYTE (y));
+       if (r != 0)
+         return r;
+       break;
+
       case 'V':
       case 'E':
        /* Compare the vector length first.  */
@@ -5177,20 +5208,20 @@ track_expr_p (tree expr, bool need_rtl)
              || (TREE_CODE (realdecl) == MEM_REF
                  && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
            {
-             HOST_WIDE_INT bitsize, bitpos, maxsize;
+             HOST_WIDE_INT bitsize, bitpos;
              bool reverse;
              tree innerdecl
-               = get_ref_base_and_extent (realdecl, &bitpos, &bitsize,
-                                          &maxsize, &reverse);
-             if (!DECL_P (innerdecl)
+               = get_ref_base_and_extent_hwi (realdecl, &bitpos,
+                                              &bitsize, &reverse);
+             if (!innerdecl
+                 || !DECL_P (innerdecl)
                  || DECL_IGNORED_P (innerdecl)
                  /* Do not track declarations for parts of tracked record
                     parameters since we want to track them as a whole.  */
                  || tracked_record_parameter_p (innerdecl)
                  || TREE_STATIC (innerdecl)
-                 || bitsize <= 0
-                 || bitpos + bitsize > 256
-                 || bitsize != maxsize)
+                 || bitsize == 0
+                 || bitpos + bitsize > 256)
                return 0;
              else
                realdecl = expr;
@@ -5232,7 +5263,7 @@ track_expr_p (tree expr, bool need_rtl)
          && !tracked_record_parameter_p (realdecl))
        return 0;
       if (MEM_SIZE_KNOWN_P (decl_rtl)
-         && MEM_SIZE (decl_rtl) > MAX_VAR_PARTS)
+         && maybe_gt (MEM_SIZE (decl_rtl), MAX_VAR_PARTS))
        return 0;
     }
 
@@ -5245,10 +5276,10 @@ track_expr_p (tree expr, bool need_rtl)
    EXPR+OFFSET.  */
 
 static bool
-same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
+same_variable_part_p (rtx loc, tree expr, poly_int64 offset)
 {
   tree expr2;
-  HOST_WIDE_INT offset2;
+  poly_int64 offset2;
 
   if (! DECL_P (expr))
     return false;
@@ -5272,7 +5303,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
   expr = var_debug_decl (expr);
   expr2 = var_debug_decl (expr2);
 
-  return (expr == expr2 && offset == offset2);
+  return (expr == expr2 && known_eq (offset, offset2));
 }
 
 /* LOC is a REG or MEM that we would like to track if possible.
@@ -5286,7 +5317,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
    from EXPR in *OFFSET_OUT (if nonnull).  */
 
 static bool
-track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
+track_loc_p (rtx loc, tree expr, poly_int64 offset, bool store_reg_p,
             machine_mode *mode_out, HOST_WIDE_INT *offset_out)
 {
   machine_mode mode;
@@ -5320,19 +5351,20 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
        || (store_reg_p
           && !COMPLEX_MODE_P (DECL_MODE (expr))
           && hard_regno_nregs (REGNO (loc), DECL_MODE (expr)) == 1))
-      && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
+      && known_eq (offset + byte_lowpart_offset (DECL_MODE (expr), mode), 0))
     {
       mode = DECL_MODE (expr);
       offset = 0;
     }
 
-  if (offset < 0 || offset >= MAX_VAR_PARTS)
+  HOST_WIDE_INT const_offset;
+  if (!track_offset_p (offset, &const_offset))
     return false;
 
   if (mode_out)
     *mode_out = mode;
   if (offset_out)
-    *offset_out = offset;
+    *offset_out = const_offset;
   return true;
 }
 
@@ -5343,7 +5375,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
 static rtx
 var_lowpart (machine_mode mode, rtx loc)
 {
-  unsigned int offset, reg_offset, regno;
+  unsigned int regno;
 
   if (GET_MODE (loc) == mode)
     return loc;
@@ -5351,12 +5383,12 @@ var_lowpart (machine_mode mode, rtx loc)
   if (!REG_P (loc) && !MEM_P (loc))
     return NULL;
 
-  offset = byte_lowpart_offset (mode, GET_MODE (loc));
+  poly_uint64 offset = byte_lowpart_offset (mode, GET_MODE (loc));
 
   if (MEM_P (loc))
     return adjust_address_nv (loc, mode, offset);
 
-  reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
+  poly_uint64 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
   regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
                                             reg_offset, mode);
   return gen_rtx_REG_offset (loc, mode, regno, offset);
@@ -9479,24 +9511,6 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
     }
 }
 
-/* Return BB's head, unless BB is the block that succeeds ENTRY_BLOCK,
-   in which case it searches back from BB's head for the very first
-   insn.  Use [get_first_insn (bb), BB_HEAD (bb->next_bb)[ as a range
-   to iterate over all insns of a function while iterating over its
-   BBs.  */
-
-static rtx_insn *
-get_first_insn (basic_block bb)
-{
-  rtx_insn *insn = BB_HEAD (bb);
-
-  if (bb->prev_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
-    while (rtx_insn *prev = PREV_INSN (insn))
-      insn = prev;
-
-  return insn;
-}
-
 /* Emit notes for the whole function.  */
 
 static void
@@ -9525,8 +9539,7 @@ vt_emit_notes (void)
     {
       /* Emit the notes for changes of variable locations between two
         subsequent basic blocks.  */
-      emit_notes_for_differences (get_first_insn (bb),
-                                 &cur, &VTI (bb)->in);
+      emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in);
 
       if (MAY_HAVE_DEBUG_BIND_INSNS)
        local_get_addr_cache = new hash_map<rtx, rtx>;
@@ -9561,7 +9574,7 @@ vt_emit_notes (void)
    assign declaration to *DECLP and offset to *OFFSETP, and return true.  */
 
 static bool
-vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
+vt_get_decl_and_offset (rtx rtl, tree *declp, poly_int64 *offsetp)
 {
   if (REG_P (rtl))
     {
@@ -9587,8 +9600,10 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
            decl = REG_EXPR (reg);
          if (REG_EXPR (reg) != decl)
            break;
-         if (REG_OFFSET (reg) < offset)
-           offset = REG_OFFSET (reg);
+         HOST_WIDE_INT this_offset;
+         if (!track_offset_p (REG_OFFSET (reg), &this_offset))
+           break;
+         offset = MIN (offset, this_offset);
        }
 
       if (i == len)
@@ -9632,7 +9647,7 @@ vt_add_function_parameter (tree parm)
   rtx incoming = DECL_INCOMING_RTL (parm);
   tree decl;
   machine_mode mode;
-  HOST_WIDE_INT offset;
+  poly_int64 offset;
   dataflow_set *out;
   decl_or_value dv;
 
@@ -9755,7 +9770,8 @@ vt_add_function_parameter (tree parm)
       offset = 0;
     }
 
-  if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
+  HOST_WIDE_INT const_offset;
+  if (!track_loc_p (incoming, parm, offset, false, &mode, &const_offset))
     return;
 
   out = &VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out;
@@ -9776,7 +9792,7 @@ vt_add_function_parameter (tree parm)
         arguments passed by invisible reference aren't dealt with
         above: incoming-rtl will have Pmode rather than the
         expected mode for the type.  */
-      if (offset)
+      if (const_offset)
        return;
 
       lowpart = var_lowpart (mode, incoming);
@@ -9791,7 +9807,7 @@ vt_add_function_parameter (tree parm)
       if (val)
        {
          preserve_value (val);
-         set_variable_part (out, val->val_rtx, dv, offset,
+         set_variable_part (out, val->val_rtx, dv, const_offset,
                             VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
          dv = dv_from_value (val->val_rtx);
        }
@@ -9812,9 +9828,9 @@ vt_add_function_parameter (tree parm)
     {
       incoming = var_lowpart (mode, incoming);
       gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
-      attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
+      attrs_list_insert (&out->regs[REGNO (incoming)], dv, const_offset,
                         incoming);
-      set_variable_part (out, incoming, dv, offset,
+      set_variable_part (out, incoming, dv, const_offset,
                         VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
       if (dv_is_value_p (dv))
        {
@@ -9845,17 +9861,19 @@ vt_add_function_parameter (tree parm)
       for (i = 0; i < XVECLEN (incoming, 0); i++)
        {
          rtx reg = XEXP (XVECEXP (incoming, 0, i), 0);
-         offset = REG_OFFSET (reg);
+         /* vt_get_decl_and_offset has already checked that the offset
+            is a valid variable part.  */
+         const_offset = get_tracked_reg_offset (reg);
          gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER);
-         attrs_list_insert (&out->regs[REGNO (reg)], dv, offset, reg);
-         set_variable_part (out, reg, dv, offset,
+         attrs_list_insert (&out->regs[REGNO (reg)], dv, const_offset, reg);
+         set_variable_part (out, reg, dv, const_offset,
                             VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
        }
     }
   else if (MEM_P (incoming))
     {
       incoming = var_lowpart (mode, incoming);
-      set_variable_part (out, incoming, dv, offset,
+      set_variable_part (out, incoming, dv, const_offset,
                         VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
     }
 }
@@ -9929,7 +9947,7 @@ vt_init_cfa_base (void)
 /* Reemit INSN, a MARKER_DEBUG_INSN, as a note.  */
 
 static rtx_insn *
-reemit_marker_as_note (rtx_insn *insn, basic_block *bb)
+reemit_marker_as_note (rtx_insn *insn)
 {
   gcc_checking_assert (DEBUG_MARKER_INSN_P (insn));
 
@@ -9944,8 +9962,6 @@ reemit_marker_as_note (rtx_insn *insn, basic_block *bb)
          {
            note = emit_note_before (kind, insn);
            NOTE_MARKER_LOCATION (note) = INSN_LOCATION (insn);
-           if (bb)
-             BLOCK_FOR_INSN (note) = *bb;
          }
        delete_insn (insn);
        return note;
@@ -10153,33 +10169,11 @@ vt_initialize (void)
          HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust;
          VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust;
 
-         /* If we are walking the first basic block, walk any HEADER
-            insns that might be before it too.  Unfortunately,
-            BB_HEADER and BB_FOOTER are not set while we run this
-            pass.  */
-         insn = get_first_insn (bb);
-         for (rtx_insn *next;
-              insn != BB_HEAD (bb->next_bb)
-                ? next = NEXT_INSN (insn), true : false;
-              insn = next)
+         rtx_insn *next;
+         FOR_BB_INSNS_SAFE (bb, insn, next)
            {
              if (INSN_P (insn))
                {
-                 basic_block save_bb = BLOCK_FOR_INSN (insn);
-                 if (!BLOCK_FOR_INSN (insn))
-                   {
-                     BLOCK_FOR_INSN (insn) = bb;
-                     gcc_assert (DEBUG_INSN_P (insn));
-                     /* Reset debug insns between basic blocks.
-                        Their location is not reliable, because they
-                        were probably not maintained up to date.  */
-                     if (DEBUG_BIND_INSN_P (insn))
-                       INSN_VAR_LOCATION_LOC (insn)
-                         = gen_rtx_UNKNOWN_VAR_LOC ();
-                   }
-                 else
-                   gcc_assert (BLOCK_FOR_INSN (insn) == bb);
-
                  if (!frame_pointer_needed)
                    {
                      insn_stack_adjust_offset_pre_post (insn, &pre, &post);
@@ -10201,7 +10195,7 @@ vt_initialize (void)
                  adjust_insn (bb, insn);
                  if (DEBUG_MARKER_INSN_P (insn))
                    {
-                     insn = reemit_marker_as_note (insn, &save_bb);
+                     reemit_marker_as_note (insn);
                      continue;
                    }
 
@@ -10253,7 +10247,6 @@ vt_initialize (void)
                            }
                        }
                    }
-                 BLOCK_FOR_INSN (insn) = save_bb;
                }
            }
          gcc_assert (offset == VTI (bb)->out.stack_adjust);
@@ -10295,15 +10288,12 @@ delete_vta_debug_insns (void)
 
   FOR_EACH_BB_FN (bb, cfun)
     {
-      for (insn = get_first_insn (bb);
-          insn != BB_HEAD (bb->next_bb)
-            ? next = NEXT_INSN (insn), true : false;
-          insn = next)
+      FOR_BB_INSNS_SAFE (bb, insn, next)
        if (DEBUG_INSN_P (insn))
          {
            if (DEBUG_MARKER_INSN_P (insn))
              {
-               insn = reemit_marker_as_note (insn, NULL);
+               reemit_marker_as_note (insn);
                continue;
              }
 
@@ -10332,12 +10322,9 @@ delete_vta_debug_insns (void)
    handled as well..  */
 
 static void
-vt_debug_insns_local (bool skipped)
+vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
 {
-  /* ??? Just skip it all for now.  If we skipped the global pass,
-     arrange for stmt markers to be dropped as well.  */
-  if (skipped)
-    cfun->debug_nonbind_markers = 0;
+  /* ??? Just skip it all for now.  */
   delete_vta_debug_insns ();
 }
 
@@ -10418,8 +10405,8 @@ variable_tracking_main_1 (void)
   if (!flag_var_tracking)
     return 0;
 
-  if (n_basic_blocks_for_fn (cfun) > 500 &&
-      n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20)
+  if (n_basic_blocks_for_fn (cfun) > 500
+      && n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20)
     {
       vt_debug_insns_local (true);
       return 0;
@@ -10439,8 +10426,6 @@ variable_tracking_main_1 (void)
     {
       vt_finalize ();
 
-      cfun->debug_nonbind_markers = 0;
-
       delete_vta_debug_insns ();
 
       /* This is later restored by our caller.  */