diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 34 | ||||
-rw-r--r-- | gcc/expr.c | 139 | ||||
-rw-r--r-- | gcc/expr.h | 3 |
4 files changed, 111 insertions, 76 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3bfd0a6..f2b8704 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c431e85..6eae78c 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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 @@ -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, |