emit-rtl.c (copy_most_rtx): Accept EXPR_LIST for may_share.
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>
Sat, 9 Mar 2002 12:53:21 +0000 (12:53 +0000)
committerRichard Kenner <kenner@gcc.gnu.org>
Sat, 9 Mar 2002 12:53:21 +0000 (07:53 -0500)
* emit-rtl.c (copy_most_rtx): Accept EXPR_LIST for may_share.
* function.c (fixup_var_refs): Add MAY_SHARE parameter.
(fixup_var_refs_insns, fixup_var_refs_insns_with_has): Likewise.
(fixup_var_refs_insn, fixup_var_refs_1): Likewise.
(pop_function_context): Compute MAY_SHARE parameter for
fixup_var_refs.
(fixup_var_refs_1, case MEM): Pass MAY_SHARE to copy_most_rtx, not VAR.
(gen_mem_addressof): Call fixup_var_refs with new parm.

From-SVN: r50493

gcc/ChangeLog
gcc/emit-rtl.c
gcc/function.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20020309-1.c [new file with mode: 0644]

index 897ff2e1d3549a2c01d58863a273ff3b38cb2864..559ab4f4fb1b1177c845399b3d6f1df7164f4d5c 100644 (file)
@@ -1,5 +1,14 @@
 Sat Mar  9 07:20:01 2002  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
+       * emit-rtl.c (copy_most_rtx): Accept EXPR_LIST for may_share.
+       * function.c (fixup_var_refs): Add MAY_SHARE parameter.
+       (fixup_var_refs_insns, fixup_var_refs_insns_with_has): Likewise.
+       (fixup_var_refs_insn, fixup_var_refs_1): Likewise.
+       (pop_function_context): Compute MAY_SHARE parameter for
+       fixup_var_refs.
+       (fixup_var_refs_1, case MEM): Pass MAY_SHARE to copy_most_rtx, not VAR.
+       (gen_mem_addressof): Call fixup_var_refs with new parm.
+
        * combine.c (make_extraction): Don't make extension of CONST_INT.
 
 2002-03-09  Alexandre Oliva  <aoliva@redhat.com>
index e3d557fe809881f79bd1b4a2166fb31c5bce5418..4d82afb68851b06adb101c3e625dbc2ee3f239e8 100644 (file)
@@ -2239,7 +2239,8 @@ reset_used_decls (blk)
 }
 
 /* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
-   placed in the result directly, rather than being copied.  */
+   placed in the result directly, rather than being copied.  MAY_SHARE is
+   either a MEM of an EXPR_LIST of MEMs.  */
 
 rtx
 copy_most_rtx (orig, may_share)
@@ -2251,7 +2252,9 @@ copy_most_rtx (orig, may_share)
   RTX_CODE code;
   const char *format_ptr;
 
-  if (orig == may_share)
+  if (orig == may_share
+      || (GET_CODE (may_share) == EXPR_LIST
+         && in_expr_list_p (may_share, orig)))
     return orig;
 
   code = GET_CODE (orig);
index 0d708ca92fa11ca10190e54b2b361f59b726ee61..f245a063a51a9d3bb9524ca5bc8bd791be03a54a 100644 (file)
@@ -239,19 +239,19 @@ static void put_reg_into_stack    PARAMS ((struct function *, rtx, tree,
 static void schedule_fixup_var_refs PARAMS ((struct function *, rtx, tree,
                                             enum machine_mode,
                                             struct hash_table *));
-static void fixup_var_refs     PARAMS ((rtx, enum machine_mode, int,
+static void fixup_var_refs     PARAMS ((rtx, enum machine_mode, int, rtx,
                                         struct hash_table *));
 static struct fixup_replacement
   *find_fixup_replacement      PARAMS ((struct fixup_replacement **, rtx));
 static void fixup_var_refs_insns PARAMS ((rtx, rtx, enum machine_mode,
-                                         int, int));
+                                         int, int, rtx));
 static void fixup_var_refs_insns_with_hash
                                PARAMS ((struct hash_table *, rtx,
-                                        enum machine_mode, int));
+                                        enum machine_mode, int, rtx));
 static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode,
-                                        int, int));
+                                        int, int, rtx));
 static void fixup_var_refs_1   PARAMS ((rtx, enum machine_mode, rtx *, rtx,
-                                        struct fixup_replacement **));
+                                        struct fixup_replacement **, rtx));
 static rtx fixup_memory_subreg PARAMS ((rtx, rtx, int));
 static rtx walk_fixup_memory_subreg  PARAMS ((rtx, rtx, int));
 static rtx fixup_stack_1       PARAMS ((rtx, rtx));
@@ -389,11 +389,29 @@ pop_function_context_from (context)
   if (restore_lang_status)
     (*restore_lang_status) (p);
 
-  /* Finish doing put_var_into_stack for any of our variables
-     which became addressable during the nested function.  */
-  for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
-    fixup_var_refs (queue->modified, queue->promoted_mode,
-                   queue->unsignedp, 0);
+  /* Finish doing put_var_into_stack for any of our variables which became
+     addressable during the nested function.  If only one entry has to be
+     fixed up, just do that one.  Otherwise, first make a list of MEMs that
+     are not to be unshared.  */
+  if (p->fixup_var_refs_queue == 0)
+    ;
+  else if (p->fixup_var_refs_queue->next == 0)
+    fixup_var_refs (p->fixup_var_refs_queue->modified,
+                   p->fixup_var_refs_queue->promoted_mode,
+                   p->fixup_var_refs_queue->unsignedp,
+                   p->fixup_var_refs_queue->modified, 0);
+  else
+    {
+      rtx list = 0;
+
+      for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
+       list = gen_rtx_EXPR_LIST (VOIDmode, queue->modified, list);
+
+      for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
+       fixup_var_refs (queue->modified, queue->promoted_mode,
+                       queue->unsignedp, list, 0);
+
+    }
 
   p->fixup_var_refs_queue = 0;
 
@@ -1525,15 +1543,16 @@ schedule_fixup_var_refs (function, reg, type, promoted_mode, ht)
     }
   else
     /* Variable is local; fix it up now.  */
-    fixup_var_refs (reg, promoted_mode, unsigned_p, ht);
+    fixup_var_refs (reg, promoted_mode, unsigned_p, reg, ht);
 }
 \f
 static void
-fixup_var_refs (var, promoted_mode, unsignedp, ht)
+fixup_var_refs (var, promoted_mode, unsignedp, may_share, ht)
      rtx var;
      enum machine_mode promoted_mode;
      int unsignedp;
      struct hash_table *ht;
+     rtx may_share;
 {
   tree pending;
   rtx first_insn = get_insns ();
@@ -1545,19 +1564,20 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
     {
       if (stack != 0)
        abort ();
-      fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp);
+      fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp,
+                                     may_share);
       return;
     }
 
   fixup_var_refs_insns (first_insn, var, promoted_mode, unsignedp,
-                       stack == 0);
+                       stack == 0, may_share);
 
   /* Scan all pending sequences too.  */
   for (; stack; stack = stack->next)
     {
       push_to_full_sequence (stack->first, stack->last);
       fixup_var_refs_insns (stack->first, var, promoted_mode, unsignedp,
-                           stack->next != 0);
+                           stack->next != 0, may_share);
       /* Update remembered end of sequence
         in case we added an insn at the end.  */
       stack->last = get_last_insn ();
@@ -1571,7 +1591,8 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
       if (seq != const0_rtx && seq != 0)
        {
          push_to_sequence (seq);
-         fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0);
+         fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0,
+                               may_share);
          end_sequence ();
        }
     }
@@ -1604,17 +1625,19 @@ find_fixup_replacement (replacements, x)
   return p;
 }
 
-/* Scan the insn-chain starting with INSN for refs to VAR
-   and fix them up.  TOPLEVEL is nonzero if this chain is the
-   main chain of insns for the current function.  */
+/* Scan the insn-chain starting with INSN for refs to VAR and fix them
+   up.  TOPLEVEL is nonzero if this chain is the main chain of insns
+   for the current function.  MAY_SHARE is either a MEM that is not
+   to be unshared or a list of them.  */
 
 static void
-fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
+fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel, may_share)
      rtx insn;
      rtx var;
      enum machine_mode promoted_mode;
      int unsignedp;
      int toplevel;
+     rtx may_share;
 {
   while (insn)
     {
@@ -1639,7 +1662,8 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
              if (seq)
                {
                  push_to_sequence (seq);
-                 fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0);
+                 fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0,
+                                       may_share);
                  XEXP (PATTERN (insn), i) = get_insns ();
                  end_sequence ();
                }
@@ -1647,7 +1671,8 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
        }
 
       else if (INSN_P (insn))
-       fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel);
+       fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel,
+                            may_share);
 
       insn = next;
     }
@@ -1661,25 +1686,22 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
    (inside the CALL_PLACEHOLDER).  */
 
 static void
-fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp)
+fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp, may_share)
      struct hash_table *ht;
      rtx var;
      enum machine_mode promoted_mode;
      int unsignedp;
+     rtx may_share;
 {
-  struct insns_for_mem_entry *ime = (struct insns_for_mem_entry *)
-    hash_lookup (ht, var, /*create=*/0, /*copy=*/0);
-  rtx insn_list = ime->insns;
-
-  while (insn_list)
-    {
-      rtx insn = XEXP (insn_list, 0);
-       
-      if (INSN_P (insn))
-       fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, 1);
-
-      insn_list = XEXP (insn_list, 1);
-    }
+  struct insns_for_mem_entry *ime
+    = (struct insns_for_mem_entry *) hash_lookup (ht, var,
+                                                 /*create=*/0, /*copy=*/0);
+  rtx insn_list;
+
+  for (insn_list = ime->insns; insn_list != 0; insn_list = XEXP (insn_list, 1))
+    if (INSN_P (XEXP (insn_list, 0)))
+      fixup_var_refs_insn (XEXP (insn_list, 0), var, promoted_mode,
+                          unsignedp, 1, may_share);
 }
 
 
@@ -1690,12 +1712,13 @@ fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp)
    function.  */
 
 static void
-fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
+fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
      rtx insn;
      rtx var;
      enum machine_mode promoted_mode;
      int unsignedp;
      int toplevel;
+     rtx no_share;
 {
   rtx call_dest = 0;
   rtx set, prev, prev_set;
@@ -1800,7 +1823,7 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
         it here.  */
 
       fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
-                       &replacements);
+                       &replacements, no_share);
 
       /* If this is last_parm_insn, and any instructions were output
         after it to fix it up, then we must set last_parm_insn to
@@ -1877,12 +1900,13 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
    or the SUBREG, as appropriate, to the pseudo.  */
 
 static void
-fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
+fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
      rtx var;
      enum machine_mode promoted_mode;
      rtx *loc;
      rtx insn;
      struct fixup_replacement **replacements;
+     rtx no_share;
 {
   int i;
   rtx x = *loc;
@@ -1979,7 +2003,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
        {
          replacement = find_fixup_replacement (replacements, x);
          if (replacement->new == 0)
-           replacement->new = copy_most_rtx (x, var);
+           replacement->new = copy_most_rtx (x, no_share);
 
          *loc = x = replacement->new;
          code = GET_CODE (x);
@@ -2116,7 +2140,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
          if (SUBREG_PROMOTED_VAR_P (x))
            {
              *loc = var;
-             fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements);
+             fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements,
+                               no_share);
              return;
            }
 
@@ -2222,11 +2247,11 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
            /* Since this case will return, ensure we fixup all the
               operands here.  */
            fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1),
-                             insn, replacements);
+                             insn, replacements, no_share);
            fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2),
-                             insn, replacements);
+                             insn, replacements, no_share);
            fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x),
-                             insn, replacements);
+                             insn, replacements, no_share);
 
            tem = XEXP (outerdest, 0);
 
@@ -2455,13 +2480,14 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-       fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements);
+       fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements,
+                         no_share);
       else if (fmt[i] == 'E')
        {
          int j;
          for (j = 0; j < XVECLEN (x, i); j++)
            fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j),
-                             insn, replacements);
+                             insn, replacements, no_share);
        }
     }
 }
@@ -2869,10 +2895,10 @@ gen_mem_addressof (reg, decl)
        SET_DECL_RTL (decl, reg);
 
       if (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0))
-       fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0);
+       fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), reg, 0);
     }
   else
-    fixup_var_refs (reg, GET_MODE (reg), 0, 0);
+    fixup_var_refs (reg, GET_MODE (reg), 0, reg, 0);
 
   return reg;
 }
index 1c069289aa8f5d79ce2ae6ee971286a2d245d167..2e1c449b0cc9fba164c26e5934e96c655420bcbc 100644 (file)
@@ -1,3 +1,7 @@
+Sat Mar  9 07:47:50 2002  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * gcc.c-torture/compile/20020309-1.c: New test.
+
 2002-03-08  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.c-torture/execute/20020307-2.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/compile/20020309-1.c b/gcc/testsuite/gcc.c-torture/compile/20020309-1.c
new file mode 100644 (file)
index 0000000..b740617
--- /dev/null
@@ -0,0 +1,14 @@
+int
+sub1 (char *p, int i)
+{
+  char j = p[i];
+
+  {
+    void
+    sub2 ()
+      {
+       i = 2;
+       p = p + 2;
+      }
+  }
+}