i386.md (pophi1, [...]): Remove.
* i386.md (pophi1, popqi1, pushqi1): Remove. * expr.c (emit_single_push_insn): New function. (move_by_pieces): Accept NULL as destination for push instructions. (gen_push_operand): Kill. (emit_push_insn): Pass NULL when pushing; avoid updating of stack_pointer_delta. * expr.h (gen_push_operand): Kill. From-SVN: r40686
This commit is contained in:
parent
d5c960a0e8
commit
566aa17469
@ -1,3 +1,14 @@
|
||||
Wed Mar 21 10:25:13 CET 2001 Jan Hubicka <jh@use.cz>
|
||||
|
||||
* i386.md (pophi1, popqi1, pushqi1): Remove.
|
||||
|
||||
* expr.c (emit_single_push_insn): New function.
|
||||
(move_by_pieces): Accept NULL as destination for push instructions.
|
||||
(gen_push_operand): Kill.
|
||||
(emit_push_insn): Pass NULL when pushing; avoid updating of
|
||||
stack_pointer_delta.
|
||||
* expr.h (gen_push_operand): Kill.
|
||||
|
||||
Tue Mar 20 20:15:06 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* rtl.texi (COMPARE): Clarify documentation and reference section
|
||||
|
@ -1745,16 +1745,6 @@
|
||||
[(set_attr "type" "push")
|
||||
(set_attr "mode" "HI")])
|
||||
|
||||
(define_insn "*pophi1"
|
||||
[(set (match_operand:HI 0 "nonimmediate_operand" "=r*m")
|
||||
(mem:HI (reg:SI 7)))
|
||||
(set (reg:SI 7)
|
||||
(plus:SI (reg:SI 7) (const_int 2)))]
|
||||
"!TARGET_64BIT"
|
||||
"pop{w}\\t%0"
|
||||
[(set_attr "type" "pop")
|
||||
(set_attr "mode" "HI")])
|
||||
|
||||
(define_insn "*movhi_1"
|
||||
[(set (match_operand:HI 0 "nonimmediate_operand" "=*a,r,r,*a,r,m")
|
||||
(match_operand:HI 1 "general_operand" "i,r,rn,rm,rm,rn"))]
|
||||
@ -1868,30 +1858,6 @@
|
||||
""
|
||||
"ix86_expand_move (QImode, operands); DONE;")
|
||||
|
||||
;; emit_push_insn when it calls move_by_pieces requires an insn to
|
||||
;; "push a byte". But actually we use pushw, which has the effect
|
||||
;; of rounding the amount pushed up to a halfword.
|
||||
|
||||
(define_insn "*pushqi2"
|
||||
[(set (match_operand:QI 0 "push_operand" "=<,<")
|
||||
(match_operand:QI 1 "nonmemory_no_elim_operand" "n,r"))]
|
||||
"!TARGET_64BIT"
|
||||
"@
|
||||
push{w}\\t{|word ptr }%1
|
||||
push{w}\\t%w1"
|
||||
[(set_attr "type" "push")
|
||||
(set_attr "mode" "HI")])
|
||||
|
||||
(define_insn "*popqi1"
|
||||
[(set (match_operand:QI 0 "nonimmediate_operand" "=r*m")
|
||||
(mem:QI (reg:SI 7)))
|
||||
(set (reg:SI 7)
|
||||
(plus:SI (reg:SI 7) (const_int 2)))]
|
||||
"!TARGET_64BIT"
|
||||
"pop{w}\\t%0"
|
||||
[(set_attr "type" "pop")
|
||||
(set_attr "mode" "HI")])
|
||||
|
||||
;; Situation is quite tricky about when to choose full sized (SImode) move
|
||||
;; over QImode moves. For Q_REG -> Q_REG move we use full size only for
|
||||
;; partial register dependency machines (such as AMD Athlon), where QImode
|
||||
|
139
gcc/expr.c
139
gcc/expr.c
@ -174,6 +174,7 @@ static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
|
||||
static void do_compare_and_jump PARAMS ((tree, enum rtx_code, enum rtx_code,
|
||||
rtx, rtx));
|
||||
static rtx do_store_flag PARAMS ((tree, rtx, enum machine_mode, int));
|
||||
static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
|
||||
|
||||
/* Record for each mode whether we can move a register directly to or
|
||||
from an object of that mode in memory. If we can't, we won't try
|
||||
@ -1387,6 +1388,10 @@ convert_modes (mode, oldmode, x, unsignedp)
|
||||
from block FROM to block TO. (These are MEM rtx's with BLKmode).
|
||||
The caller must pass FROM and TO
|
||||
through protect_from_queue before calling.
|
||||
|
||||
When TO is NULL, the emit_single_push_insn is used to push the
|
||||
FROM to stack.
|
||||
|
||||
ALIGN is maximum alignment we can assume. */
|
||||
|
||||
void
|
||||
@ -1396,19 +1401,36 @@ move_by_pieces (to, from, len, align)
|
||||
unsigned int align;
|
||||
{
|
||||
struct move_by_pieces data;
|
||||
rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
|
||||
rtx to_addr, from_addr = XEXP (from, 0);
|
||||
unsigned int max_size = MOVE_MAX_PIECES + 1;
|
||||
enum machine_mode mode = VOIDmode, tmode;
|
||||
enum insn_code icode;
|
||||
|
||||
data.offset = 0;
|
||||
data.to_addr = to_addr;
|
||||
data.from_addr = from_addr;
|
||||
data.to = to;
|
||||
if (to)
|
||||
{
|
||||
to_addr = XEXP (to, 0);
|
||||
data.to = to;
|
||||
data.autinc_to
|
||||
= (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
|
||||
|| GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
|
||||
data.reverse
|
||||
= (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
|
||||
}
|
||||
else
|
||||
{
|
||||
to_addr = NULL_RTX;
|
||||
data.to = NULL_RTX;
|
||||
data.autinc_to = 1;
|
||||
#ifdef STACK_GROWS_DOWNWARD
|
||||
data.reverse = 1;
|
||||
#else
|
||||
data.reverse = 0;
|
||||
#endif
|
||||
}
|
||||
data.to_addr = to_addr;
|
||||
data.from = from;
|
||||
data.autinc_to
|
||||
= (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
|
||||
|| GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
|
||||
data.autinc_from
|
||||
= (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
|
||||
|| GET_CODE (from_addr) == POST_INC
|
||||
@ -1416,8 +1438,6 @@ move_by_pieces (to, from, len, align)
|
||||
|
||||
data.explicit_inc_from = 0;
|
||||
data.explicit_inc_to = 0;
|
||||
data.reverse
|
||||
= (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
|
||||
if (data.reverse) data.offset = len;
|
||||
data.len = len;
|
||||
|
||||
@ -1550,14 +1570,17 @@ move_by_pieces_1 (genfun, mode, data)
|
||||
if (data->reverse)
|
||||
data->offset -= size;
|
||||
|
||||
if (data->autinc_to)
|
||||
if (data->to)
|
||||
{
|
||||
to1 = gen_rtx_MEM (mode, data->to_addr);
|
||||
MEM_COPY_ATTRIBUTES (to1, data->to);
|
||||
if (data->autinc_to)
|
||||
{
|
||||
to1 = gen_rtx_MEM (mode, data->to_addr);
|
||||
MEM_COPY_ATTRIBUTES (to1, data->to);
|
||||
}
|
||||
else
|
||||
to1 = change_address (data->to, mode,
|
||||
plus_constant (data->to_addr, data->offset));
|
||||
}
|
||||
else
|
||||
to1 = change_address (data->to, mode,
|
||||
plus_constant (data->to_addr, data->offset));
|
||||
|
||||
if (data->autinc_from)
|
||||
{
|
||||
@ -1573,7 +1596,10 @@ move_by_pieces_1 (genfun, mode, data)
|
||||
if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
|
||||
emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
|
||||
|
||||
emit_insn ((*genfun) (to1, from1));
|
||||
if (data->to)
|
||||
emit_insn ((*genfun) (to1, from1));
|
||||
else
|
||||
emit_single_push_insn (mode, from1, NULL);
|
||||
|
||||
if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
|
||||
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
|
||||
@ -3078,11 +3104,6 @@ push_block (size, extra, below)
|
||||
return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
|
||||
}
|
||||
|
||||
rtx
|
||||
gen_push_operand ()
|
||||
{
|
||||
return gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
|
||||
}
|
||||
|
||||
/* Return an rtx for the address of the beginning of a as-if-it-was-pushed
|
||||
block of SIZE bytes. */
|
||||
@ -3103,6 +3124,51 @@ get_push_address (size)
|
||||
return copy_to_reg (temp);
|
||||
}
|
||||
|
||||
/* Emit single push insn. */
|
||||
static void
|
||||
emit_single_push_insn (mode, x, type)
|
||||
rtx x;
|
||||
enum machine_mode mode;
|
||||
tree type;
|
||||
{
|
||||
#ifdef PUSH_ROUNDING
|
||||
rtx dest_addr;
|
||||
int rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
|
||||
rtx dest;
|
||||
|
||||
if (GET_MODE_SIZE (mode) == rounded_size)
|
||||
dest_addr = gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
|
||||
else
|
||||
{
|
||||
#ifdef STACK_GROWS_DOWNWARD
|
||||
dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
|
||||
GEN_INT (-rounded_size));
|
||||
#else
|
||||
dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
|
||||
GEN_INT (rounded_size));
|
||||
#endif
|
||||
dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
|
||||
}
|
||||
|
||||
dest = gen_rtx_MEM (mode, dest_addr);
|
||||
|
||||
stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
|
||||
|
||||
if (type != 0)
|
||||
{
|
||||
set_mem_attributes (dest, type, 1);
|
||||
/* Function incoming arguments may overlap with sibling call
|
||||
outgoing arguments and we cannot allow reordering of reads
|
||||
from function arguments with stores to outgoing arguments
|
||||
of sibling calls. */
|
||||
MEM_ALIAS_SET (dest) = 0;
|
||||
}
|
||||
emit_move_insn (dest, x);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Generate code to push X onto the stack, assuming it has mode MODE and
|
||||
type TYPE.
|
||||
MODE is redundant except when X is a CONST_INT (since they don't
|
||||
@ -3223,9 +3289,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
|
||||
&& where_pad != none && where_pad != stack_direction)
|
||||
anti_adjust_stack (GEN_INT (extra));
|
||||
|
||||
stack_pointer_delta += INTVAL (size) - used;
|
||||
move_by_pieces (gen_rtx_MEM (BLKmode, gen_push_operand ()), xinner,
|
||||
INTVAL (size) - used, align);
|
||||
move_by_pieces (NULL, xinner, INTVAL (size) - used, align);
|
||||
|
||||
if (current_function_check_memory_usage && ! in_check_memory_usage)
|
||||
{
|
||||
@ -3477,10 +3541,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
|
||||
|
||||
#ifdef PUSH_ROUNDING
|
||||
if (args_addr == 0 && PUSH_ARGS)
|
||||
{
|
||||
addr = gen_push_operand ();
|
||||
stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
|
||||
}
|
||||
emit_single_push_insn (mode, x, type);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@ -3493,20 +3554,20 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
|
||||
addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
|
||||
args_so_far));
|
||||
target = addr;
|
||||
}
|
||||
dest = gen_rtx_MEM (mode, addr);
|
||||
if (type != 0)
|
||||
{
|
||||
set_mem_attributes (dest, type, 1);
|
||||
/* Function incoming arguments may overlap with sibling call
|
||||
outgoing arguments and we cannot allow reordering of reads
|
||||
from function arguments with stores to outgoing arguments
|
||||
of sibling calls. */
|
||||
MEM_ALIAS_SET (dest) = 0;
|
||||
}
|
||||
|
||||
dest = gen_rtx_MEM (mode, addr);
|
||||
if (type != 0)
|
||||
{
|
||||
set_mem_attributes (dest, type, 1);
|
||||
/* Function incoming arguments may overlap with sibling call
|
||||
outgoing arguments and we cannot allow reordering of reads
|
||||
from function arguments with stores to outgoing arguments
|
||||
of sibling calls. */
|
||||
MEM_ALIAS_SET (dest) = 0;
|
||||
}
|
||||
emit_move_insn (dest, x);
|
||||
|
||||
emit_move_insn (dest, x);
|
||||
}
|
||||
|
||||
if (current_function_check_memory_usage && ! in_check_memory_usage)
|
||||
{
|
||||
|
@ -1040,9 +1040,6 @@ extern rtx emit_move_insn_1 PARAMS ((rtx, rtx));
|
||||
and return an rtx to address the beginning of the block. */
|
||||
extern rtx push_block PARAMS ((rtx, int, int));
|
||||
|
||||
/* Make an operand to push something on the stack. */
|
||||
extern rtx gen_push_operand PARAMS ((void));
|
||||
|
||||
#ifdef TREE_CODE
|
||||
/* Generate code to push something onto the stack, given its mode and type. */
|
||||
extern void emit_push_insn PARAMS ((rtx, enum machine_mode, tree, rtx,
|
||||
|
Loading…
Reference in New Issue
Block a user