From aea8cb376b8670465347c99ea33feb019637dedc Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 24 Oct 2008 08:04:22 +0000 Subject: [PATCH] mips.c (mips_canonicalize_move_class): New function. gcc/ * config/mips/mips.c (mips_canonicalize_move_class): New function. (mips_move_to_gpr_cost): Likewise. (mips_move_from_gpr_cost): Likewise. (mips_register_move_cost): Make more fine-grained. From-SVN: r141336 --- gcc/ChangeLog | 7 +++ gcc/config/mips/mips.c | 168 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 131 insertions(+), 44 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1ade1e7..76d8c01 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2008-10-24 Richard Sandiford + + * config/mips/mips.c (mips_canonicalize_move_class): New function. + (mips_move_to_gpr_cost): Likewise. + (mips_move_from_gpr_cost): Likewise. + (mips_register_move_cost): Make more fine-grained. + 2008-10-23 Tobias Grosser * graphite.c (graphite_apply_transformations): Check for diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index eb76ff4..f566e03 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -9689,62 +9689,142 @@ mips_preferred_reload_class (rtx x, enum reg_class rclass) return rclass; } -/* Implement REGISTER_MOVE_COST. */ +/* RCLASS is a class involved in a REGISTER_MOVE_COST calculation. + Return a "canonical" class to represent it in later calculations. */ -int -mips_register_move_cost (enum machine_mode mode, - enum reg_class to, enum reg_class from) +static enum reg_class +mips_canonicalize_move_class (enum reg_class rclass) { - if (TARGET_MIPS16) + /* All moves involving accumulator registers have the same cost. */ + if (reg_class_subset_p (rclass, ACC_REGS)) + rclass = ACC_REGS; + + /* Likewise promote subclasses of general registers to the most + interesting containing class. */ + if (TARGET_MIPS16 && reg_class_subset_p (rclass, M16_REGS)) + rclass = M16_REGS; + else if (reg_class_subset_p (rclass, GENERAL_REGS)) + rclass = GENERAL_REGS; + + return rclass; +} + +/* Return the cost of moving a value of mode MODE from a register of + class FROM to a GPR. Return 0 for classes that are unions of other + classes handled by this function. */ + +static int +mips_move_to_gpr_cost (enum machine_mode mode ATTRIBUTE_UNUSED, + enum reg_class from) +{ + switch (from) { - if (reg_class_subset_p (from, GENERAL_REGS) - && reg_class_subset_p (to, GENERAL_REGS)) - { - if (reg_class_subset_p (from, M16_REGS) - || reg_class_subset_p (to, M16_REGS)) - return 2; - /* Two MOVEs. */ - return 4; - } + case GENERAL_REGS: + /* A MIPS16 MOVE instruction, or a non-MIPS16 MOVE macro. */ + return 2; + + case ACC_REGS: + /* MFLO and MFHI. */ + return 6; + + case FP_REGS: + /* MFC1, etc. */ + return 4; + + case ST_REGS: + /* LUI followed by MOVF. */ + return 4; + + case COP0_REGS: + case COP2_REGS: + case COP3_REGS: + /* This choice of value is historical. */ + return 5; + + default: + return 0; } - else if (reg_class_subset_p (from, GENERAL_REGS)) +} + +/* Return the cost of moving a value of mode MODE from a GPR to a + register of class TO. Return 0 for classes that are unions of + other classes handled by this function. */ + +static int +mips_move_from_gpr_cost (enum machine_mode mode, enum reg_class to) +{ + switch (to) { - if (reg_class_subset_p (to, GENERAL_REGS)) - return 2; - if (reg_class_subset_p (to, FP_REGS)) - return 4; - if (reg_class_subset_p (to, COP0_REGS) - || reg_class_subset_p (to, COP2_REGS) - || reg_class_subset_p (to, COP3_REGS)) - return 5; - if (reg_class_subset_p (to, ACC_REGS)) - return 6; + case GENERAL_REGS: + /* A MIPS16 MOVE instruction, or a non-MIPS16 MOVE macro. */ + return 2; + + case ACC_REGS: + /* MTLO and MTHI. */ + return 6; + + case FP_REGS: + /* MTC1, etc. */ + return 4; + + case ST_REGS: + /* A secondary reload through an FPR scratch. */ + return (mips_register_move_cost (mode, GENERAL_REGS, FP_REGS) + + mips_register_move_cost (mode, FP_REGS, ST_REGS)); + + case COP0_REGS: + case COP2_REGS: + case COP3_REGS: + /* This choice of value is historical. */ + return 5; + + default: + return 0; } - else if (reg_class_subset_p (to, GENERAL_REGS)) +} + +/* Implement REGISTER_MOVE_COST. Return 0 for classes that are the + maximum of the move costs for subclasses; regclass will work out + the maximum for us. */ + +int +mips_register_move_cost (enum machine_mode mode, + enum reg_class from, enum reg_class to) +{ + enum reg_class dregs; + int cost1, cost2; + + from = mips_canonicalize_move_class (from); + to = mips_canonicalize_move_class (to); + + /* Handle moves that can be done without using general-purpose registers. */ + if (from == FP_REGS) { - if (reg_class_subset_p (from, FP_REGS)) + if (to == FP_REGS && mips_mode_ok_for_mov_fmt_p (mode)) + /* MOV.FMT. */ return 4; - if (reg_class_subset_p (from, ST_REGS)) - /* LUI followed by MOVF. */ - return 4; - if (reg_class_subset_p (from, COP0_REGS) - || reg_class_subset_p (from, COP2_REGS) - || reg_class_subset_p (from, COP3_REGS)) - return 5; - if (reg_class_subset_p (from, ACC_REGS)) - return 6; + if (to == ST_REGS) + /* The sequence generated by mips_expand_fcc_reload. */ + return 8; } - else if (reg_class_subset_p (from, FP_REGS)) + + /* Handle cases in which only one class deviates from the ideal. */ + dregs = TARGET_MIPS16 ? M16_REGS : GENERAL_REGS; + if (from == dregs) + return mips_move_from_gpr_cost (mode, to); + if (to == dregs) + return mips_move_to_gpr_cost (mode, from); + + /* Handles cases that require a GPR temporary. */ + cost1 = mips_move_to_gpr_cost (mode, from); + if (cost1 != 0) { - if (reg_class_subset_p (to, FP_REGS) - && mips_mode_ok_for_mov_fmt_p (mode)) - return 4; - if (reg_class_subset_p (to, ST_REGS)) - /* An expensive sequence. */ - return 8; + cost2 = mips_move_from_gpr_cost (mode, to); + if (cost2 != 0) + return cost1 + cost2; } - return 12; + return 0; } /* Implement TARGET_IRA_COVER_CLASSES. */ -- 2.7.4