alpha.c (aligned_memory_operand): Handle out of range stack slots.
authorRichard Henderson <rth@cygnus.com>
Mon, 12 Apr 1999 03:11:37 +0000 (20:11 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 12 Apr 1999 03:11:37 +0000 (20:11 -0700)
        * alpha.c (aligned_memory_operand): Handle out of range stack slots.
        Take a new SCRATCH argument for the occasion.  Update all callers.
        (get_unaligned_address): Abort on out of range stack slots.
        * alpha.md (adddi3 splitter): Check s_p_rtx not REGNO.
        (reload_inqi): Check for aligned mems before unaligned.
        (reload_inhi): Likewise.

From-SVN: r26362

gcc/ChangeLog
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.md

index db5281d88f1c3a4b93864a71736a482ce9ae1be2..9178df129962ef24516ea8cb67b9fa754a4e2633 100644 (file)
@@ -1,3 +1,12 @@
+Mon Apr 12 03:07:44 1999  Richard Henderson  <rth@cygnus.com>
+
+       * alpha.c (aligned_memory_operand): Handle out of range stack slots.
+       Take a new SCRATCH argument for the occasion.  Update all callers.
+       (get_unaligned_address): Abort on out of range stack slots.
+       * alpha.md (adddi3 splitter): Check s_p_rtx not REGNO.
+       (reload_inqi): Check for aligned mems before unaligned.
+       (reload_inhi): Likewise.
+
 Mon Apr 12 03:11:30 1999  Jeffrey A Law  (law@cygnus.com)
 
        * flow.c (flow_delete_insn): If we delete a CODE_LABEL, also remove
index 85658361103f4c85a88357ca934af88498393910..1b7ecd365ebe730ca2a0ed2548c99540e094a08e 100644 (file)
@@ -728,11 +728,7 @@ divmod_operator (op, mode)
    a constant.  It must be a valid address.  This means that we can do
    this as an aligned reference plus some offset.
 
-   Take into account what reload will do.
-
-   We could say that out-of-range stack slots are alignable, but that would
-   complicate get_aligned_mem and it isn't worth the trouble since few
-   functions have large stack space.  */
+   Take into account what reload will do.  */
 
 int
 aligned_memory_operand (op, mode)
@@ -747,11 +743,18 @@ aligned_memory_operand (op, mode)
       mode = GET_MODE (op);
     }
 
-  if (reload_in_progress && GET_CODE (op) == REG
-      && REGNO (op) >= FIRST_PSEUDO_REGISTER)
-    op = reg_equiv_mem[REGNO (op)];
+  if (reload_in_progress)
+    {
+      /* This is a stack slot.  The stack pointer is always aligned.
+        We may have to jump through hoops to get a valid address,
+        but we can do it.  */
+      if (GET_CODE (op) == REG
+          && REGNO (op) >= FIRST_PSEUDO_REGISTER)
+       return 1;
+    }
 
-  if (GET_CODE (op) != MEM || GET_MODE (op) != mode
+  if (GET_CODE (op) != MEM
+      || GET_MODE (op) != mode
       || ! memory_address_p (mode, XEXP (op, 0)))
     return 0;
 
@@ -899,11 +902,12 @@ direct_return ()
 
 /* REF is an alignable memory location.  Place an aligned SImode
    reference into *PALIGNED_MEM and the number of bits to shift into
-   *PBITNUM.  */
+   *PBITNUM.  SCRATCH is a free register for use in reloading out
+   of range stack slots.  */
 
 void
-get_aligned_mem (ref, paligned_mem, pbitnum)
-     rtx ref;
+get_aligned_mem (ref, scratch, paligned_mem, pbitnum)
+     rtx ref, scratch;
      rtx *paligned_mem, *pbitnum;
 {
   rtx base;
@@ -919,13 +923,48 @@ get_aligned_mem (ref, paligned_mem, pbitnum)
       ref = SUBREG_REG (ref);
     }
 
-  if (GET_CODE (ref) == REG)
-    ref = reg_equiv_mem[REGNO (ref)];
-
   if (reload_in_progress)
-    base = find_replacement (&XEXP (ref, 0));
+    {
+      if (GET_CODE (ref) == REG)
+       {
+         /* The "simple" case is where the stack slot is in range.  */
+         if (reg_equiv_mem[REGNO (ref)])
+           {
+             ref = reg_equiv_mem[REGNO (ref)];
+             base = find_replacement (&XEXP (ref, 0));
+           }
+         else
+           {
+             /* The stack slot isn't in range.  Fix it up as needed.  */
+             HOST_WIDE_INT hi, lo;
+
+             base = reg_equiv_address[REGNO (ref)];
+             if (GET_CODE (base) != PLUS)
+               abort ();
+             offset += INTVAL (XEXP (base, 1));
+             base = XEXP (base, 0);
+
+             lo = ((offset & 0xFFFF) ^ 0x8000) - 0x8000;
+             hi = (((offset - lo) & 0xFFFFFFFF) ^ 0x80000000) - 0x80000000;
+             if (hi + lo != offset)
+               abort ();
+             if (scratch == NULL)
+               abort ();
+
+             emit_insn (gen_adddi3 (scratch, base, GEN_INT (hi)));
+             base = scratch;
+             offset = lo;
+           }
+       }
+      else
+       base = find_replacement (&XEXP (ref, 0));
+    }
   else
-    base = XEXP (ref, 0);
+    {
+      if (GET_CODE (ref) != MEM)
+       abort ();
+      base = XEXP (ref, 0);
+    }
 
   if (GET_CODE (base) == PLUS)
     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
@@ -962,13 +1001,27 @@ get_unaligned_address (ref, extra_offset)
       ref = SUBREG_REG (ref);
     }
 
-  if (GET_CODE (ref) == REG)
-    ref = reg_equiv_mem[REGNO (ref)];
-
   if (reload_in_progress)
-    base = find_replacement (&XEXP (ref, 0));
+    {
+      if (GET_CODE (ref) == REG)
+       {
+         if (reg_equiv_mem[REGNO (ref)])
+            ref = reg_equiv_mem[REGNO (ref)];
+         else
+           {
+             /* The stack slot is out of range.  We should have handled
+                this as an aligned access -- I wonder why we didn't? */
+             abort ();
+           }
+       }
+      base = find_replacement (&XEXP (ref, 0));
+    }
   else
-    base = XEXP (ref, 0);
+    {
+      if (GET_CODE (ref) != MEM)
+       abort ();
+      base = XEXP (ref, 0);
+    }
 
   if (GET_CODE (base) == PLUS)
     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
index 838cff0a998c2dc10ac0d35f97ad623af0c42805..7a2ce2fd032eea788bdfcb4f9ac55479b2598f1e 100644 (file)
        (plus:DI (match_operand:DI 1 "register_operand" "")
                 (match_operand:DI 2 "const_int_operand" "")))]
   "! add_operand (operands[2], DImode)
-   && REGNO (operands[0]) != STACK_POINTER_REGNUM"
+   && operands[0] != stack_pointer_rtx"
   [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 3)))
    (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
   "
                         ? gen_rtx_REG (SImode, REGNO (operands[0]))
                         : gen_reg_rtx (SImode));
 
-         get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+         get_aligned_mem (operands[1], scratch, &aligned_mem, &bitnum);
 
          emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum,
                                         scratch));
          rtx temp1 = gen_reg_rtx (SImode);
          rtx temp2 = gen_reg_rtx (SImode);
 
-         get_aligned_mem (operands[0], &aligned_mem, &bitnum);
+         get_aligned_mem (operands[0], NULL_RTX, &aligned_mem, &bitnum);
 
          emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
                                        temp1, temp2));
                         ? gen_rtx_REG (SImode, REGNO (operands[0]))
                         : gen_reg_rtx (SImode));
 
-         get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+         get_aligned_mem (operands[1], scratch, &aligned_mem, &bitnum);
 
          emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum,
                                         scratch));
          rtx temp1 = gen_reg_rtx (SImode);
          rtx temp2 = gen_reg_rtx (SImode);
 
-         get_aligned_mem (operands[0], &aligned_mem, &bitnum);
+         get_aligned_mem (operands[0], NULL_RTX, &aligned_mem, &bitnum);
 
          emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
                                        temp1, temp2));
   "! TARGET_BWX"
   "
 {
-  rtx addr = get_unaligned_address (operands[1], 0);
+  rtx scratch, seq;
 
-  /* It is possible that one of the registers we got for operands[2]
-     might coincide with that of operands[0] (which is why we made
-     it TImode).  Pick the other one to use as our scratch.  */
-  rtx scratch = gen_rtx_REG (DImode,
-                            REGNO (operands[0]) == REGNO (operands[2]) 
-                            ? REGNO (operands[2]) + 1 : REGNO (operands[2]));
+  if (aligned_memory_operand (operands[1], QImode))
+    {
+      rtx aligned_mem, bitnum;
 
-  rtx seq = gen_unaligned_loadqi (operands[0], addr, scratch,
-                                 gen_rtx_REG (DImode, REGNO (operands[0])));
+      get_aligned_mem (operands[1],
+                      gen_rtx_REG (DImode, REGNO (operands[2]) + 1),
+                      &aligned_mem, &bitnum);
+      seq = gen_aligned_loadqi (operands[0], aligned_mem, bitnum,
+                               gen_rtx_REG (SImode, REGNO (operands[2])));
+    }
+  else
+    {
+      rtx addr;
+
+      /* It is possible that one of the registers we got for operands[2]
+         might coincide with that of operands[0] (which is why we made
+         it TImode).  Pick the other one to use as our scratch.  */
+      if (REGNO (operands[0]) == REGNO (operands[2]))
+       scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
+      else
+       scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
 
+      addr = get_unaligned_address (operands[1], 0);
+      seq = gen_unaligned_loadqi (operands[0], addr, scratch,
+                                 gen_rtx_REG (DImode, REGNO (operands[0])));
+    }
   alpha_set_memflags (seq, operands[1]);
   emit_insn (seq);
   DONE;
 
 (define_expand "reload_inhi"
   [(parallel [(match_operand:HI 0 "register_operand" "=r")
-             (match_operand:HI 1 "unaligned_memory_operand" "m")
+             (match_operand:HI 1 "any_memory_operand" "m")
              (match_operand:TI 2 "register_operand" "=&r")])]
   "! TARGET_BWX"
   "
 {
-  rtx addr = get_unaligned_address (operands[1], 0);
+  rtx scratch, seq;
 
-  /* It is possible that one of the registers we got for operands[2]
-     might coincide with that of operands[0] (which is why we made
-     it TImode).  Pick the other one to use as our scratch.  */
-  rtx scratch = gen_rtx_REG (DImode,
-                            REGNO (operands[0]) == REGNO (operands[2]) 
-                            ? REGNO (operands[2]) + 1 : REGNO (operands[2]));
+  if (aligned_memory_operand (operands[1], HImode))
+    {
+      rtx aligned_mem, bitnum;
 
-  rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch,
-                                 gen_rtx_REG (DImode, REGNO (operands[0])));
+      get_aligned_mem (operands[1],
+                      gen_rtx_REG (DImode, REGNO (operands[2]) + 1),
+                      &aligned_mem, &bitnum);
+      seq = gen_aligned_loadhi (operands[0], aligned_mem, bitnum,
+                               gen_rtx_REG (SImode, REGNO (operands[2])));
+    }
+  else
+    {
+      rtx addr;
+
+      /* It is possible that one of the registers we got for operands[2]
+         might coincide with that of operands[0] (which is why we made
+         it TImode).  Pick the other one to use as our scratch.  */
+      if (REGNO (operands[0]) == REGNO (operands[2]))
+       scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
+      else
+       scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
 
+      addr = get_unaligned_address (operands[1], 0);
+      seq = gen_unaligned_loadhi (operands[0], addr, scratch,
+                                 gen_rtx_REG (DImode, REGNO (operands[0])));
+    }
   alpha_set_memflags (seq, operands[1]);
   emit_insn (seq);
   DONE;
     {
       rtx aligned_mem, bitnum;
 
-      get_aligned_mem (operands[0], &aligned_mem, &bitnum);
+      get_aligned_mem (operands[0], NULL_RTX, &aligned_mem, &bitnum);
 
       emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
                                    gen_rtx_REG (SImode, REGNO (operands[2])),
     {
       rtx aligned_mem, bitnum;
 
-      get_aligned_mem (operands[0], &aligned_mem, &bitnum);
+      get_aligned_mem (operands[0], NULL_RTX, &aligned_mem, &bitnum);
 
       emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
                                    gen_rtx_REG (SImode, REGNO (operands[2])),