From f84aa48ac1c8718f7f3275496aa4bcc734c6e36a Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 13 Feb 2001 11:40:40 +0100 Subject: [PATCH] i386.h (SSE_CLASS_P, [...]): New macros. * i386.h (SSE_CLASS_P, MMX_CLASS_P, MAYBE_FLOAT_CLASS_P, MAYBE_SSE_CLASS_P, MAYBE_MMX_CLASS_P): New macros. (PREFERRED_RELOAD_CLASS, SECONDARY_MEMORY_NEEDED): Move offline. (REGISTER_MOVE_COST): Likewise. * i386-protos.h (ix86_secondary_memory_needed, ix86_preferred_reload_class, ix86_register_move_cost): Declare. * i386.c (ix86_secondary_memory_needed, ix86_preferred_reload_class, ix86_register_move_cost): New function. From-SVN: r39622 --- gcc/ChangeLog | 11 ++++++ gcc/config/i386/i386.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/config/i386/i386.h | 44 ++++++--------------- 3 files changed, 125 insertions(+), 32 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aac7623..df04b03 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +Tue Feb 13 11:37:06 CET 2001 Jan Hubicka + + * i386.h (SSE_CLASS_P, MMX_CLASS_P, MAYBE_FLOAT_CLASS_P, + MAYBE_SSE_CLASS_P, MAYBE_MMX_CLASS_P): New macros. + (PREFERRED_RELOAD_CLASS, SECONDARY_MEMORY_NEEDED): Move offline. + (REGISTER_MOVE_COST): Likewise. + * i386-protos.h (ix86_secondary_memory_needed, + ix86_preferred_reload_class, ix86_register_move_cost): Declare. + * i386.c (ix86_secondary_memory_needed, + ix86_preferred_reload_class, ix86_register_move_cost): New function. + Die Feb 13 11:04:25 CET 2001 Jan Hubicka * i386.h (VALID_FP_MODE_P, VALID_INT_MODE_P): New. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 683c881..4e5dffd 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -8725,6 +8725,108 @@ ix86_free_from_memory (mode) : 4)))); } +/* Put float CONST_DOUBLE in the constant pool instead of fp regs. + QImode must go into class Q_REGS. + Narrow ALL_REGS to GENERAL_REGS. This supports allowing movsf and + movdf to do mem-to-mem moves through integer regs. */ +enum reg_class +ix86_preferred_reload_class (x, class) + rtx x; + enum reg_class class; +{ + if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode) + { + /* SSE can't load any constant directly yet. */ + if (SSE_CLASS_P (class)) + return NO_REGS; + /* Floats can load 0 and 1. */ + if (MAYBE_FLOAT_CLASS_P (class) && standard_80387_constant_p (x)) + { + /* Limit class to non-SSE. Use GENERAL_REGS if possible. */ + if (MAYBE_SSE_CLASS_P (class)) + return (reg_class_subset_p (class, GENERAL_REGS) + ? GENERAL_REGS : FLOAT_REGS); + else + return class; + } + /* General regs can load everything. */ + if (reg_class_subset_p (class, GENERAL_REGS)) + return GENERAL_REGS; + /* In case we haven't resolved FLOAT or SSE yet, give up. */ + if (MAYBE_FLOAT_CLASS_P (class) || MAYBE_SSE_CLASS_P (class)) + return NO_REGS; + } + if (MAYBE_MMX_CLASS_P (class) && CONSTANT_P (x)) + return NO_REGS; + if (GET_MODE (x) == QImode && ! reg_class_subset_p (class, Q_REGS)) + return Q_REGS; + return class; +} + +/* If we are copying between general and FP registers, we need a memory + location. The same is true for SSE and MMX registers. + + The macro can't work reliably when one of the CLASSES is class containing + registers from multiple units (SSE, MMX, integer). We avoid this by never + combining those units in single alternative in the machine description. + Ensure that this constraint holds to avoid unexpected surprises. + + When STRICT is false, we are being called from REGISTER_MOVE_COST, so do not + enforce these sanity checks. */ +int +ix86_secondary_memory_needed (class1, class2, mode, strict) + enum reg_class class1, class2; + enum machine_mode mode; + int strict; +{ + if (MAYBE_FLOAT_CLASS_P (class1) != FLOAT_CLASS_P (class1) + || MAYBE_FLOAT_CLASS_P (class2) != FLOAT_CLASS_P (class2) + || MAYBE_SSE_CLASS_P (class1) != SSE_CLASS_P (class1) + || MAYBE_SSE_CLASS_P (class2) != SSE_CLASS_P (class2) + || MAYBE_MMX_CLASS_P (class1) != MMX_CLASS_P (class1) + || MAYBE_MMX_CLASS_P (class2) != MMX_CLASS_P (class2)) + { + if (strict) + abort (); + else + return 1; + } + return (FLOAT_CLASS_P (class1) != FLOAT_CLASS_P (class2) + || (SSE_CLASS_P (class1) != SSE_CLASS_P (class2) + && (mode) != SImode) + || (MMX_CLASS_P (class1) != MMX_CLASS_P (class2) + && (mode) != SImode)); +} +/* Return the cost of moving data from a register in class CLASS1 to + one in class CLASS2. + + It is not required that the cost always equal 2 when FROM is the same as TO; + on some machines it is expensive to move between registers if they are not + general registers. */ +int +ix86_register_move_cost (mode, class1, class2) + enum machine_mode mode; + enum reg_class class1, class2; +{ + /* In case we require secondary memory, compute cost of the store followed + by load. In case of copying from general_purpose_register we may emit + multiple stores followed by single load causing memory size mismatch + stall. Count this as arbitarily high cost of 20. */ + if (ix86_secondary_memory_needed (class1, class2, mode, 0)) + { + if (CLASS_MAX_NREGS (CLASS1, MODE) > CLASS_MAX_NREGS (CLASS2, MODE)) + return 10; + return (MEMORY_MOVE_COST (MODE, CLASS1, 0) + + MEMORY_MOVE_COST (MODE, CLASS2, 1)); + } + /* Moves between SSE/MMX and integer unit are expensive. + ??? We should make this cost CPU specific. */ + if (MMX_CLASS_P (CLASS1) != MMX_CLASS_P (CLASS2) + || SSE_CLASS_P (CLASS1) != SSE_CLASS_P (CLASS2)) + return 3; + return 2; +} + /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */ int ix86_hard_regno_mode_ok (regno, mode) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 162da52..13ef600 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -946,6 +946,11 @@ enum reg_class #define N_REG_CLASSES (int) LIM_REG_CLASSES #define FLOAT_CLASS_P(CLASS) (reg_class_subset_p (CLASS, FLOAT_REGS)) +#define SSE_CLASS_P(CLASS) (reg_class_subset_p (CLASS, SSE_REGS)) +#define MMX_CLASS_P(CLASS) (reg_class_subset_p (CLASS, MMX_REGS)) +#define MAYBE_FLOAT_CLASS_P(CLASS) (reg_classes_intersect_p (CLASS, FLOAT_REGS)) +#define MAYBE_SSE_CLASS_P(CLASS) (reg_classes_intersect_p (SSE_REGS, CLASS)) +#define MAYBE_MMX_CLASS_P(CLASS) (reg_classes_intersect_p (MMX_REGS, CLASS)) #define Q_CLASS_P(CLASS) (reg_class_subset_p (CLASS, Q_REGS)) @@ -1112,22 +1117,12 @@ enum reg_class movdf to do mem-to-mem moves through integer regs. */ #define PREFERRED_RELOAD_CLASS(X,CLASS) \ - (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode \ - ? (standard_80387_constant_p (X) \ - ? CLASS \ - : (reg_class_subset_p (CLASS, FLOAT_REGS) \ - ? NO_REGS \ - : reg_class_subset_p (CLASS, GENERAL_REGS) ? CLASS : GENERAL_REGS)) \ - : GET_MODE (X) == QImode && ! reg_class_subset_p (CLASS, Q_REGS) ? Q_REGS \ - : (CLASS)) + ix86_preferred_reload_class (X, CLASS) /* If we are copying between general and FP registers, we need a memory - location. */ -/* The same is true for SSE and MMX registers. */ + location. The same is true for SSE and MMX registers. */ #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \ - (FLOAT_CLASS_P (CLASS1) != FLOAT_CLASS_P (CLASS2) \ - || ((CLASS1 == SSE_REGS) != (CLASS2 == SSE_REGS)) \ - || ((CLASS1 == MMX_REGS) != (CLASS2 == MMX_REGS) && (MODE) != SImode)) + ix86_secondary_memory_needed (CLASS1, CLASS2, MODE, 1) /* QImode spills from non-QI registers need a scratch. This does not happen often -- the only example so far requires an uninitialized @@ -1141,7 +1136,7 @@ enum reg_class /* On the 80386, this is the size of MODE in words, except in the FP regs, where a single reg is always enough. */ #define CLASS_MAX_NREGS(CLASS, MODE) \ - (FLOAT_CLASS_P (CLASS) || (CLASS) == SSE_REGS || (CLASS) == MMX_REGS \ + (FLOAT_CLASS_P (CLASS) || SSE_CLASS_P (CLASS) || MMX_CLASS_P (CLASS) \ ? 1 \ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) @@ -2352,25 +2347,10 @@ while (0) It is not required that the cost always equal 2 when FROM is the same as TO; on some machines it is expensive to move between registers if they are not - general registers. + general registers. */ - On the i386, copying between floating-point and fixed-point - registers is done trough memory. - - Integer -> fp moves are noticeably slower than the opposite direction - because of the partial memory stall they cause. Give it an - arbitary high cost. - */ - -#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \ - ((FLOAT_CLASS_P (CLASS1) && ! FLOAT_CLASS_P (CLASS2)) \ - ? (MEMORY_MOVE_COST (DFmode, CLASS1, 0) \ - + MEMORY_MOVE_COST (DFmode, CLASS2, 1)) \ - : (! FLOAT_CLASS_P (CLASS1) && FLOAT_CLASS_P (CLASS2)) ? 10 \ - : ((CLASS1) == MMX_REGS && (CLASS2) == SSE_REGS) ? 10 \ - : ((CLASS1) == SSE_REGS && (CLASS2) == MMX_REGS) ? 10 \ - : ((CLASS1) == MMX_REGS) != ((CLASS2) == MMX_REGS) ? 3 \ - : 2) +#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \ + ix86_register_move_cost (mode, class1, class2); /* A C expression for the cost of moving data of mode M between a register and memory. A value of 2 is the default; this cost is -- 2.7.4