reload1.c (struct elim_table): Change offset, initial_offset and previous_offset fields to HOST_WIDE_INT.
* 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. Co-Authored-By: Jan Hubicka <jh@suse.cz> From-SVN: r72975
This commit is contained in:
parent
501e79efe7
commit
b19ee4bd24
9 changed files with 194 additions and 50 deletions
|
@ -1,3 +1,27 @@
|
|||
2003-10-27 Jakub Jelinek <jakub@redhat.com>
|
||||
Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* 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 <rth@redhat.com>
|
||||
|
||||
* config/alpha/alpha.md (attr cannot_copy): New.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2003-10-27 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* 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 <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/10371
|
||||
|
|
66
gcc/testsuite/gcc.c-torture/compile/20031023-1.c
Normal file
66
gcc/testsuite/gcc.c-torture/compile/20031023-1.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef ASIZE
|
||||
# define ASIZE 0x10000000000UL
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#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;
|
||||
}
|
2
gcc/testsuite/gcc.c-torture/compile/20031023-2.c
Normal file
2
gcc/testsuite/gcc.c-torture/compile/20031023-2.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ASIZE 0x1000000000UL
|
||||
#include "20031023-1.c"
|
2
gcc/testsuite/gcc.c-torture/compile/20031023-3.c
Normal file
2
gcc/testsuite/gcc.c-torture/compile/20031023-3.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ASIZE 0x100000000UL
|
||||
#include "20031023-1.c"
|
2
gcc/testsuite/gcc.c-torture/compile/20031023-4.c
Normal file
2
gcc/testsuite/gcc.c-torture/compile/20031023-4.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ASIZE 0x80000000UL
|
||||
#include "20031023-1.c"
|
Loading…
Add table
Reference in a new issue