Fix i386 code generation error reported by Mumit Khan.
authorJim Wilson <wilson@cygnus.com>
Tue, 2 Sep 1997 21:40:31 +0000 (21:40 +0000)
committerJim Wilson <wilson@gcc.gnu.org>
Tue, 2 Sep 1997 21:40:31 +0000 (14:40 -0700)
* local-alloc.c (contains_replace_regs): New function.
(update_equiv_regs): When adding a REG_EQUIV note for a set of a MEM,
verify that there is no existing REG_EQUIV note, and add a call to
contains_place_regs.

From-SVN: r15041

gcc/ChangeLog
gcc/local-alloc.c

index 94b896223ae804ee45a6315836da94732ddd8f46..d982628ace592f5b61cdb8c0a8ea75156cc79dea 100644 (file)
@@ -1,3 +1,10 @@
+Tue Sep  2 14:22:43 1997  Jim Wilson  <wilson@cygnus.com>
+
+       * local-alloc.c (contains_replace_regs): New function.
+       (update_equiv_regs): When adding a REG_EQUIV note for a set of a MEM,
+       verify that there is no existing REG_EQUIV note, and add a call to
+       contains_place_regs.
+
 Tue Sep  2 12:48:11 1997  H.J. Lu  (hjl@gnu.ai.mit.edu)
 
        * config/alpha/elf.h (CPP_PREDEFINES): Add -D__PIC__ -D__pic__.
index 677801e8696820d5107b0059651a75ffeba99e25..7a3e103c6bf61635a588b7fa7fcab6196760c94f 100644 (file)
@@ -246,6 +246,7 @@ static void alloc_qty               PROTO((int, enum machine_mode, int, int));
 static void alloc_qty_for_scratch PROTO((rtx, int, rtx, int, int));
 static void validate_equiv_mem_from_store PROTO((rtx, rtx));
 static int validate_equiv_mem  PROTO((rtx, rtx, rtx));
+static int contains_replace_regs PROTO((rtx, char *));
 static int memref_referenced_p PROTO((rtx, rtx));
 static int memref_used_between_p PROTO((rtx, rtx, rtx));
 static void optimize_reg_copy_1        PROTO((rtx, rtx, rtx));
@@ -600,6 +601,52 @@ validate_equiv_mem (start, reg, memref)
 
   return 0;
 }
+
+/* TRUE if X uses any registers for which reg_equiv_replace is true.  */
+
+static int
+contains_replace_regs (x, reg_equiv_replace)
+     rtx x;
+     char *reg_equiv_replace;
+{
+  int i, j;
+  char *fmt;
+  enum rtx_code code = GET_CODE (x);
+
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+    case CONST_DOUBLE:
+    case PC:
+    case CC0:
+    case HIGH:
+    case LO_SUM:
+      return 0;
+
+    case REG:
+      return reg_equiv_replace[REGNO (x)];
+    }
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    switch (fmt[i])
+      {
+      case 'e':
+       if (contains_replace_regs (XEXP (x, i), reg_equiv_replace))
+         return 1;
+       break;
+      case 'E':
+       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+         if (contains_replace_regs (XVECEXP (x, i, j), reg_equiv_replace))
+           return 1;
+       break;
+      }
+
+  return 0;
+}
 \f
 /* TRUE if X references a memory location that would be affected by a store
    to MEMREF.  */
@@ -1005,12 +1052,24 @@ update_equiv_regs ()
         in a single basic block, see if the register is always equivalent
         to that memory location and if moving the store from INSN to the
         insn that set REG is safe.  If so, put a REG_EQUIV note on the
-        initializing insn.  */
+        initializing insn.
+
+        Don't add a REG_EQUIV note if the insn already has one.  The existing
+        REG_EQUIV is likely more useful than the one we are adding.
+
+        If one of the regs in the address is marked as reg_equiv_replace,
+        then we can't add this REG_EQUIV note.  The reg_equiv_replace
+        optimization may move the set of this register immediately before
+        insn, which puts it after reg_equiv_init_insn[regno], and hence
+        the mention in the REG_EQUIV note would be to an uninitialized
+        pseudo.  */
 
       if (GET_CODE (dest) == MEM && GET_CODE (SET_SRC (set)) == REG
          && (regno = REGNO (SET_SRC (set))) >= FIRST_PSEUDO_REGISTER
          && REG_BASIC_BLOCK (regno) >= 0
          && reg_equiv_init_insn[regno] != 0
+         && ! find_reg_note (insn, REG_EQUIV, NULL_RTX)
+         && ! contains_replace_regs (XEXP (dest, 0), reg_equiv_replace)
          && validate_equiv_mem (reg_equiv_init_insn[regno], SET_SRC (set),
                                 dest)
          && ! memref_used_between_p (SET_DEST (set),