/* Graph coloring register allocator
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
Contributed by Michael Matz <matz@suse.de>
and Daniel Berlin <dan@cgsoftware.com>.
#include "recog.h"
#include "function.h"
#include "hard-reg-set.h"
-#include "basic-block.h"
+#include "regs.h"
#include "df.h"
#include "output.h"
#include "ra.h"
/* This file contains various dumping and debug functions for
the graph coloring register allocator. */
-static void ra_print_rtx_1op PARAMS ((FILE *, rtx));
-static void ra_print_rtx_2op PARAMS ((FILE *, rtx));
-static void ra_print_rtx_3op PARAMS ((FILE *, rtx));
-static void ra_print_rtx_object PARAMS ((FILE *, rtx));
+static void ra_print_rtx_1op (FILE *, rtx);
+static void ra_print_rtx_2op (FILE *, rtx);
+static void ra_print_rtx_3op (FILE *, rtx);
+static void ra_print_rtx_object (FILE *, rtx);
/* The hardregs as names, for debugging. */
static const char *const reg_class_names[] = REG_CLASS_NAMES;
have any bits in common. */
void
-ra_debug_msg VPARAMS ((unsigned int level, const char *format, ...))
+ra_debug_msg (unsigned int level, const char *format, ...)
{
- VA_OPEN (ap, format);
- VA_FIXEDARG (ap, unsigned int, level);
- VA_FIXEDARG (ap, const char *, format);
- if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
- vfprintf (rtl_dump_file, format, ap);
- VA_CLOSE (ap);
+ va_list ap;
+
+ va_start (ap, format);
+ if ((debug_new_regalloc & level) != 0 && dump_file != NULL)
+ vfprintf (dump_file, format, ap);
+ va_end (ap);
}
"op(Y)" to FILE. */
static void
-ra_print_rtx_1op (file, x)
- FILE *file;
- rtx x;
+ra_print_rtx_1op (FILE *file, rtx x)
{
enum rtx_code code = GET_CODE (x);
rtx op0 = XEXP (x, 0);
to FILE. */
static void
-ra_print_rtx_2op (file, x)
- FILE *file;
- rtx x;
+ra_print_rtx_2op (FILE *file, rtx x)
{
int infix = 1;
const char *opname = "shitop";
case AND: opname = "&"; break;
case IOR: opname = "|"; break;
case XOR: opname = "^"; break;
- /* class '<' */
+ /* class '=' */
case NE: opname = "!="; break;
case EQ: opname = "=="; break;
+ case LTGT: opname = "<>"; break;
+ /* class '<' */
case GE: opname = "s>="; break;
case GT: opname = "s>"; break;
case LE: opname = "s<="; break;
I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
static void
-ra_print_rtx_3op (file, x)
- FILE *file;
- rtx x;
+ra_print_rtx_3op (FILE *file, rtx x)
{
enum rtx_code code = GET_CODE (x);
rtx op0 = XEXP (x, 0);
}
}
-/* Print rtx X, which represents an object (class 'o' or some constructs
+/* Print rtx X, which represents an object (class 'o', 'C', or some constructs
of class 'x' (e.g. subreg)), to FILE.
(reg XX) rtl is represented as "pXX", of XX was a pseudo,
as "name" it name is the nonnull hardreg name, or as "hXX", if XX
is a hardreg, whose name is NULL, or empty. */
static void
-ra_print_rtx_object (file, x)
- FILE *file;
- rtx x;
+ra_print_rtx_object (FILE *file, rtx x)
{
enum rtx_code code = GET_CODE (x);
enum machine_mode mode = GET_MODE (x);
int regno = REGNO (x);
if (regno < FIRST_PSEUDO_REGISTER)
{
- int i, nregs = HARD_REGNO_NREGS (regno, mode);
+ int i, nregs = hard_regno_nregs[regno][mode];
if (nregs > 1)
fputs ("[", file);
for (i = 0; i < nregs; i++)
{
rtx sub = SUBREG_REG (x);
int ofs = SUBREG_BYTE (x);
- if (GET_CODE (sub) == REG
+ if (REG_P (sub)
&& REGNO (sub) < FIRST_PSEUDO_REGISTER)
{
int regno = REGNO (sub);
- int i, nregs = HARD_REGNO_NREGS (regno, mode);
+ int i, nregs = hard_regno_nregs[regno][mode];
regno += subreg_regno_offset (regno, GET_MODE (sub),
ofs, mode);
if (nregs > 1)
case LABEL_REF:
{
rtx sub = XEXP (x, 0);
- if (GET_CODE (sub) == NOTE
+ if (NOTE_P (sub)
&& NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
- else if (GET_CODE (sub) == CODE_LABEL)
+ else if (LABEL_P (sub))
fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
else
fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
the preceding and following insn. */
void
-ra_print_rtx (file, x, with_pn)
- FILE *file;
- rtx x;
- int with_pn;
+ra_print_rtx (FILE *file, rtx x, int with_pn)
{
enum rtx_code code;
- char class;
int unhandled = 0;
if (!x)
return;
code = GET_CODE (x);
- class = GET_RTX_CLASS (code);
/* First handle the insn like constructs. */
if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
else
{
- fprintf (file, " line %d", ln);
- if (NOTE_SOURCE_FILE (x))
- fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
+ expanded_location s;
+ NOTE_EXPANDED_LOCATION (s, x);
+ fprintf (file, " line %d", s.line);
+ if (s.file != NULL)
+ fprintf (file, ":%s", s.file);
}
}
else
}
if (!unhandled)
return;
- if (class == '1')
- ra_print_rtx_1op (file, x);
- else if (class == '2' || class == 'c' || class == '<')
- ra_print_rtx_2op (file, x);
- else if (class == '3' || class == 'b')
- ra_print_rtx_3op (file, x);
- else if (class == 'o')
- ra_print_rtx_object (file, x);
- else
- print_inline_rtx (file, x, 0);
+ switch (GET_RTX_CLASS (code))
+ {
+ case RTX_UNARY:
+ ra_print_rtx_1op (file, x);
+ break;
+ case RTX_BIN_ARITH:
+ case RTX_COMM_ARITH:
+ case RTX_COMPARE:
+ case RTX_COMM_COMPARE:
+ ra_print_rtx_2op (file, x);
+ break;
+ case RTX_TERNARY:
+ case RTX_BITFIELD_OPS:
+ ra_print_rtx_3op (file, x);
+ break;
+ case RTX_OBJ:
+ case RTX_CONST_OBJ:
+ ra_print_rtx_object (file, x);
+ break;
+ default:
+ print_inline_rtx (file, x, 0);
+ break;
+ }
}
/* This only calls ra_print_rtx(), but emits a final newline. */
void
-ra_print_rtx_top (file, x, with_pn)
- FILE *file;
- rtx x;
- int with_pn;
+ra_print_rtx_top (FILE *file, rtx x, int with_pn)
{
ra_print_rtx (file, x, with_pn);
fprintf (file, "\n");
/* Callable from gdb. This prints rtx X onto stderr. */
void
-ra_debug_rtx (x)
- rtx x;
+ra_debug_rtx (rtx x)
{
ra_print_rtx_top (stderr, x, 1);
}
The first and last insn are emitted with UIDs of prev and next insns. */
void
-ra_debug_bbi (bbi)
- int bbi;
+ra_debug_bbi (int bbi)
{
basic_block bb = BASIC_BLOCK (bbi);
rtx insn;
- for (insn = bb->head; insn; insn = NEXT_INSN (insn))
+ for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
{
- ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
+ ra_print_rtx_top (stderr, insn,
+ (insn == BB_HEAD (bb) || insn == BB_END (bb)));
fprintf (stderr, "\n");
- if (insn == bb->end)
+ if (insn == BB_END (bb))
break;
}
}
or emit a window of NUM insns around INSN, to stderr. */
void
-ra_debug_insns (insn, num)
- rtx insn;
- int num;
+ra_debug_insns (rtx insn, int num)
{
int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
if (num < 0)
insn = PREV_INSN (insn);
for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
{
- if (GET_CODE (insn) == CODE_LABEL)
+ if (LABEL_P (insn))
fprintf (stderr, "\n");
ra_print_rtx_top (stderr, insn, (i == count || i == 1));
}
some notes, if flag_ra_dump_notes is zero. */
void
-ra_print_rtl_with_bb (file, insn)
- FILE *file;
- rtx insn;
+ra_print_rtl_with_bb (FILE *file, rtx insn)
{
basic_block last_bb, bb;
unsigned int num = 0;
last_bb = NULL;
for (; insn; insn = NEXT_INSN (insn))
{
- if (GET_CODE (insn) == BARRIER)
+ if (BARRIER_P (insn))
bb = NULL;
else
bb = BLOCK_FOR_INSN (insn);
fprintf (file, ";; Begin of basic block %d\n", bb->index);
last_bb = bb;
}
- if (GET_CODE (insn) == CODE_LABEL)
+ if (LABEL_P (insn))
fputc ('\n', file);
- if (GET_CODE (insn) == NOTE)
+ if (NOTE_P (insn))
{
/* Ignore basic block and maybe other notes not referencing
deleted things. */
graph, and prints the findings. */
void
-dump_number_seen ()
+dump_number_seen (void)
{
#define N 17
int num[N];
/* Dump the interference graph, the move list and the webs. */
void
-dump_igraph (df)
- struct df *df ATTRIBUTE_UNUSED;
+dump_igraph (struct df *df ATTRIBUTE_UNUSED)
{
struct move_list *ml;
unsigned int def1, def2;
int num = 0;
int num2;
unsigned int i;
- if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
+ if (!dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
return;
ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
for (def1 = 0; def1 < num_webs; def1++)
{
int num1 = num;
- for (num2=0, def2 = 0; def2 < num_webs; def2++)
+ num2 = 0;
+ for (def2 = 0; def2 < num_webs; def2++)
if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
{
if (num1 == num)
ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
}
- ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost ",
- web->add_hardregs, web->span_deaths);
- ra_debug_msg (DUMP_WEBS, HOST_WIDE_INT_PRINT_DEC, web->spill_cost);
- ra_debug_msg (DUMP_WEBS, ") (%s)", reg_class_names[web->regclass]);
+ ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
+ HOST_WIDE_INT_PRINT_DEC ") (%s)",
+ web->add_hardregs, web->span_deaths, web->spill_cost,
+ reg_class_names[web->regclass]);
if (web->spill_temp == 1)
ra_debug_msg (DUMP_WEBS, " (spilltemp)");
else if (web->spill_temp == 2)
to my custom graph colorizer. */
void
-dump_igraph_machine ()
+dump_igraph_machine (void)
{
unsigned int i;
- if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
+ if (!dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
return;
ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
FIRST_PSEUDO_REGISTER);
and emits information, if the resulting insns are strictly valid. */
void
-dump_constraints ()
+dump_constraints (void)
{
rtx insn;
int i;
- if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
+ if (!dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
return;
for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
- if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
+ if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
REGNO (regno_reg_rtx[i])
= ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
ra_debug_msg (DUMP_CONSTRAINTS, "\n");
}
for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
- if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
+ if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
REGNO (regno_reg_rtx[i]) = i;
}
preceded by a custom message MSG, with debug level LEVEL. */
void
-dump_graph_cost (level, msg)
- unsigned int level;
- const char *msg;
+dump_graph_cost (unsigned int level, const char *msg)
{
unsigned int i;
unsigned HOST_WIDE_INT cost;
- if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
+ if (!dump_file || (debug_new_regalloc & level) == 0)
return;
cost = 0;
if (alias (web)->type == SPILLED)
cost += web->orig_spill_cost;
}
- ra_debug_msg (level, " spill cost of graph (%s) = ", msg ? msg : "");
- ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, cost);
- ra_debug_msg (level, "\n");
+ ra_debug_msg (level, " spill cost of graph (%s) = "
+ HOST_WIDE_INT_PRINT_UNSIGNED "\n",
+ msg ? msg : "", cost);
}
/* Dump the color assignment per web, the coalesced and spilled webs. */
void
-dump_ra (df)
- struct df *df ATTRIBUTE_UNUSED;
+dump_ra (struct df *df ATTRIBUTE_UNUSED)
{
struct web *web;
struct dlist *d;
- if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
+ if (!dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
return;
ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
(loads, stores and copies). */
void
-dump_static_insn_cost (file, message, prefix)
- FILE *file;
- const char *message;
- const char *prefix;
+dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
{
struct cost
{
{
unsigned HOST_WIDE_INT block_cost = bb->frequency;
rtx insn, set;
- for (insn = bb->head; insn; insn = NEXT_INSN (insn))
+ for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
{
/* Yes, yes. We don't calculate the costs precisely.
Only for "simple enough" insns. Those containing single
if (rtx_equal_p (src, dest))
pcost = &selfcopy;
else if (GET_CODE (src) == GET_CODE (dest)
- && ((GET_CODE (src) == REG)
+ && ((REG_P (src))
|| (GET_CODE (src) == SUBREG
- && GET_CODE (SUBREG_REG (src)) == REG
- && GET_CODE (SUBREG_REG (dest)) == REG)))
+ && REG_P (SUBREG_REG (src))
+ && REG_P (SUBREG_REG (dest)))))
+ /* XXX is dest guaranteed to be a subreg? */
pcost = ®copy;
else
{
src = SUBREG_REG (src);
if (GET_CODE (dest) == SUBREG)
dest = SUBREG_REG (dest);
- if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
+ if (MEM_P (src) && !MEM_P (dest)
&& memref_is_stack_slot (src))
pcost = &load;
- else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
+ else if (!MEM_P (src) && MEM_P (dest)
&& memref_is_stack_slot (dest))
pcost = &store;
}
pcost->count++;
}
}
- if (insn == bb->end)
+ if (insn == BB_END (bb))
break;
}
}
if (!prefix)
prefix = "";
fprintf (file, "static insn cost %s\n", message ? message : "");
- fprintf (file, " %soverall:\tnum=%6d\tcost=", prefix, overall.count);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, overall.cost);
- fprintf (file, "\n");
- fprintf (file, " %sloads:\tnum=%6d\tcost=", prefix, load.count);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, load.cost);
- fprintf (file, "\n");
- fprintf (file, " %sstores:\tnum=%6d\tcost=", prefix, store.count);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, store.cost);
- fprintf (file, "\n");
- fprintf (file, " %sregcopy:\tnum=%6d\tcost=", prefix, regcopy.count);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, regcopy.cost);
- fprintf (file, "\n");
- fprintf (file, " %sselfcpy:\tnum=%6d\tcost=", prefix, selfcopy.count);
- fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, selfcopy.cost);
- fprintf (file, "\n");
+ fprintf (file, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
+ prefix, overall.count, overall.cost);
+ fprintf (file, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
+ prefix, load.count, load.cost);
+ fprintf (file, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
+ prefix, store.count, store.cost);
+ fprintf (file, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
+ prefix, regcopy.count, regcopy.cost);
+ fprintf (file, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
+ prefix, selfcopy.count, selfcopy.cost);
}
/* Returns nonzero, if WEB1 and WEB2 have some possible
hardregs in common. */
int
-web_conflicts_p (web1, web2)
- struct web *web1;
- struct web *web2;
+web_conflicts_p (struct web *web1, struct web *web2)
{
if (web1->type == PRECOLORED && web2->type == PRECOLORED)
return 0;
/* Dump all uids of insns in which WEB is mentioned. */
void
-dump_web_insns (web)
- struct web *web;
+dump_web_insns (struct web *web)
{
unsigned int i;
/* Dump conflicts for web WEB. */
void
-dump_web_conflicts (web)
- struct web *web;
+dump_web_conflicts (struct web *web)
{
int num = 0;
unsigned int def2;
/* Output HARD_REG_SET to stderr. */
void
-debug_hard_reg_set (set)
- HARD_REG_SET set;
+debug_hard_reg_set (HARD_REG_SET set)
{
int i;
- for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
{
if (TEST_HARD_REG_BIT (set, i))
{