diff options
author | Richard Henderson <rth@cygnus.com> | 2000-02-01 23:50:21 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-02-01 23:50:21 -0800 |
commit | 2c5a510cb834f9d9c91d65ee40e568b2e33b6164 (patch) | |
tree | ceccc6e724603c079d5844d258770ae96c1ae2d9 /gcc | |
parent | ea2d416aac0d9e927f567c09617bd8c417b194a5 (diff) | |
download | gcc-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/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 42 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 17 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 16 |
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" "* { |