/* Convert RTL to assembler code and output it, for GNU compiler.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
#include "varasm.h"
#include "hard-reg-set.h"
#include "toplev.h" /* exact_log2, floor_log2 */
#include "reload.h"
#include "intl.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
#include "basic-block.h"
#include "target.h"
#include "targhooks.h"
#include "debug.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
#include "tree-pass.h"
#include "cgraph.h"
#include "tree-ssa.h"
#include "coverage.h"
#include "df.h"
-#include "ggc.h"
#include "cfgloop.h"
#include "params.h"
#include "tree-pretty-print.h" /* for dump_function_header */
/* Nonzero while outputting an `asm' with operands.
This means that inconsistencies are the user's fault, so don't die.
The precise value is the insn being output, to pass to error_for_asm. */
-rtx this_is_asm_operands;
+const rtx_insn *this_is_asm_operands;
/* Number of operands of this insn, for an `asm' with operands. */
static unsigned int insn_noperands;
static int insn_counter = 0;
-#ifdef HAVE_cc0
/* This variable contains machine-dependent flags (defined in tm.h)
set and examined by output routines
that describe how to interpret the condition codes properly. */
from before the insn. */
CC_STATUS cc_prev_status;
-#endif
/* Number of unmatched NOTE_INSN_BLOCK_BEG notes we have seen. */
#ifdef LEAF_REGISTERS
static void leaf_renumber_regs (rtx_insn *);
#endif
-#ifdef HAVE_cc0
+#if HAVE_cc0
static int alter_cond (rtx);
#endif
#ifndef ADDR_VEC_ALIGN
get its actual length. Otherwise, use FALLBACK_FN to calculate the
length. */
static int
-get_attr_length_1 (rtx uncast_insn, int (*fallback_fn) (rtx))
+get_attr_length_1 (rtx_insn *insn, int (*fallback_fn) (rtx_insn *))
{
- rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
rtx body;
int i;
int length = 0;
/* Obtain the current length of an insn. If branch shortening has been done,
get its actual length. Otherwise, get its maximum length. */
int
-get_attr_length (rtx insn)
+get_attr_length (rtx_insn *insn)
{
return get_attr_length_1 (insn, insn_default_length);
}
/* Obtain the current length of an insn. If branch shortening has been done,
get its actual length. Otherwise, get its minimum length. */
int
-get_attr_min_length (rtx insn)
+get_attr_min_length (rtx_insn *insn)
{
return get_attr_length_1 (insn, insn_min_length);
}
#endif
int
-default_label_align_after_barrier_max_skip (rtx insn ATTRIBUTE_UNUSED)
+default_label_align_after_barrier_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
{
return 0;
}
int
-default_loop_align_max_skip (rtx insn ATTRIBUTE_UNUSED)
+default_loop_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
{
return align_loops_max_skip;
}
int
-default_label_align_max_skip (rtx insn ATTRIBUTE_UNUSED)
+default_label_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
{
return align_labels_max_skip;
}
int
-default_jump_align_max_skip (rtx insn ATTRIBUTE_UNUSED)
+default_jump_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
{
return align_jumps_max_skip;
}
int
insn_current_reference_address (rtx_insn *branch)
{
- rtx dest, seq;
+ rtx dest;
int seq_uid;
if (! INSN_ADDRESSES_SET_P ())
return 0;
- seq = NEXT_INSN (PREV_INSN (branch));
+ rtx_insn *seq = NEXT_INSN (PREV_INSN (branch));
seq_uid = INSN_UID (seq);
if (!JUMP_P (branch))
/* This can happen for example on the PA; the objective is to know the
#endif /* CASE_VECTOR_SHORTEN_MODE */
/* Compute initial lengths, addresses, and varying flags for each insn. */
- int (*length_fun) (rtx) = increasing ? insn_min_length : insn_default_length;
+ int (*length_fun) (rtx_insn *) = increasing ? insn_min_length : insn_default_length;
for (insn_current_address = 0, insn = first;
insn != 0;
if (NOTE_P (insn) || BARRIER_P (insn)
|| LABEL_P (insn) || DEBUG_INSN_P (insn))
continue;
- if (INSN_DELETED_P (insn))
+ if (insn->deleted ())
continue;
body = PATTERN (insn);
#else
const_delay_slots = 0;
#endif
- int (*inner_length_fun) (rtx)
+ int (*inner_length_fun) (rtx_insn *)
= const_delay_slots ? length_fun : insn_default_length;
/* Inside a delay slot sequence, we do not do any branch shortening
if the shortening could change the number of delay slots
rtx_insn *prev;
int rel_align = 0;
addr_diff_vec_flags flags;
- enum machine_mode vec_mode;
+ machine_mode vec_mode;
/* Avoid automatic aggregate initialization. */
flags = ADDR_DIFF_VEC_FLAGS (body);
if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
{
+ rtx_sequence *seqn = as_a <rtx_sequence *> (PATTERN (insn));
int i;
body = PATTERN (insn);
new_length = 0;
- for (i = 0; i < XVECLEN (body, 0); i++)
+ for (i = 0; i < seqn->len (); i++)
{
- rtx inner_insn = XVECEXP (body, 0, i);
+ rtx_insn *inner_insn = seqn->insn (i);
int inner_uid = INSN_UID (inner_insn);
int inner_length;
if (bb->frequency)
fprintf (file, " freq:%d", bb->frequency);
if (bb->count)
- fprintf (file, " count:%"PRId64,
+ fprintf (file, " count:%" PRId64,
bb->count);
fprintf (file, " seq:%d", (*bb_seqn)++);
fprintf (file, "\n%s PRED:", ASM_COMMENT_START);
last_ignored_compare = 0;
-#ifdef HAVE_cc0
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- /* If CC tracking across branches is enabled, record the insn which
- jumps to each branch only reached from one place. */
- if (optimize_p && JUMP_P (insn))
- {
- rtx lab = JUMP_LABEL (insn);
- if (lab && LABEL_P (lab) && LABEL_NUSES (lab) == 1)
- {
- LABEL_REFS (lab) = insn;
- }
- }
- }
-#endif
+ if (HAVE_cc0)
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ /* If CC tracking across branches is enabled, record the insn which
+ jumps to each branch only reached from one place. */
+ if (optimize_p && JUMP_P (insn))
+ {
+ rtx lab = JUMP_LABEL (insn);
+ if (lab && LABEL_P (lab) && LABEL_NUSES (lab) == 1)
+ {
+ LABEL_REFS (lab) = insn;
+ }
+ }
+ }
init_recog ();
final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
int nopeepholes ATTRIBUTE_UNUSED, int *seen)
{
-#ifdef HAVE_cc0
+#if HAVE_cc0
rtx set;
#endif
rtx_insn *next;
/* Ignore deleted insns. These can occur when we split insns (due to a
template of "#") while not optimizing. */
- if (INSN_DELETED_P (insn))
+ if (insn->deleted ())
return NEXT_INSN (insn);
switch (GET_CODE (insn))
switch (NOTE_KIND (insn))
{
case NOTE_INSN_DELETED:
+ case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
break;
case NOTE_INSN_SWITCH_TEXT_SECTIONS:
suffixing "cold" to the original function's name. */
if (in_cold_section_p)
{
- tree cold_function_name
+ cold_function_name
= clone_function_name (current_function_decl, "cold");
+#ifdef ASM_DECLARE_COLD_FUNCTION_NAME
+ ASM_DECLARE_COLD_FUNCTION_NAME (asm_out_file,
+ IDENTIFIER_POINTER
+ (cold_function_name),
+ current_function_decl);
+#else
ASM_OUTPUT_LABEL (asm_out_file,
IDENTIFIER_POINTER (cold_function_name));
+#endif
}
break;
|| GET_CODE (body) == CLOBBER)
break;
-#ifdef HAVE_cc0
+#if HAVE_cc0
{
/* If there is a REG_CC_SETTER note on this insn, it means that
the setting of the condition code was done in the delay slot
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
if (note)
{
- NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
+ rtx_insn *other = as_a <rtx_insn *> (XEXP (note, 0));
+ NOTICE_UPDATE_CC (PATTERN (other), other);
cc_prev_status = cc_status;
}
}
body = PATTERN (insn);
-#ifdef HAVE_cc0
+#if HAVE_cc0
set = single_set (insn);
/* Check for redundant test and compare instructions
#endif
-#ifdef HAVE_peephole
/* Do machine-specific peephole optimizations if desired. */
- if (optimize_p && !flag_no_peephole && !nopeepholes)
+ if (HAVE_peephole && optimize_p && !flag_no_peephole && !nopeepholes)
{
rtx_insn *next = peephole (insn);
/* When peepholing, if there were notes within the peephole,
/* PEEPHOLE might have changed this. */
body = PATTERN (insn);
}
-#endif
/* Try to recognize the instruction.
If successful, verify that the operands satisfy the
print_rtx_head = "";
}
- if (! constrain_operands_cached (1))
+ if (! constrain_operands_cached (insn, 1))
fatal_insn_not_found (insn);
/* Some target machines need to prescan each insn before
&& GET_CODE (PATTERN (insn)) == COND_EXEC)
current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
-#ifdef HAVE_cc0
+#if HAVE_cc0
cc_prev_status = cc_status;
/* Update `cc_status' for this instruction.
directly to the desired hard register. */
void
-cleanup_subreg_operands (rtx insn)
+cleanup_subreg_operands (rtx_insn *insn)
{
int i;
bool changed = false;
*recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i], &changed);
}
if (changed)
- df_insn_rescan (as_a <rtx_insn *> (insn));
+ df_insn_rescan (insn);
}
/* If X is a SUBREG, try to replace it with a REG or a MEM, based on
else
*xp = adjust_address_nv (y, GET_MODE (x), offset);
}
- else
+ else if (REG_P (y) && HARD_REGISTER_P (y))
{
rtx new_rtx = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
SUBREG_BYTE (x));
return *xp;
}
\f
-#ifdef HAVE_cc0
+#if HAVE_cc0
/* Given BODY, the body of a jump instruction, alter the jump condition
as required by the bits that are set in cc_status.flags.
va_start (ap, cmsgid);
pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: ";
- asprintf (&fmt_string, "%s%s", pfx_str, _(cmsgid));
- vasprintf (&new_message, fmt_string, ap);
+ fmt_string = xasprintf ("%s%s", pfx_str, _(cmsgid));
+ new_message = xvasprintf (fmt_string, ap);
if (this_is_asm_operands)
error_for_asm (this_is_asm_operands, "%s", new_message);
char buf[256];
if (GET_CODE (x) == LABEL_REF)
- x = XEXP (x, 0);
+ x = LABEL_REF_LABEL (x);
if (LABEL_P (x)
|| (NOTE_P (x)
&& NOTE_KIND (x) == NOTE_INSN_DELETED_LABEL))
x = alter_subreg (&x, true);
/* X must not be a pseudo reg. */
- gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
+ if (!targetm.no_register_allocation)
+ gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
targetm.asm_out.print_operand (asm_out_file, x, code);
break;
case LABEL_REF:
- x = XEXP (x, 0);
+ x = LABEL_REF_LABEL (x);
/* Fall through. */
case CODE_LABEL:
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
int
sprint_ul (char *s, unsigned long value)
{
- int len;
- char tmp_c;
- int i;
- int j;
-
- len = sprint_ul_rev (s, value);
+ int len = sprint_ul_rev (s, value);
s[len] = '\0';
- /* Reverse the string. */
- i = 0;
- j = len - 1;
- while (i < j)
- {
- tmp_c = s[i];
- s[i] = s[j];
- s[j] = tmp_c;
- i++; j--;
- }
-
+ std::reverse (s, s + len);
return len;
}
df_set_regs_ever_live (newreg, true);
SET_REGNO (in_rtx, newreg);
in_rtx->used = 1;
+ return;
}
if (INSN_P (in_rtx))
static unsigned int
rest_of_handle_final (void)
{
- rtx x;
- const char *fnname;
-
- /* Get the function's name, as described by its RTL. This may be
- different from the DECL_NAME name used in the source file. */
-
- x = DECL_RTL (current_function_decl);
- gcc_assert (MEM_P (x));
- x = XEXP (x, 0);
- gcc_assert (GET_CODE (x) == SYMBOL_REF);
- fnname = XSTR (x, 0);
+ const char *fnname = get_fnname_from_decl (current_function_decl);
assemble_start_function (current_function_decl, fnname);
final_start_function (get_insns (), asm_out_file, optimize);
final (get_insns (), asm_out_file, optimize);
- if (flag_use_caller_save)
+ if (flag_ipa_ra)
collect_fn_hard_reg_usage ();
final_end_function ();
in REG_SET. Return DEFAULT_SET in REG_SET if not found. */
bool
-get_call_reg_set_usage (rtx uncast_insn, HARD_REG_SET *reg_set,
+get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set,
HARD_REG_SET default_set)
{
- rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
- if (flag_use_caller_save)
+ if (flag_ipa_ra)
{
struct cgraph_rtl_info *node = get_call_cgraph_rtl_info (insn);
if (node != NULL