From: Richard Henderson Date: Thu, 23 Aug 2001 07:44:03 +0000 (-0700) Subject: ia64.c (ia64_register_move_cost): Add mode arguemnt. X-Git-Tag: prereleases/libstdc++-3.0.95~2471 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7109d286421592dd087ae3b397107bf711ac80af;p=thirdparty%2Fgcc.git ia64.c (ia64_register_move_cost): Add mode arguemnt. * config/ia64/ia64.c (ia64_register_move_cost): Add mode arguemnt. Reorganize. Handle ADDL like GR, add GR_AND_BR. Handle TFmode. (ia64_secondary_reload_class): Need GR between AR/BR and anything. Need GR between FR and not GR_AND_FR. * config/ia64/ia64-protos.h (ia64_register_move_cost): Update. * config/ia64/ia64.h (reg_class): Add GR_AND_BR_REGS, move AR regs before GR regs. (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update. (PREFERRED_RELOAD_CLASS): Tweak for reordered classes. (REGISTER_MOVE_COST): Update. (MEMORY_MOVE_COST): Add GR_AND_FR_REGS. From-SVN: r45125 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb088f362dd9..af192db17a45 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2001-08-23 Richard Henderson + + * config/ia64/ia64.c (ia64_register_move_cost): Add mode arguemnt. + Reorganize. Handle ADDL like GR, add GR_AND_BR. Handle TFmode. + (ia64_secondary_reload_class): Need GR between AR/BR and anything. + Need GR between FR and not GR_AND_FR. + * config/ia64/ia64-protos.h (ia64_register_move_cost): Update. + * config/ia64/ia64.h (reg_class): Add GR_AND_BR_REGS, move + AR regs before GR regs. + (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update. + (PREFERRED_RELOAD_CLASS): Tweak for reordered classes. + (REGISTER_MOVE_COST): Update. + (MEMORY_MOVE_COST): Add GR_AND_FR_REGS. + 2001-08-23 Richard Henderson * regclass.c (init_reg_sets_1): Don't assume cost 2 within diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index 03d2952aa227..fca7f35551a5 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -119,7 +119,8 @@ extern void ia64_asm_output_external PARAMS((FILE *, tree, const char *)); extern void ia64_encode_section_info PARAMS((tree)); #endif /* TREE_CODE */ -extern int ia64_register_move_cost PARAMS((enum reg_class, enum reg_class)); +extern int ia64_register_move_cost PARAMS((enum machine_mode, enum reg_class, + enum reg_class)); extern int ia64_epilogue_uses PARAMS((int)); extern void emit_safe_across_calls PARAMS((FILE *)); extern void ia64_init_builtins PARAMS((void)); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 5cba6245ef05..8b56dad35083 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -3551,45 +3551,73 @@ ia64_print_operand (file, x, code) } /* Calulate the cost of moving data from a register in class FROM to - one in class TO. */ + one in class TO, using MODE. */ int -ia64_register_move_cost (from, to) +ia64_register_move_cost (mode, from, to) + enum machine_mode mode; enum reg_class from, to; { - int from_hard, to_hard; - int from_gr, to_gr; - int from_fr, to_fr; - int from_pr, to_pr; - - from_hard = (from == BR_REGS || from == AR_M_REGS || from == AR_I_REGS); - to_hard = (to == BR_REGS || to == AR_M_REGS || to == AR_I_REGS); - from_gr = (from == GENERAL_REGS); - to_gr = (to == GENERAL_REGS); - from_fr = (from == FR_REGS); - to_fr = (to == FR_REGS); - from_pr = (from == PR_REGS); - to_pr = (to == PR_REGS); - - if (from_hard && to_hard) - return 8; - else if ((from_hard && !to_gr) || (!from_gr && to_hard)) - return 6; + /* ADDL_REGS is the same as GR_REGS for movement purposes. */ + if (to == ADDL_REGS) + to = GR_REGS; + if (from == ADDL_REGS) + from = GR_REGS; - /* Moving between PR registers takes two insns. */ - else if (from_pr && to_pr) - return 3; - /* Moving between PR and anything but GR is impossible. */ - else if ((from_pr && !to_gr) || (!from_gr && to_pr)) - return 6; - - /* ??? Moving from FR<->GR must be more expensive than 2, so that we get - secondary memory reloads for TFmode moves. Unfortunately, we don't - have the mode here, so we can't check that. */ - /* Moreover, we have to make this at least as high as MEMORY_MOVE_COST - to avoid spectacularly poor register class preferencing for TFmode. */ - else if (from_fr != to_fr) - return 5; + /* All costs are symmetric, so reduce cases by putting the + lower number class as the destination. */ + if (from < to) + { + enum reg_class tmp = to; + to = from, from = tmp; + } + + /* Moving from FR<->GR in TFmode must be more expensive than 2, + so that we get secondary memory reloads. Between FR_REGS, + we have to make this at least as expensive as MEMORY_MOVE_COST + to avoid spectacularly poor register class preferencing. */ + if (mode == TFmode) + { + if (to != GR_REGS || from != GR_REGS) + return MEMORY_MOVE_COST (mode, to, 0); + else + return 3; + } + + switch (to) + { + case PR_REGS: + /* Moving between PR registers takes two insns. */ + if (from == PR_REGS) + return 3; + /* Moving between PR and anything but GR is impossible. */ + if (from != GR_REGS) + return MEMORY_MOVE_COST (mode, to, 0); + break; + + case BR_REGS: + /* Moving between BR and anything but GR is impossible. */ + if (from != GR_REGS && from != GR_AND_BR_REGS) + return MEMORY_MOVE_COST (mode, to, 0); + break; + + case AR_I_REGS: + case AR_M_REGS: + /* Moving between AR and anything but GR is impossible. */ + if (from != GR_REGS) + return MEMORY_MOVE_COST (mode, to, 0); + break; + + case GR_REGS: + case FR_REGS: + case GR_AND_FR_REGS: + case GR_AND_BR_REGS: + case ALL_REGS: + break; + + default: + abort (); + } return 2; } @@ -3613,17 +3641,21 @@ ia64_secondary_reload_class (class, mode, x) switch (class) { case BR_REGS: - /* ??? This is required because of a bad gcse/cse/global interaction. - We end up with two pseudos with overlapping lifetimes both of which - are equiv to the same constant, and both which need to be in BR_REGS. - This results in a BR_REGS to BR_REGS copy which doesn't exist. To - reproduce, return NO_REGS here, and compile divdi3 in libgcc2.c. - This seems to be a cse bug. cse_basic_block_end changes depending - on the path length, which means the qty_first_reg check in - make_regs_eqv can give different answers at different times. */ - /* ??? At some point I'll probably need a reload_indi pattern to handle - this. */ - if (BR_REGNO_P (regno)) + case AR_M_REGS: + case AR_I_REGS: + /* ??? BR<->BR register copies can happen due to a bad gcse/cse/global + interaction. We end up with two pseudos with overlapping lifetimes + both of which are equiv to the same constant, and both which need + to be in BR_REGS. This seems to be a cse bug. cse_basic_block_end + changes depending on the path length, which means the qty_first_reg + check in make_regs_eqv can give different answers at different times. + At some point I'll probably need a reload_indi pattern to handle + this. + + We can also get GR_AND_FR_REGS to BR_REGS/AR_REGS copies, where we + wound up with a FP register from GR_AND_FR_REGS. Extend that to all + non-general registers for good measure. */ + if (regno >= 0 && ! GENERAL_REGNO_P (regno)) return GR_REGS; /* This is needed if a pseudo used as a call_operand gets spilled to a @@ -3633,6 +3665,10 @@ ia64_secondary_reload_class (class, mode, x) break; case FR_REGS: + /* Need to go through general regsters to get to other class regs. */ + if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno))) + return GR_REGS; + /* This can happen when a paradoxical subreg is an operand to the muldi3 pattern. */ /* ??? This shouldn't be necessary after instruction scheduling is diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index ccd6df7fbaad..737b1e7b597a 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -907,12 +907,13 @@ enum reg_class NO_REGS, PR_REGS, BR_REGS, + AR_M_REGS, + AR_I_REGS, ADDL_REGS, GR_REGS, FR_REGS, + GR_AND_BR_REGS, GR_AND_FR_REGS, - AR_M_REGS, - AR_I_REGS, ALL_REGS, LIM_REG_CLASSES }; @@ -925,8 +926,9 @@ enum reg_class /* An initializer containing the names of the register classes as C string constants. These names are used in writing some of the debugging dumps. */ #define REG_CLASS_NAMES \ -{ "NO_REGS", "PR_REGS", "BR_REGS", "ADDL_REGS", "GR_REGS", "FR_REGS", \ - "GR_AND_FR_REGS", "AR_M_REGS", "AR_I_REGS", "ALL_REGS" } +{ "NO_REGS", "PR_REGS", "BR_REGS", "AR_M_REGS", "AR_I_REGS", \ + "ADDL_REGS", "GR_REGS", "FR_REGS", \ + "GR_AND_BR_REGS", "GR_AND_FR_REGS", "ALL_REGS" } /* An initializer containing the contents of the register classes, as integers which are bit masks. The Nth integer specifies the contents of class N. @@ -946,6 +948,14 @@ enum reg_class { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00FF }, \ + /* AR_M_REGS. */ \ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x0C00 }, \ + /* AR_I_REGS. */ \ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x7000 }, \ /* ADDL_REGS. */ \ { 0x0000000F, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ @@ -958,18 +968,14 @@ enum reg_class { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0x00000000, 0x00000000, 0x0000 }, \ + /* GR_AND_BR_REGS. */ \ + { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x03FF }, \ /* GR_AND_FR_REGS. */ \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0x00000000, 0x00000000, 0x0300 }, \ - /* AR_M_REGS. */ \ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ - 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ - 0x00000000, 0x00000000, 0x0C00 }, \ - /* AR_I_REGS. */ \ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ - 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ - 0x00000000, 0x00000000, 0x7000 }, \ /* ALL_REGS. */ \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ @@ -1044,7 +1050,8 @@ enum reg_class #define PREFERRED_RELOAD_CLASS(X, CLASS) \ (CLASS == FR_REGS && GET_CODE (X) == MEM && MEM_VOLATILE_P (X) ? NO_REGS \ : CLASS == FR_REGS && GET_CODE (X) == CONST_DOUBLE ? NO_REGS \ - : GET_RTX_CLASS (GET_CODE (X)) != 'o' && CLASS > GR_AND_FR_REGS ? NO_REGS \ + : GET_RTX_CLASS (GET_CODE (X)) != 'o' \ + && (CLASS == AR_M_REGS || CLASS == AR_I_REGS) ? NO_REGS \ : CLASS) /* You should define this macro to indicate to the reload phase that it may @@ -1882,15 +1889,15 @@ do { \ #define ADDRESS_COST(ADDRESS) 0 /* A C expression for the cost of moving data from a register in class FROM to - one in class TO. */ + one in class TO, using MODE. */ -#define REGISTER_MOVE_COST(MODE, FROM, TO) \ - ia64_register_move_cost((FROM), (TO)) +#define REGISTER_MOVE_COST ia64_register_move_cost /* A C expression for the cost of moving data of mode M between a register and memory. */ #define MEMORY_MOVE_COST(MODE,CLASS,IN) \ - ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS ? 4 : 10) + ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS \ + || (CLASS) == GR_AND_FR_REGS ? 4 : 10) /* A C expression for the cost of a branch instruction. A value of 1 is the default; other values are interpreted relative to that. Used by the