Commit d305ca88 by Richard Sandiford Committed by Richard Sandiford

[59/77] Add a rtx_jump_table_data::get_data_mode helper

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
parent 2123a9a5
...@@ -2,6 +2,20 @@ ...@@ -2,6 +2,20 @@
Alan Hayward <alan.hayward@arm.com> Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@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 * combine.c (try_combine): Use is_a <scalar_int_mode> when
trying to combine a full-register integer set with a subreg trying to combine a full-register integer set with a subreg
integer set. integer set.
......
...@@ -219,9 +219,6 @@ static void leaf_renumber_regs (rtx_insn *); ...@@ -219,9 +219,6 @@ static void leaf_renumber_regs (rtx_insn *);
#if HAVE_cc0 #if HAVE_cc0
static int alter_cond (rtx); static int alter_cond (rtx);
#endif #endif
#ifndef ADDR_VEC_ALIGN
static int final_addr_vec_align (rtx_insn *);
#endif
static int align_fuzz (rtx, rtx, int, unsigned); static int align_fuzz (rtx, rtx, int, unsigned);
static void collect_fn_hard_reg_usage (void); static void collect_fn_hard_reg_usage (void);
static tree get_call_fndecl (rtx_insn *); static tree get_call_fndecl (rtx_insn *);
...@@ -518,9 +515,9 @@ default_jump_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED) ...@@ -518,9 +515,9 @@ default_jump_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
#ifndef ADDR_VEC_ALIGN #ifndef ADDR_VEC_ALIGN
static int 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) if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
align = BIGGEST_ALIGNMENT / BITS_PER_UNIT; align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
...@@ -937,45 +934,41 @@ shorten_branches (rtx_insn *first) ...@@ -937,45 +934,41 @@ shorten_branches (rtx_insn *first)
if (INSN_P (insn)) if (INSN_P (insn))
continue; 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. */ /* Merge in alignments computed by compute_alignments. */
log = LABEL_TO_ALIGNMENT (insn); log = LABEL_TO_ALIGNMENT (label);
if (max_log < log) if (max_log < log)
{ {
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); rtx_jump_table_data *table = jump_table_for_label (label);
next_is_jumptable = next && JUMP_TABLE_DATA_P (next); if (!table)
if (!next_is_jumptable)
{ {
log = LABEL_ALIGN (insn); log = LABEL_ALIGN (label);
if (max_log < log) if (max_log < log)
{ {
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 /* ADDR_VECs only take room if read-only data goes into the text
section. */ section. */
if ((JUMP_TABLES_IN_TEXT_SECTION if ((JUMP_TABLES_IN_TEXT_SECTION
|| readonly_data_section == 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) if (max_log < log)
{ {
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_ALIGNMENT (label) = max_log;
LABEL_TO_MAX_SKIP (insn) = max_skip; LABEL_TO_MAX_SKIP (label) = max_skip;
max_log = 0; max_log = 0;
max_skip = 0; max_skip = 0;
} }
...@@ -1131,7 +1124,7 @@ shorten_branches (rtx_insn *first) ...@@ -1131,7 +1124,7 @@ shorten_branches (rtx_insn *first)
continue; continue;
body = PATTERN (insn); 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 /* This only takes room if read-only data goes into the text
section. */ section. */
...@@ -1139,7 +1132,7 @@ shorten_branches (rtx_insn *first) ...@@ -1139,7 +1132,7 @@ shorten_branches (rtx_insn *first)
|| readonly_data_section == text_section) || readonly_data_section == text_section)
insn_lengths[uid] = (XVECLEN (body, insn_lengths[uid] = (XVECLEN (body,
GET_CODE (body) == ADDR_DIFF_VEC) 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. */ /* Alignment is handled by ADDR_VEC_ALIGN. */
} }
else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
...@@ -1219,28 +1212,27 @@ shorten_branches (rtx_insn *first) ...@@ -1219,28 +1212,27 @@ shorten_branches (rtx_insn *first)
uid = INSN_UID (insn); 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 #ifdef CASE_VECTOR_SHORTEN_MODE
/* If the mode of a following jump table was changed, we /* If the mode of a following jump table was changed, we
may need to update the alignment of this label. */ may need to update the alignment of this label. */
rtx_insn *next;
bool next_is_jumptable; if (JUMP_TABLES_IN_TEXT_SECTION
|| readonly_data_section == text_section)
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)
{ {
int newlog = ADDR_VEC_ALIGN (next); rtx_jump_table_data *table = jump_table_for_label (label);
if (newlog != log) if (table)
{ {
log = newlog; int newlog = ADDR_VEC_ALIGN (table);
LABEL_TO_ALIGNMENT (insn) = log; if (newlog != log)
something_changed = 1; {
log = newlog;
LABEL_TO_ALIGNMENT (insn) = log;
something_changed = 1;
}
} }
} }
#endif #endif
...@@ -1271,6 +1263,7 @@ shorten_branches (rtx_insn *first) ...@@ -1271,6 +1263,7 @@ shorten_branches (rtx_insn *first)
&& JUMP_TABLE_DATA_P (insn) && JUMP_TABLE_DATA_P (insn)
&& GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
{ {
rtx_jump_table_data *table = as_a <rtx_jump_table_data *> (insn);
rtx body = PATTERN (insn); rtx body = PATTERN (insn);
int old_length = insn_lengths[uid]; int old_length = insn_lengths[uid];
rtx_insn *rel_lab = rtx_insn *rel_lab =
...@@ -1366,13 +1359,14 @@ shorten_branches (rtx_insn *first) ...@@ -1366,13 +1359,14 @@ shorten_branches (rtx_insn *first)
max_addr - rel_addr, body); max_addr - rel_addr, body);
if (!increasing if (!increasing
|| (GET_MODE_SIZE (vec_mode) || (GET_MODE_SIZE (vec_mode)
>= GET_MODE_SIZE (GET_MODE (body)))) >= GET_MODE_SIZE (table->get_data_mode ())))
PUT_MODE (body, vec_mode); PUT_MODE (body, vec_mode);
if (JUMP_TABLES_IN_TEXT_SECTION if (JUMP_TABLES_IN_TEXT_SECTION
|| readonly_data_section == text_section) || readonly_data_section == text_section)
{ {
insn_lengths[uid] 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]; insn_current_address += insn_lengths[uid];
if (insn_lengths[uid] != old_length) if (insn_lengths[uid] != old_length)
something_changed = 1; something_changed = 1;
...@@ -2191,6 +2185,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, ...@@ -2191,6 +2185,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
rtx set; rtx set;
#endif #endif
rtx_insn *next; rtx_insn *next;
rtx_jump_table_data *table;
insn_counter++; insn_counter++;
...@@ -2448,11 +2443,11 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, ...@@ -2448,11 +2443,11 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
app_disable (); app_disable ();
next = next_nonnote_insn (insn);
/* If this label is followed by a jump-table, make sure we put /* If this label is followed by a jump-table, make sure we put
the label in the read-only section. Also possibly write the the label in the read-only section. Also possibly write the
label and jump table together. */ 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) #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
/* In this case, the case vector is being moved by the /* 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, ...@@ -2467,7 +2462,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
(current_function_decl)); (current_function_decl));
#ifdef ADDR_VEC_ALIGN #ifdef ADDR_VEC_ALIGN
log_align = ADDR_VEC_ALIGN (next); log_align = ADDR_VEC_ALIGN (table);
#else #else
log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
#endif #endif
...@@ -2477,8 +2472,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, ...@@ -2477,8 +2472,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
switch_to_section (current_function_section ()); switch_to_section (current_function_section ());
#ifdef ASM_OUTPUT_CASE_LABEL #ifdef ASM_OUTPUT_CASE_LABEL
ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), table);
next);
#else #else
targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
#endif #endif
......
...@@ -103,6 +103,11 @@ TYPE dyn_cast <TYPE> (pointer) ...@@ -103,6 +103,11 @@ TYPE dyn_cast <TYPE> (pointer)
Note that we have converted two sets of assertions in the calls to varpool Note that we have converted two sets of assertions in the calls to varpool
into safe and efficient use of a variable. 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 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 'missing symbol' error message for 'is_a_helper<....>::test', it means that
...@@ -222,4 +227,13 @@ dyn_cast (U *p) ...@@ -222,4 +227,13 @@ dyn_cast (U *p)
return static_cast <T> (0); 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 */ #endif /* GCC_IS_A_H */
...@@ -634,6 +634,7 @@ public: ...@@ -634,6 +634,7 @@ public:
This method gets the underlying vec. */ This method gets the underlying vec. */
inline rtvec get_labels () const; inline rtvec get_labels () const;
inline scalar_int_mode get_data_mode () const;
}; };
class GTY(()) rtx_barrier : public rtx_insn class GTY(()) rtx_barrier : public rtx_insn
...@@ -1477,6 +1478,24 @@ inline rtvec rtx_jump_table_data::get_labels () const ...@@ -1477,6 +1478,24 @@ inline rtvec rtx_jump_table_data::get_labels () const
return XVEC (pat, 1); /* presumably an ADDR_DIFF_VEC */ 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) \ #define RTX_FRAME_RELATED_P(RTX) \
(RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN, \ (RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN, \
CALL_INSN, JUMP_INSN, BARRIER, SET)->frame_related) CALL_INSN, JUMP_INSN, BARRIER, SET)->frame_related)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment