aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-02-01 23:50:21 -0800
committerRichard Henderson <rth@gcc.gnu.org>2000-02-01 23:50:21 -0800
commit2c5a510cb834f9d9c91d65ee40e568b2e33b6164 (patch)
treececcc6e724603c079d5844d258770ae96c1ae2d9 /gcc
parentea2d416aac0d9e927f567c09617bd8c417b194a5 (diff)
downloadgcc-2c5a510cb834f9d9c91d65ee40e568b2e33b6164.zip
gcc-2c5a510cb834f9d9c91d65ee40e568b2e33b6164.tar.gz
gcc-2c5a510cb834f9d9c91d65ee40e568b2e33b6164.tar.bz2
i386.c (general_no_elim_operand): New.
* i386.c (general_no_elim_operand): New. (nonmemory_no_elim_operand): New. (ix86_expand_move): Copy eliminable operands before a push. * i386-protos.h: Declare new functions. * i386.h (CAN_ELIMINATE): Simplify. (PREDICATE_CODES): Update. * i386.md (push insns): Don't allow eliminable register operands. From-SVN: r31755
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c42
-rw-r--r--gcc/config/i386/i386.h17
-rw-r--r--gcc/config/i386/i386.md16
5 files changed, 69 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 480e69d..8af9597 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
2000-02-01 Richard Henderson <rth@cygnus.com>
+ * i386.c (general_no_elim_operand): New.
+ (nonmemory_no_elim_operand): New.
+ (ix86_expand_move): Copy eliminable operands before a push.
+ * i386-protos.h: Declare new functions.
+ * i386.h (CAN_ELIMINATE): Simplify.
+ (PREDICATE_CODES): Update.
+ * i386.md (push insns): Don't allow eliminable register operands.
+
+2000-02-01 Richard Henderson <rth@cygnus.com>
+
* flow.c (mark_regs_live_at_end): Follow expand_function_end and
replace BLKmode with DECL_RTL's mode.
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 9d40768..21dc139 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -50,6 +50,8 @@ extern int const1_operand PARAMS ((rtx, enum machine_mode));
extern int const248_operand PARAMS ((rtx, enum machine_mode));
extern int incdec_operand PARAMS ((rtx, enum machine_mode));
extern int reg_no_sp_operand PARAMS ((rtx, enum machine_mode));
+extern int general_no_elim_operand PARAMS ((rtx, enum machine_mode));
+extern int nonmemory_no_elim_operand PARAMS ((rtx, enum machine_mode));
extern int q_regs_operand PARAMS ((rtx, enum machine_mode));
extern int non_q_regs_operand PARAMS ((rtx, enum machine_mode));
extern int no_comparison_operator PARAMS ((rtx, enum machine_mode));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2030daa..18fc2f3 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1168,6 +1168,44 @@ reg_no_sp_operand (op, mode)
return register_operand (op, mode);
}
+/* Return false if this is any eliminable register. Otherwise
+ general_operand. */
+
+int
+general_no_elim_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ rtx t = op;
+ if (GET_CODE (t) == SUBREG)
+ t = SUBREG_REG (t);
+ if (t == arg_pointer_rtx || t == frame_pointer_rtx
+ || t == virtual_incoming_args_rtx || t == virtual_stack_vars_rtx
+ || t == virtual_stack_dynamic_rtx)
+ return 0;
+
+ return general_operand (op, mode);
+}
+
+/* Return false if this is any eliminable register. Otherwise
+ register_operand or const_int. */
+
+int
+nonmemory_no_elim_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ rtx t = op;
+ if (GET_CODE (t) == SUBREG)
+ t = SUBREG_REG (t);
+ if (t == arg_pointer_rtx || t == frame_pointer_rtx
+ || t == virtual_incoming_args_rtx || t == virtual_stack_vars_rtx
+ || t == virtual_stack_dynamic_rtx)
+ return 0;
+
+ return GET_CODE (op) == CONST_INT || register_operand (op, mode);
+}
+
/* Return true if op is a Q_REGS class register. */
int
@@ -3987,6 +4025,10 @@ ix86_expand_move (mode, operands)
&& GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (mode, operands[1]);
+ if (push_operand (operands[0], mode)
+ && ! general_no_elim_operand (operands[1], mode))
+ operands[1] = copy_to_mode_reg (mode, operands[1]);
+
if (FLOAT_MODE_P (mode))
{
/* If we are loading a floating point constant to a register,
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 95532c9..1302b65 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1411,19 +1411,13 @@ pop{l} %0" \
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \
-/* Given FROM and TO register numbers, say whether this elimination is allowed.
- Frame pointer elimination is automatically handled.
-
- For the i386, if frame pointer elimination is being done, we would like to
- convert ap into sp, not fp.
+/* Given FROM and TO register numbers, say whether this elimination is
+ allowed. Frame pointer elimination is automatically handled.
All other eliminations are valid. */
-#define CAN_ELIMINATE(FROM, TO) \
- ((((FROM) == ARG_POINTER_REGNUM || (FROM) == FRAME_POINTER_REGNUM) \
- && (TO) == STACK_POINTER_REGNUM) \
- ? ! frame_pointer_needed \
- : 1)
+#define CAN_ELIMINATE(FROM, TO) \
+ ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
/* Define the offset between two registers, one to be eliminated, and the other
its replacement, at the start of a routine. */
@@ -2436,6 +2430,9 @@ do { long l; \
{"const248_operand", {CONST_INT}}, \
{"incdec_operand", {CONST_INT}}, \
{"reg_no_sp_operand", {SUBREG, REG}}, \
+ {"general_no_elim_operand", {CONST_INT, CONST_DOUBLE, CONST, \
+ SYMBOL_REF, LABEL_REF, SUBREG, REG, MEM}}, \
+ {"nonmemory_no_elim_operand", {CONST_INT, REG, SUBREG}}, \
{"q_regs_operand", {SUBREG, REG}}, \
{"non_q_regs_operand", {SUBREG, REG}}, \
{"no_comparison_operator", {EQ, NE, LT, GE, LTU, GTU, LEU, GEU}}, \
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index fac96f5..ce2ac95 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1281,7 +1281,7 @@
(define_insn "pushsi2"
[(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_operand" "ri*m"))]
+ (match_operand:SI 1 "general_no_elim_operand" "ri*m"))]
""
"push{l}\\t%1"
[(set_attr "type" "push")])
@@ -1361,7 +1361,7 @@
(define_insn "pushhi2"
[(set (match_operand:HI 0 "push_operand" "=<,<")
- (match_operand:HI 1 "general_operand" "n,r*m"))]
+ (match_operand:HI 1 "general_no_elim_operand" "n,r*m"))]
""
"@
push{w}\\t{|WORD PTR }%1
@@ -1479,7 +1479,7 @@
(define_insn "pushqi2"
[(set (match_operand:QI 0 "push_operand" "=<,<")
- (match_operand:QI 1 "nonmemory_operand" "n,r"))]
+ (match_operand:QI 1 "nonmemory_no_elim_operand" "n,r"))]
""
"@
push{w}\\t{|word ptr }%1
@@ -1693,7 +1693,7 @@
(define_insn "*pushdi"
[(set (match_operand:DI 0 "push_operand" "=<")
- (match_operand:DI 1 "general_operand" "riF*m"))]
+ (match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
""
"#")
@@ -1727,7 +1727,7 @@
(define_insn "*pushsf"
[(set (match_operand:SF 0 "push_operand" "=<,<")
- (match_operand:SF 1 "general_operand" "f#r,rFm#f"))]
+ (match_operand:SF 1 "general_no_elim_operand" "f#r,rFm#f"))]
""
"*
{
@@ -1861,7 +1861,7 @@
(define_insn "*pushdf"
[(set (match_operand:DF 0 "push_operand" "=<,<")
- (match_operand:DF 1 "general_operand" "f#r,rFo#f"))]
+ (match_operand:DF 1 "general_no_elim_operand" "f#r,rFo#f"))]
""
"*
{
@@ -2057,7 +2057,7 @@
(define_insn "*pushxf_nointeger"
[(set (match_operand:XF 0 "push_operand" "=<,<,<")
- (match_operand:XF 1 "general_operand" "f,Fo,*r"))]
+ (match_operand:XF 1 "general_no_elim_operand" "f,Fo,*r"))]
"optimize_size"
"*
{
@@ -2085,7 +2085,7 @@
(define_insn "*pushxf_integer"
[(set (match_operand:XF 0 "push_operand" "=<,<")
- (match_operand:XF 1 "general_operand" "f#r,rFo#f"))]
+ (match_operand:XF 1 "general_no_elim_operand" "f#r,rFo#f"))]
"!optimize_size"
"*
{