[59/77] Add a rtx_jump_table_data::get_data_mode helper
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 30 Aug 2017 11:18:37 +0000 (11:18 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 30 Aug 2017 11:18:37 +0000 (11:18 +0000)
This patch adds a helper function to get the mode of the addresses
or offsets in a jump table.  It also changes the final.c code to use
rtx_jump_table_data over rtx or rtx_insn in cases where it needed
to use the new helper.  This in turn meant adding a safe_dyn_cast
equivalent of safe_as_a, to cope with null NEXT_INSNs.

2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* is-a.h (safe_dyn_cast): New function.
* rtl.h (rtx_jump_table_data::get_data_mode): New function.
(jump_table_for_label): Likewise.
* final.c (final_addr_vec_align): Take an rtx_jump_table_data *
instead of an rtx_insn *.
(shorten_branches): Use dyn_cast instead of LABEL_P and
JUMP_TABLE_DATA_P.  Use jump_table_for_label and
rtx_jump_table_data::get_data_mode.
(final_scan_insn): Likewise.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r251511

gcc/ChangeLog
gcc/final.c
gcc/is-a.h
gcc/rtl.h

index 3fb54e6..612bd69 100644 (file)
@@ -2,6 +2,20 @@
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
 
+       * is-a.h (safe_dyn_cast): New function.
+       * rtl.h (rtx_jump_table_data::get_data_mode): New function.
+       (jump_table_for_label): Likewise.
+       * final.c (final_addr_vec_align): Take an rtx_jump_table_data *
+       instead of an rtx_insn *.
+       (shorten_branches): Use dyn_cast instead of LABEL_P and
+       JUMP_TABLE_DATA_P.  Use jump_table_for_label and
+       rtx_jump_table_data::get_data_mode.
+       (final_scan_insn): Likewise.
+
+2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
        * combine.c (try_combine): Use is_a <scalar_int_mode> when
        trying to combine a full-register integer set with a subreg
        integer set.
index be41d6e..8af1f17 100644 (file)
@@ -219,9 +219,6 @@ static void leaf_renumber_regs (rtx_insn *);
 #if HAVE_cc0
 static int alter_cond (rtx);
 #endif
-#ifndef ADDR_VEC_ALIGN
-static int final_addr_vec_align (rtx_insn *);
-#endif
 static int align_fuzz (rtx, rtx, int, unsigned);
 static void collect_fn_hard_reg_usage (void);
 static tree get_call_fndecl (rtx_insn *);
@@ -518,9 +515,9 @@ default_jump_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
 
 #ifndef ADDR_VEC_ALIGN
 static int
-final_addr_vec_align (rtx_insn *addr_vec)
+final_addr_vec_align (rtx_jump_table_data *addr_vec)
 {
-  int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec)));
+  int align = GET_MODE_SIZE (addr_vec->get_data_mode ());
 
   if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
     align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
@@ -937,45 +934,41 @@ shorten_branches (rtx_insn *first)
       if (INSN_P (insn))
        continue;
 
-      if (LABEL_P (insn))
+      if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
        {
-         rtx_insn *next;
-         bool next_is_jumptable;
-
          /* Merge in alignments computed by compute_alignments.  */
-         log = LABEL_TO_ALIGNMENT (insn);
+         log = LABEL_TO_ALIGNMENT (label);
          if (max_log < log)
            {
              max_log = log;
-             max_skip = LABEL_TO_MAX_SKIP (insn);
+             max_skip = LABEL_TO_MAX_SKIP (label);
            }
 
-         next = next_nonnote_insn (insn);
-         next_is_jumptable = next && JUMP_TABLE_DATA_P (next);
-         if (!next_is_jumptable)
+         rtx_jump_table_data *table = jump_table_for_label (label);
+         if (!table)
            {
-             log = LABEL_ALIGN (insn);
+             log = LABEL_ALIGN (label);
              if (max_log < log)
                {
                  max_log = log;
-                 max_skip = targetm.asm_out.label_align_max_skip (insn);
+                 max_skip = targetm.asm_out.label_align_max_skip (label);
                }
            }
          /* ADDR_VECs only take room if read-only data goes into the text
             section.  */
          if ((JUMP_TABLES_IN_TEXT_SECTION
               || readonly_data_section == text_section)
-             && next_is_jumptable)
+             && table)
            {
-             log = ADDR_VEC_ALIGN (next);
+             log = ADDR_VEC_ALIGN (table);
              if (max_log < log)
                {
                  max_log = log;
-                 max_skip = targetm.asm_out.label_align_max_skip (insn);
+                 max_skip = targetm.asm_out.label_align_max_skip (label);
                }
            }
-         LABEL_TO_ALIGNMENT (insn) = max_log;
-         LABEL_TO_MAX_SKIP (insn) = max_skip;
+         LABEL_TO_ALIGNMENT (label) = max_log;
+         LABEL_TO_MAX_SKIP (label) = max_skip;
          max_log = 0;
          max_skip = 0;
        }
@@ -1131,7 +1124,7 @@ shorten_branches (rtx_insn *first)
        continue;
 
       body = PATTERN (insn);
-      if (JUMP_TABLE_DATA_P (insn))
+      if (rtx_jump_table_data *table = dyn_cast <rtx_jump_table_data *> (insn))
        {
          /* This only takes room if read-only data goes into the text
             section.  */
@@ -1139,7 +1132,7 @@ shorten_branches (rtx_insn *first)
              || readonly_data_section == text_section)
            insn_lengths[uid] = (XVECLEN (body,
                                          GET_CODE (body) == ADDR_DIFF_VEC)
-                                * GET_MODE_SIZE (GET_MODE (body)));
+                                * GET_MODE_SIZE (table->get_data_mode ()));
          /* Alignment is handled by ADDR_VEC_ALIGN.  */
        }
       else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
@@ -1219,28 +1212,27 @@ shorten_branches (rtx_insn *first)
 
          uid = INSN_UID (insn);
 
-         if (LABEL_P (insn))
+         if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
            {
-             int log = LABEL_TO_ALIGNMENT (insn);
+             int log = LABEL_TO_ALIGNMENT (label);
 
 #ifdef CASE_VECTOR_SHORTEN_MODE
              /* If the mode of a following jump table was changed, we
                 may need to update the alignment of this label.  */
-             rtx_insn *next;
-             bool next_is_jumptable;
-
-             next = next_nonnote_insn (insn);
-             next_is_jumptable = next && JUMP_TABLE_DATA_P (next);
-             if ((JUMP_TABLES_IN_TEXT_SECTION
-                  || readonly_data_section == text_section)
-                 && next_is_jumptable)
+
+             if (JUMP_TABLES_IN_TEXT_SECTION
+                 || readonly_data_section == text_section)
                {
-                 int newlog = ADDR_VEC_ALIGN (next);
-                 if (newlog != log)
+                 rtx_jump_table_data *table = jump_table_for_label (label);
+                 if (table)
                    {
-                     log = newlog;
-                     LABEL_TO_ALIGNMENT (insn) = log;
-                     something_changed = 1;
+                     int newlog = ADDR_VEC_ALIGN (table);
+                     if (newlog != log)
+                       {
+                         log = newlog;
+                         LABEL_TO_ALIGNMENT (insn) = log;
+                         something_changed = 1;
+                       }
                    }
                }
 #endif
@@ -1271,6 +1263,7 @@ shorten_branches (rtx_insn *first)
              && JUMP_TABLE_DATA_P (insn)
              && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
            {
+             rtx_jump_table_data *table = as_a <rtx_jump_table_data *> (insn);
              rtx body = PATTERN (insn);
              int old_length = insn_lengths[uid];
              rtx_insn *rel_lab =
@@ -1366,13 +1359,14 @@ shorten_branches (rtx_insn *first)
                                                   max_addr - rel_addr, body);
              if (!increasing
                  || (GET_MODE_SIZE (vec_mode)
-                     >= GET_MODE_SIZE (GET_MODE (body))))
+                     >= GET_MODE_SIZE (table->get_data_mode ())))
                PUT_MODE (body, vec_mode);
              if (JUMP_TABLES_IN_TEXT_SECTION
                  || readonly_data_section == text_section)
                {
                  insn_lengths[uid]
-                   = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
+                   = (XVECLEN (body, 1)
+                      * GET_MODE_SIZE (table->get_data_mode ()));
                  insn_current_address += insn_lengths[uid];
                  if (insn_lengths[uid] != old_length)
                    something_changed = 1;
@@ -2191,6 +2185,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
   rtx set;
 #endif
   rtx_insn *next;
+  rtx_jump_table_data *table;
 
   insn_counter++;
 
@@ -2448,11 +2443,11 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 
       app_disable ();
 
-      next = next_nonnote_insn (insn);
       /* If this label is followed by a jump-table, make sure we put
         the label in the read-only section.  Also possibly write the
         label and jump table together.  */
-      if (next != 0 && JUMP_TABLE_DATA_P (next))
+      table = jump_table_for_label (as_a <rtx_code_label *> (insn));
+      if (table)
        {
 #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
          /* In this case, the case vector is being moved by the
@@ -2467,7 +2462,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
                                 (current_function_decl));
 
 #ifdef ADDR_VEC_ALIGN
-             log_align = ADDR_VEC_ALIGN (next);
+             log_align = ADDR_VEC_ALIGN (table);
 #else
              log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
 #endif
@@ -2477,8 +2472,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
            switch_to_section (current_function_section ());
 
 #ifdef ASM_OUTPUT_CASE_LABEL
-         ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
-                                next);
+         ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), table);
 #else
          targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
 #endif
index b4e5279..2adc740 100644 (file)
@@ -103,6 +103,11 @@ TYPE dyn_cast <TYPE> (pointer)
     Note that we have converted two sets of assertions in the calls to varpool
     into safe and efficient use of a variable.
 
+TYPE safe_dyn_cast <TYPE> (pointer)
+
+    Like dyn_cast <TYPE> (pointer), except that it accepts null pointers
+    and returns null results for them.
+
 
 If you use these functions and get a 'inline function not defined' or a
 'missing symbol' error message for 'is_a_helper<....>::test', it means that
@@ -222,4 +227,13 @@ dyn_cast (U *p)
     return static_cast <T> (0);
 }
 
+/* Similar to dyn_cast, except that the pointer may be null.  */
+
+template <typename T, typename U>
+inline T
+safe_dyn_cast (U *p)
+{
+  return p ? dyn_cast <T> (p) : 0;
+}
+
 #endif  /* GCC_IS_A_H  */
index 8f4c1fa..736134f 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -634,6 +634,7 @@ public:
      This method gets the underlying vec.  */
 
   inline rtvec get_labels () const;
+  inline scalar_int_mode get_data_mode () const;
 };
 
 class GTY(()) rtx_barrier : public rtx_insn
@@ -1477,6 +1478,24 @@ inline rtvec rtx_jump_table_data::get_labels () const
     return XVEC (pat, 1); /* presumably an ADDR_DIFF_VEC */
 }
 
+/* Return the mode of the data in the table, which is always a scalar
+   integer.  */
+
+inline scalar_int_mode
+rtx_jump_table_data::get_data_mode () const
+{
+  return as_a <scalar_int_mode> (GET_MODE (PATTERN (this)));
+}
+
+/* If LABEL is followed by a jump table, return the table, otherwise
+   return null.  */
+
+inline rtx_jump_table_data *
+jump_table_for_label (const rtx_code_label *label)
+{
+  return safe_dyn_cast <rtx_jump_table_data *> (NEXT_INSN (label));
+}
+
 #define RTX_FRAME_RELATED_P(RTX)                                       \
   (RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN,    \
                    CALL_INSN, JUMP_INSN, BARRIER, SET)->frame_related)