From: jakub Date: Mon, 27 Oct 2003 10:52:48 +0000 (+0000) Subject: * reload1.c (struct elim_table): Change offset, initial_offset and X-Git-Tag: upstream/4.9.2~75705 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ec96de93a5e8117a86cb6c7d50b45026a2416557;p=platform%2Fupstream%2Flinaro-gcc.git * reload1.c (struct elim_table): Change offset, initial_offset and previous_offset fields to HOST_WIDE_INT. (offsets_at): Change from int to HOST_WIDE_INT. (reload): Adjust offsets_at initialization. (eliminate_regs_in_insn): Change type of offset to HOST_WIDE_INT. (verify_initial_elim_offsets): Change type of t to HOST_WIDE_INT. * config/i386/i386.c (ix86_compute_frame_layout): Change offset type to HOST_WIDE_INT. Don't save regs using mov for huge frame sizes if TARGET_64BIT. (pro_epilogue_adjust_stack): New function. (ix86_expand_prologue, ix86_expand_epilogue): Use it. * config/i386/i386.md (pro_epilogue_adjust_stack): Remove. (pro_epilogue_adjust_stack_1): Remove * in front of name. (pro_epilogue_adjust_stack_rex64): Handle -2147483648 properly. (pro_epilogue_adjust_stack_rex64_2): New insn. * config/i386/i386.c (ix86_expand_epilogue): Fix comment typo. * config/i386/i386.c (ix86_expand_call): Replace 40 with FIRST_REX_INT_REG + 3 /* R11 */. * gcc.c-torture/compile/20031023-1.c: New test. * gcc.c-torture/compile/20031023-2.c: New test. * gcc.c-torture/compile/20031023-3.c: New test. * gcc.c-torture/compile/20031023-4.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@72975 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e9b2474..6bac398 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2003-10-27 Jakub Jelinek + Jan Hubicka + + * reload1.c (struct elim_table): Change offset, initial_offset and + previous_offset fields to HOST_WIDE_INT. + (offsets_at): Change from int to HOST_WIDE_INT. + (reload): Adjust offsets_at initialization. + (eliminate_regs_in_insn): Change type of offset to HOST_WIDE_INT. + (verify_initial_elim_offsets): Change type of t to HOST_WIDE_INT. + * config/i386/i386.c (ix86_compute_frame_layout): Change offset type + to HOST_WIDE_INT. Don't save regs using mov for huge frame sizes + if TARGET_64BIT. + (pro_epilogue_adjust_stack): New function. + (ix86_expand_prologue, ix86_expand_epilogue): Use it. + * config/i386/i386.md (pro_epilogue_adjust_stack): Remove. + (pro_epilogue_adjust_stack_1): Remove * in front of name. + (pro_epilogue_adjust_stack_rex64): Handle -2147483648 properly. + (pro_epilogue_adjust_stack_rex64_2): New insn. + + * config/i386/i386.c (ix86_expand_epilogue): Fix comment typo. + + * config/i386/i386.c (ix86_expand_call): Replace 40 with + FIRST_REX_INT_REG + 3 /* R11 */. + 2003-10-26 Richard Henderson * config/alpha/alpha.md (attr cannot_copy): New. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 8fdf24d..25240ac 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -4882,7 +4882,7 @@ ix86_compute_frame_layout (struct ix86_frame *frame) { HOST_WIDE_INT total_size; int stack_alignment_needed = cfun->stack_alignment_needed / BITS_PER_UNIT; - int offset; + HOST_WIDE_INT offset; int preferred_alignment = cfun->preferred_stack_boundary / BITS_PER_UNIT; HOST_WIDE_INT size = get_frame_size (); @@ -4998,7 +4998,8 @@ ix86_compute_frame_layout (struct ix86_frame *frame) (size + frame->padding1 + frame->padding2 + frame->outgoing_arguments_size + frame->va_arg_size); - if (!frame->to_allocate && frame->nregs <= 1) + if ((!frame->to_allocate && frame->nregs <= 1) + || (TARGET_64BIT && frame->to_allocate >= (HOST_WIDE_INT) 0x80000000)) frame->save_regs_using_mov = false; if (TARGET_RED_ZONE && current_function_sp_is_unchanging @@ -5065,6 +5066,41 @@ ix86_emit_save_regs_using_mov (rtx pointer, HOST_WIDE_INT offset) } } +/* Expand prologue or epilogue stack adjustement. + The pattern exist to put a dependency on all ebp-based memory accesses. + STYLE should be negative if instructions should be marked as frame related, + zero if %r11 register is live and cannot be freely used and positive + otherwise. */ + +static void +pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style) +{ + rtx insn; + + if (! TARGET_64BIT) + insn = emit_insn (gen_pro_epilogue_adjust_stack_1 (dest, src, offset)); + else if (x86_64_immediate_operand (offset, DImode)) + insn = emit_insn (gen_pro_epilogue_adjust_stack_rex64 (dest, src, offset)); + else + { + rtx r11; + /* r11 is used by indirect sibcall return as well, set before the + epilogue and used after the epilogue. ATM indirect sibcall + shouldn't be used together with huge frame sizes in one + function because of the frame_size check in sibcall.c. */ + if (style == 0) + abort (); + r11 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 /* R11 */); + insn = emit_insn (gen_rtx_SET (DImode, r11, offset)); + if (style < 0) + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_pro_epilogue_adjust_stack_rex64_2 (dest, src, r11, + offset)); + } + if (style < 0) + RTX_FRAME_RELATED_P (insn) = 1; +} + /* Expand the prologue into a bunch of separate insns. */ void @@ -5106,12 +5142,8 @@ ix86_expand_prologue (void) if (allocate == 0) ; else if (! TARGET_STACK_PROBE || allocate < CHECK_STACK_LIMIT) - { - insn = emit_insn (gen_pro_epilogue_adjust_stack - (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-allocate))); - RTX_FRAME_RELATED_P (insn) = 1; - } + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-allocate), -1); else { /* Only valid for Win32. */ @@ -5266,8 +5298,8 @@ ix86_expand_epilogue (int style) tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx); emit_move_insn (hard_frame_pointer_rtx, tmp); - emit_insn (gen_pro_epilogue_adjust_stack - (stack_pointer_rtx, sa, const0_rtx)); + pro_epilogue_adjust_stack (stack_pointer_rtx, sa, + const0_rtx, style); } else { @@ -5278,19 +5310,19 @@ ix86_expand_epilogue (int style) } } else if (!frame_pointer_needed) - emit_insn (gen_pro_epilogue_adjust_stack - (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (frame.to_allocate - + frame.nregs * UNITS_PER_WORD))); + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (frame.to_allocate + + frame.nregs * UNITS_PER_WORD), + style); /* If not an i386, mov & pop is faster than "leave". */ else if (TARGET_USE_LEAVE || optimize_size || !cfun->machine->use_fast_prologue_epilogue) emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ()); else { - emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx, - hard_frame_pointer_rtx, - const0_rtx)); + pro_epilogue_adjust_stack (stack_pointer_rtx, + hard_frame_pointer_rtx, + const0_rtx, style); if (TARGET_64BIT) emit_insn (gen_popdi1 (hard_frame_pointer_rtx)); else @@ -5305,14 +5337,13 @@ ix86_expand_epilogue (int style) { if (!frame_pointer_needed) abort (); - emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx, - hard_frame_pointer_rtx, - GEN_INT (offset))); + pro_epilogue_adjust_stack (stack_pointer_rtx, + hard_frame_pointer_rtx, + GEN_INT (offset), style); } else if (frame.to_allocate) - emit_insn (gen_pro_epilogue_adjust_stack - (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (frame.to_allocate))); + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (frame.to_allocate), style); for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (ix86_save_reg (regno, false)) @@ -5351,7 +5382,7 @@ ix86_expand_epilogue (int style) { rtx ecx = gen_rtx_REG (SImode, 2); - /* There are is no "pascal" calling convention in 64bit ABI. */ + /* There is no "pascal" calling convention in 64bit ABI. */ if (TARGET_64BIT) abort (); @@ -11594,7 +11625,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx callarg2, { rtx addr; addr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0)); - fnaddr = gen_rtx_REG (Pmode, 40); + fnaddr = gen_rtx_REG (Pmode, FIRST_REX_INT_REG + 3 /* R11 */); emit_move_insn (fnaddr, addr); fnaddr = gen_rtx_MEM (QImode, fnaddr); } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 835480d..f9acc04 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -17772,23 +17772,7 @@ ;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))] ;; ;; in proper program order. -(define_expand "pro_epilogue_adjust_stack" - [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_operand:SI 1 "register_operand" "0,r") - (match_operand:SI 2 "immediate_operand" "i,i"))) - (clobber (reg:CC 17)) - (clobber (mem:BLK (scratch)))])] - "" -{ - if (TARGET_64BIT) - { - emit_insn (gen_pro_epilogue_adjust_stack_rex64 - (operands[0], operands[1], operands[2])); - DONE; - } -}) - -(define_insn "*pro_epilogue_adjust_stack_1" +(define_insn "pro_epilogue_adjust_stack_1" [(set (match_operand:SI 0 "register_operand" "=r,r") (plus:SI (match_operand:SI 1 "register_operand" "0,r") (match_operand:SI 2 "immediate_operand" "i,i"))) @@ -17844,6 +17828,8 @@ case TYPE_ALU: if (GET_CODE (operands[2]) == CONST_INT + /* Avoid overflows. */ + && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) @@ -17870,6 +17856,30 @@ (const_string "lea"))) (set_attr "mode" "DI")]) +(define_insn "pro_epilogue_adjust_stack_rex64_2" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (plus:DI (match_operand:DI 1 "register_operand" "0,r") + (match_operand:DI 3 "immediate_operand" "i,i"))) + (use (match_operand:DI 2 "register_operand" "r,r")) + (clobber (reg:CC 17)) + (clobber (mem:BLK (scratch)))] + "TARGET_64BIT" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + return "add{q}\t{%2, %0|%0, %2}"; + + case TYPE_LEA: + operands[2] = gen_rtx_PLUS (DImode, operands[1], operands[2]); + return "lea{q}\t{%a2, %0|%0, %a2}"; + + default: + abort (); + } +} + [(set_attr "type" "alu,lea") + (set_attr "mode" "DI")]) ;; Placeholder for the conditional moves. This one is split either to SSE ;; based moves emulation or to usual cmove sequence. Little bit unfortunate diff --git a/gcc/reload1.c b/gcc/reload1.c index ecab52b..717489f 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -293,12 +293,12 @@ struct elim_table { int from; /* Register number to be eliminated. */ int to; /* Register number used as replacement. */ - int initial_offset; /* Initial difference between values. */ + HOST_WIDE_INT initial_offset; /* Initial difference between values. */ int can_eliminate; /* Nonzero if this elimination can be done. */ int can_eliminate_previous; /* Value of CAN_ELIMINATE in previous scan over insns made by reload. */ - int offset; /* Current offset between the two regs. */ - int previous_offset; /* Offset at end of previous insn. */ + HOST_WIDE_INT offset; /* Current offset between the two regs. */ + HOST_WIDE_INT previous_offset;/* Offset at end of previous insn. */ int ref_outside_mem; /* "to" has been referenced outside a MEM. */ rtx from_rtx; /* REG rtx for the register to be eliminated. We cannot simply compare the number since @@ -352,7 +352,7 @@ static int num_eliminable_invariants; static int first_label_num; static char *offsets_known_at; -static int (*offsets_at)[NUM_ELIMINABLE_REGS]; +static HOST_WIDE_INT (*offsets_at)[NUM_ELIMINABLE_REGS]; /* Number of labels in the current function. */ @@ -816,7 +816,7 @@ reload (rtx first, int global) allocate would occasionally cause it to exceed the stack limit and cause a core dump. */ offsets_known_at = xmalloc (num_labels); - offsets_at = xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (int)); + offsets_at = xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT)); /* Alter each pseudo-reg rtx to contain its hard reg number. Assign stack slots to the pseudos that lack hard regs or equivalents. @@ -2897,7 +2897,7 @@ eliminate_regs_in_insn (rtx insn, int replace) { rtx base = SET_SRC (old_set); rtx base_insn = insn; - int offset = 0; + HOST_WIDE_INT offset = 0; while (base != ep->to_rtx) { @@ -2980,7 +2980,7 @@ eliminate_regs_in_insn (rtx insn, int replace) && REGNO (XEXP (SET_SRC (old_set), 0)) < FIRST_PSEUDO_REGISTER) { rtx reg = XEXP (SET_SRC (old_set), 0); - int offset = INTVAL (XEXP (SET_SRC (old_set), 1)); + HOST_WIDE_INT offset = INTVAL (XEXP (SET_SRC (old_set), 1)); for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) if (ep->from_rtx == reg && ep->can_eliminate) @@ -3263,7 +3263,7 @@ mark_not_eliminable (rtx dest, rtx x, void *data ATTRIBUTE_UNUSED) static void verify_initial_elim_offsets (void) { - int t; + HOST_WIDE_INT t; #ifdef ELIMINABLE_REGS struct elim_table *ep; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 47a7512..5163837 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2003-10-27 Jakub Jelinek + + * gcc.c-torture/compile/20031023-1.c: New test. + * gcc.c-torture/compile/20031023-2.c: New test. + * gcc.c-torture/compile/20031023-3.c: New test. + * gcc.c-torture/compile/20031023-4.c: New test. + 2003-10-26 Kriang Lerdsuwanakij PR c++/10371 diff --git a/gcc/testsuite/gcc.c-torture/compile/20031023-1.c b/gcc/testsuite/gcc.c-torture/compile/20031023-1.c new file mode 100644 index 0000000..67f8ea9 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20031023-1.c @@ -0,0 +1,66 @@ +#ifndef ASIZE +# define ASIZE 0x10000000000UL +#endif + +#include + +#if LONG_MAX < 8 * ASIZE +# undef ASIZE +# define ASIZE 4096 +#endif + +extern void abort (void); + +int __attribute__((noinline)) +foo (const char *s) +{ + if (!s) + return 1; + if (s[0] != 'a') + abort (); + s += ASIZE - 1; + if (s[0] != 'b') + abort (); + return 0; +} + +int (*fn) (const char *) = foo; + +int __attribute__((noinline)) +bar (void) +{ + char s[ASIZE]; + s[0] = 'a'; + s[ASIZE - 1] = 'b'; + foo (s); + foo (s); + return 0; +} + +int __attribute__((noinline)) +baz (long i) +{ + if (i) + return fn (0); + else + { + char s[ASIZE]; + s[0] = 'a'; + s[ASIZE - 1] = 'b'; + foo (s); + foo (s); + return fn (0); + } +} + +int +main (void) +{ + if (bar ()) + abort (); + if (baz (0) != 1) + abort (); + if (baz (1) != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/20031023-2.c b/gcc/testsuite/gcc.c-torture/compile/20031023-2.c new file mode 100644 index 0000000..663e447 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20031023-2.c @@ -0,0 +1,2 @@ +#define ASIZE 0x1000000000UL +#include "20031023-1.c" diff --git a/gcc/testsuite/gcc.c-torture/compile/20031023-3.c b/gcc/testsuite/gcc.c-torture/compile/20031023-3.c new file mode 100644 index 0000000..f4a16c7 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20031023-3.c @@ -0,0 +1,2 @@ +#define ASIZE 0x100000000UL +#include "20031023-1.c" diff --git a/gcc/testsuite/gcc.c-torture/compile/20031023-4.c b/gcc/testsuite/gcc.c-torture/compile/20031023-4.c new file mode 100644 index 0000000..5c61f37 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20031023-4.c @@ -0,0 +1,2 @@ +#define ASIZE 0x80000000UL +#include "20031023-1.c"