* reload1.c (struct elim_table): Change offset, initial_offset and
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 27 Oct 2003 10:52:48 +0000 (10:52 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 27 Oct 2003 10:52:48 +0000 (10:52 +0000)
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

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/reload1.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20031023-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/compile/20031023-2.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/compile/20031023-3.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/compile/20031023-4.c [new file with mode: 0644]

index e9b2474..6bac398 100644 (file)
@@ -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.
index 8fdf24d..25240ac 100644 (file)
@@ -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);
     }
index 835480d..f9acc04 100644 (file)
 ;; [(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")))
 
     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)))
              (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
index ecab52b..717489f 100644 (file)
@@ -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 < &reg_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;
index 47a7512..5163837 100644 (file)
@@ -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
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 (file)
index 0000000..67f8ea9
--- /dev/null
@@ -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;
+}
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 (file)
index 0000000..663e447
--- /dev/null
@@ -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 (file)
index 0000000..f4a16c7
--- /dev/null
@@ -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 (file)
index 0000000..5c61f37
--- /dev/null
@@ -0,0 +1,2 @@
+#define ASIZE 0x80000000UL
+#include "20031023-1.c"