aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1994-09-08 17:59:18 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1994-09-08 17:59:18 +0000
commitf5316dfe88b8d1b8d3012c1f75349edf2ba1bdde (patch)
tree4539f2afd4cec5391458adbad088c180787efd5c /gcc
parent0be5d99ff22bb43d45d13c620071ba377d3e02d6 (diff)
downloadgcc-f5316dfe88b8d1b8d3012c1f75349edf2ba1bdde.zip
gcc-f5316dfe88b8d1b8d3012c1f75349edf2ba1bdde.tar.gz
gcc-f5316dfe88b8d1b8d3012c1f75349edf2ba1bdde.tar.bz2
Add support for -mreg-alloc=<xxx>
From-SVN: r8040
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386.c114
-rw-r--r--gcc/config/i386/i386.h98
2 files changed, 195 insertions, 17 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index ddfb4ee..3133a36 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -74,8 +74,120 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
/* Test and compare insns in i386.md store the information needed to
generate branch and scc insns here. */
-struct rtx_def *i386_compare_op0, *i386_compare_op1;
+struct rtx_def *i386_compare_op0 = NULL_RTX;
+struct rtx_def *i386_compare_op1 = NULL_RTX;
struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
+
+/* Register allocation order */
+char *i386_reg_alloc_order = (char *)0;
+static char regs_allocated[FIRST_PSEUDO_REGISTER];
+
+
+/* Sometimes certain combinations of command options do not make
+ sense on a particular target machine. You can define a macro
+ `OVERRIDE_OPTIONS' to take account of this. This macro, if
+ defined, is executed once just after all the command options have
+ been parsed.
+
+ Don't use this macro to turn on various extra optimizations for
+ `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
+
+void
+override_options ()
+{
+ int ch, i, regno;
+
+#ifdef SUBTARGET_OVERRIDE_OPTIONS
+ SUBTARGET_OVERRIDE_OPTIONS;
+#endif
+
+ /* Validate registers in register allocation order */
+ if (i386_reg_alloc_order)
+ {
+ for (i = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
+ {
+ switch (ch)
+ {
+ case 'a': regno = 0; break;
+ case 'd': regno = 1; break;
+ case 'c': regno = 2; break;
+ case 'b': regno = 3; break;
+ case 'S': regno = 4; break;
+ case 'D': regno = 5; break;
+ case 'B': regno = 6; break;
+
+ default: fatal ("Register '%c' is unknown", ch);
+ }
+
+ if (regs_allocated[regno])
+ fatal ("Register '%c' was already specified in the allocation order", ch);
+
+ regs_allocated[regno] = 1;
+ }
+ }
+}
+
+/* A C statement (sans semicolon) to choose the order in which to
+ allocate hard registers for pseudo-registers local to a basic
+ block.
+
+ Store the desired register order in the array `reg_alloc_order'.
+ Element 0 should be the register to allocate first; element 1, the
+ next register; and so on.
+
+ The macro body should not assume anything about the contents of
+ `reg_alloc_order' before execution of the macro.
+
+ On most machines, it is not necessary to define this macro. */
+
+void
+order_regs_for_local_alloc ()
+{
+ int i, ch, order, regno;
+
+ /* User specified the register allocation order */
+ if (i386_reg_alloc_order)
+ {
+ for (i = order = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
+ {
+ switch (ch)
+ {
+ case 'a': regno = 0; break;
+ case 'd': regno = 1; break;
+ case 'c': regno = 2; break;
+ case 'b': regno = 3; break;
+ case 'S': regno = 4; break;
+ case 'D': regno = 5; break;
+ case 'B': regno = 6; break;
+ }
+
+ reg_alloc_order[order++] = regno;
+ }
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (!regs_allocated[i])
+ reg_alloc_order[order++] = i;
+ }
+ }
+
+ /* If users did not specify a register allocation order, favor eax
+ normally except if cse is following jumps, then favor edx so
+ that function returns are cse'ed */
+ else
+ {
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ reg_alloc_order[i] = i;
+
+ if (optimize && flag_cse_follow_jumps && !leaf_function_p ())
+ {
+ reg_alloc_order[0] = 1; /* edx */
+ reg_alloc_order[1] = 2; /* ecx */
+ reg_alloc_order[2] = 0; /* eax */
+ }
+ }
+}
+
/* Output an insn whose source is a 386 integer register. SRC is the
rtx for the register, and TEMPLATE is the op-code template. SRC may
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 1bc8048..c68b32d 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -158,16 +158,34 @@ extern int target_flags;
SUBTARGET_SWITCHES \
{ "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
-/* This is meant to be redefined in the host dependent files */
+/* This macro is similar to `TARGET_SWITCHES' but defines names of
+ command options that have values. Its definition is an
+ initializer with a subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the
+ fixed part of the option name, and the address of a variable. The
+ variable, type `char *', is set to the variable part of the given
+ option if the fixed part matches. The actual option name is made
+ by appending `-m' to the specified name. */
+#define TARGET_OPTIONS \
+{ { "reg-alloc=", &i386_reg_alloc_order }, \
+ SUBTARGET_OPTIONS }
+
+/* Sometimes certain combinations of command options do not make
+ sense on a particular target machine. You can define a macro
+ `OVERRIDE_OPTIONS' to take account of this. This macro, if
+ defined, is executed once just after all the command options have
+ been parsed.
+
+ Don't use this macro to turn on various extra optimizations for
+ `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
+
+#define OVERRIDE_OPTIONS override_options ()
+
+/* These are meant to be redefined in the host dependent files */
#define SUBTARGET_SWITCHES
+#define SUBTARGET_OPTIONS
-#define OVERRIDE_OPTIONS \
-{ \
- SUBTARGET_OVERRIDE_OPTIONS \
-}
-
-/* This is meant to be redefined in the host dependent files */
-#define SUBTARGET_OVERRIDE_OPTIONS
/* target machine storage layout */
@@ -313,11 +331,24 @@ extern int target_flags;
functions, and a slightly slower compiler. Users complained about the code
generated by allocating edx first, so restore the 'natural' order of things. */
-#if 0
#define REG_ALLOC_ORDER \
-/*dx,cx,ax,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
-{ 1, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
-#endif
+/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
+
+/* A C statement (sans semicolon) to choose the order in which to
+ allocate hard registers for pseudo-registers local to a basic
+ block.
+
+ Store the desired register order in the array `reg_alloc_order'.
+ Element 0 should be the register to allocate first; element 1, the
+ next register; and so on.
+
+ The macro body should not assume anything about the contents of
+ `reg_alloc_order' before execution of the macro.
+
+ On most machines, it is not necessary to define this macro. */
+
+#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
/* Macro to conditionally modify fixed_regs/call_used_regs. */
#define CONDITIONAL_REGISTER_USAGE \
@@ -509,7 +540,6 @@ enum reg_class
reg number REGNO. This could be a conditional expression
or could index an array. */
-extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
/* When defined, the compiler allows registers explicitly used in the
@@ -641,6 +671,32 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
#define CLASS_MAX_NREGS(CLASS, MODE) \
(FLOAT_CLASS_P (CLASS) ? 1 : \
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* A C expression whose value is nonzero if pseudos that have been
+ assigned to registers of class CLASS would likely be spilled
+ because registers of CLASS are needed for spill registers.
+
+ The default value of this macro returns 1 if CLASS has exactly one
+ register and zero otherwise. On most machines, this default
+ should be used. Only define this macro to some other expression
+ if pseudo allocated by `local-alloc.c' end up in memory because
+ their hard registers were needed for spill regisers. If this
+ macro returns nonzero for those classes, those pseudos will only
+ be allocated by `global.c', which knows how to reallocate the
+ pseudo to another register. If there would not be another
+ register available for reallocation, you should not change the
+ definition of this macro since the only effect of such a
+ definition would be to slow down register allocation. */
+
+#define CLASS_LIKELY_SPILLED_P(CLASS) \
+ (((CLASS) == AREG) \
+ || ((CLASS) == DREG) \
+ || ((CLASS) == CREG) \
+ || ((CLASS) == BREG) \
+ || ((CLASS) == AD_REGS) \
+ || ((CLASS) == SIREG) \
+ || ((CLASS) == DIREG))
+
/* Stack layout; function entry, exit and calling. */
@@ -1296,7 +1352,6 @@ while (0)
stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */
-extern struct rtx_def *i386_compare_op0, *i386_compare_op1;
extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
/* Tell final.c how to eliminate redundant test instructions. */
@@ -1643,6 +1698,8 @@ extern char *qi_high_reg_name[];
#define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx))
/* Functions in i386.c */
+extern void override_options ();
+extern void order_regs_for_local_alloc ();
extern void output_op_from_reg ();
extern void output_to_reg ();
extern char *singlemove_string ();
@@ -1676,9 +1733,18 @@ extern void restore_386_machine_status ();
extern void clear_386_stack_locals ();
extern struct rtx_def *assign_386_stack_local ();
+/* Variables in i386.c */
+extern char *i386_reg_alloc_order; /* register allocation order */
+extern char *hi_reg_name[]; /* names for 16 bit regs */
+extern char *qi_reg_name[]; /* names for 8 bit regs (low) */
+extern char *qi_high_reg_name[]; /* names for 8 bit regs (high) */
+extern enum reg_class regclass_map[]; /* smalled class containing REGNO */
+extern struct rtx_def *i386_compare_op0; /* operand 0 for comparisons */
+extern struct rtx_def *i386_compare_op1; /* operand 1 for comparisons */
+
/* External variables used */
-extern int optimize; /* optimization level */
-extern int obey_regdecls; /* TRUE if stupid register allocation */
+extern int optimize; /* optimization level */
+extern int obey_regdecls; /* TRUE if stupid register allocation */
/* External functions used */
extern struct rtx_def *force_operand ();