aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-02-01 16:30:36 -0800
committerRichard Henderson <rth@gcc.gnu.org>2005-02-01 16:30:36 -0800
commitc1c5b5e383b7e566b49b4c160a1af16eb9222f52 (patch)
tree7ed9ac7a001a41282b1bc0a116f2ed9933e1a48a
parentfa4c37aab9ba18b8d345be30a4ebc463e7209b4c (diff)
downloadgcc-c1c5b5e383b7e566b49b4c160a1af16eb9222f52.zip
gcc-c1c5b5e383b7e566b49b4c160a1af16eb9222f52.tar.gz
gcc-c1c5b5e383b7e566b49b4c160a1af16eb9222f52.tar.bz2
re PR rtl-optimization/19680 (sub-optimial register allocation with sse)
PR target/19680 * config/i386/i386.h (MODES_TIEABLE_P): Use ix86_modes_tieable_p. * config/i386/i386.c (ix86_hard_regno_mode_ok): Change return type to bool. (ix86_tieable_integer_mode_p, ix86_modes_tieable_p): New. * config/i386/i386-protos.h: Update. From-SVN: r94575
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/i386/i386-protos.h3
-rw-r--r--gcc/config/i386/i386.c64
-rw-r--r--gcc/config/i386/i386.h11
4 files changed, 75 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac04aeb..6390a0b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2005-02-01 Richard Henderson <rth@redhat.com
+
+ PR target/19680
+ * config/i386/i386.h (MODES_TIEABLE_P): Use ix86_modes_tieable_p.
+ * config/i386/i386.c (ix86_hard_regno_mode_ok): Change return
+ type to bool.
+ (ix86_tieable_integer_mode_p, ix86_modes_tieable_p): New.
+ * config/i386/i386-protos.h: Update.
+
2005-02-01 Steven Bosscher <stevenb@suse.de>
PR tree-optimization/19217
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index feacd2d..53edfd1 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -180,7 +180,8 @@ extern rtx ix86_force_to_memory (enum machine_mode, rtx);
extern void ix86_free_from_memory (enum machine_mode);
extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx,
rtx, rtx, rtx, rtx);
-extern int ix86_hard_regno_mode_ok (int, enum machine_mode);
+extern bool ix86_hard_regno_mode_ok (int, enum machine_mode);
+extern bool ix86_modes_tieable_p (enum machine_mode, enum machine_mode);
extern int ix86_register_move_cost (enum machine_mode, enum reg_class,
enum reg_class);
extern int ix86_secondary_memory_needed (enum reg_class, enum reg_class,
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f72bd3d..bc680c8 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -14997,7 +14997,8 @@ ix86_register_move_cost (enum machine_mode mode, enum reg_class class1,
}
/* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
-int
+
+bool
ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
{
/* Flags and only flags can only hold CCmode values. */
@@ -15038,6 +15039,67 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
return reload_in_progress || reload_completed || !TARGET_PARTIAL_REG_STALL;
}
+/* A subroutine of ix86_modes_tieable_p. Return true if MODE is a
+ tieable integer mode. */
+
+static bool
+ix86_tieable_integer_mode_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case HImode:
+ case SImode:
+ return true;
+
+ case QImode:
+ return TARGET_64BIT || !TARGET_PARTIAL_REG_STALL;
+
+ case DImode:
+ return TARGET_64BIT;
+
+ default:
+ return false;
+ }
+}
+
+/* Return true if MODE1 is accessible in a register that can hold MODE2
+ without copying. That is, all register classes that can hold MODE2
+ can also hold MODE1. */
+
+bool
+ix86_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
+{
+ if (mode1 == mode2)
+ return true;
+
+ if (ix86_tieable_integer_mode_p (mode1)
+ && ix86_tieable_integer_mode_p (mode2))
+ return true;
+
+ /* MODE2 being XFmode implies fp stack or general regs, which means we
+ can tie any smaller floating point modes to it. Note that we do not
+ tie this with TFmode. */
+ if (mode2 == XFmode)
+ return mode1 == SFmode || mode1 == DFmode;
+
+ /* MODE2 being DFmode implies fp stack, general or sse regs, which means
+ that we can tie it with SFmode. */
+ if (mode2 == DFmode)
+ return mode1 == SFmode;
+
+ /* If MODE2 is only appropriate for an SSE register, then tie with
+ any other mode acceptable to SSE registers. */
+ if (SSE_REG_MODE_P (mode2))
+ return ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode1);
+
+ /* If MODE2 is appropriate for an MMX (or SSE) register, then tie
+ with any other mode acceptable to MMX registers. */
+ if (MMX_REG_MODE_P (mode2))
+ return ix86_hard_regno_mode_ok (FIRST_MMX_REG, mode1);
+
+ return false;
+}
+
/* Return the cost of moving data of mode M between a
register and memory. A value of 2 is the default; this cost is
relative to those in `REGISTER_MOVE_COST'.
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e155a4f..5c2046a 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1122,16 +1122,7 @@ do { \
If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
for any hard reg, then this must be 0 for correct output. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
- ((MODE1) == (MODE2) \
- || (((MODE1) == HImode || (MODE1) == SImode \
- || ((MODE1) == QImode \
- && (TARGET_64BIT || !TARGET_PARTIAL_REG_STALL)) \
- || ((MODE1) == DImode && TARGET_64BIT)) \
- && ((MODE2) == HImode || (MODE2) == SImode \
- || ((MODE2) == QImode \
- && (TARGET_64BIT || !TARGET_PARTIAL_REG_STALL)) \
- || ((MODE2) == DImode && TARGET_64BIT))))
+#define MODES_TIEABLE_P(MODE1, MODE2) ix86_modes_tieable_p (MODE1, MODE2)
/* It is possible to write patterns to move flags; but until someone
does it, */