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 @@
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.
......
......@@ -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,23 +1212,21 @@ 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
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 (table)
{
int newlog = ADDR_VEC_ALIGN (table);
if (newlog != log)
{
log = newlog;
......@@ -1243,6 +1234,7 @@ shorten_branches (rtx_insn *first)
something_changed = 1;
}
}
}
#endif
if (log > insn_current_align)
......@@ -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
......
......@@ -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 */
......@@ -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)
......
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