OSDN Git Service

* simplify-rtx.c (simplify_subreg): Adjust REG_OFFSET for
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 May 2006 05:35:21 +0000 (05:35 +0000)
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 May 2006 05:35:21 +0000 (05:35 +0000)
big-endian paradoxical subregs.
* var-tracking.c (struct micro_operation_def): Document that,
for modify micro operations, insn is the subsequent instruction.
(var_reg_delete_and_set, var_mem_delete_and_set): Split into...
(var_reg_set, var_mem_set): ... new functions.
(add_stores): Record subsequent insn.
(compute_bb_dataflow): Use new functions for MO_USE.
(emit_notes_in_bb): Use new functions for MO_USE.  Emit use
notes after the insn, and modify notes before the insn known
to be the subsequent one.
(vt_initialize): Invert sorting of MO_CLOBBERs and MO_SETs.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@114013 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/simplify-rtx.c
gcc/var-tracking.c

index 4da9ce4..18c97a9 100644 (file)
@@ -1,3 +1,18 @@
+2006-05-23  Alexandre Oliva  <aoliva@redhat.com>
+
+       * simplify-rtx.c (simplify_subreg): Adjust REG_OFFSET for
+       big-endian paradoxical subregs.
+       * var-tracking.c (struct micro_operation_def): Document that,
+       for modify micro operations, insn is the subsequent instruction.
+       (var_reg_delete_and_set, var_mem_delete_and_set): Split into...
+       (var_reg_set, var_mem_set): ... new functions.
+       (add_stores): Record subsequent insn.
+       (compute_bb_dataflow): Use new functions for MO_USE.
+       (emit_notes_in_bb): Use new functions for MO_USE.  Emit use
+       notes after the insn, and modify notes before the insn known
+       to be the subsequent one.
+       (vt_initialize): Invert sorting of MO_CLOBBERs and MO_SETs.
+
 2006-05-23  Kazu Hirata  <kazu@codesourcery.com>
 
        PR target/27696
index 6ab5cb7..7199316 100644 (file)
@@ -4552,7 +4552,22 @@ simplify_subreg (enum machine_mode outermode, rtx op,
       if (HARD_REGNO_MODE_OK (final_regno, outermode)
          || ! HARD_REGNO_MODE_OK (regno, innermode))
        {
-         rtx x = gen_rtx_REG_offset (op, outermode, final_regno, byte);
+         rtx x;
+         int final_offset = byte;
+
+         /* Adjust offset for paradoxical subregs.  */
+         if (byte == 0
+             && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode))
+           {
+             int difference = (GET_MODE_SIZE (innermode)
+                               - GET_MODE_SIZE (outermode));
+             if (WORDS_BIG_ENDIAN)
+               final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+             if (BYTES_BIG_ENDIAN)
+               final_offset += difference % UNITS_PER_WORD;
+           }
+
+         x = gen_rtx_REG_offset (op, outermode, final_regno, final_offset);
 
          /* Propagate original regno.  We don't have any way to specify
             the offset inside original regno, so do so only for lowpart.
index 7e910d6..704d2f5 100644 (file)
@@ -140,7 +140,11 @@ typedef struct micro_operation_def
     HOST_WIDE_INT adjust;
   } u;
 
-  /* The instruction which the micro operation is in.  */
+  /* The instruction which the micro operation is in, for MO_USE,
+     MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
+     instruction or note in the original flow (before any var-tracking
+     notes are inserted, to simplify emission of notes), for MO_SET
+     and MO_CLOBBER.  */
   rtx insn;
 } micro_operation;
 
@@ -291,9 +295,11 @@ static void vars_clear (htab_t);
 static variable unshare_variable (dataflow_set *set, variable var);
 static int vars_copy_1 (void **, void *);
 static void vars_copy (htab_t, htab_t);
+static void var_reg_set (dataflow_set *, rtx);
 static void var_reg_delete_and_set (dataflow_set *, rtx);
 static void var_reg_delete (dataflow_set *, rtx);
 static void var_regno_delete (dataflow_set *, int);
+static void var_mem_set (dataflow_set *, rtx);
 static void var_mem_delete_and_set (dataflow_set *, rtx);
 static void var_mem_delete (dataflow_set *, rtx);
 
@@ -792,6 +798,19 @@ vars_copy (htab_t dst, htab_t src)
   htab_traverse (src, vars_copy_1, dst);
 }
 
+/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  */
+
+static void
+var_reg_set (dataflow_set *set, rtx loc)
+{
+  tree decl = REG_EXPR (loc);
+  HOST_WIDE_INT offset = REG_OFFSET (loc);
+
+  if (set->regs[REGNO (loc)] == NULL)
+    attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
+  set_variable_part (set, loc, decl, offset);
+}
+
 /* Delete current content of register LOC in dataflow set SET
    and set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  */
 
@@ -819,9 +838,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc)
          nextp = &node->next;
        }
     }
-  if (set->regs[REGNO (loc)] == NULL)
-    attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
-  set_variable_part (set, loc, decl, offset);
+  var_reg_set (set, loc);
 }
 
 /* Delete current content of register LOC in dataflow set SET.  */
@@ -858,12 +875,12 @@ var_regno_delete (dataflow_set *set, int regno)
   *reg = NULL;
 }
 
-/* Delete and set the location part of variable MEM_EXPR (LOC)
-   in dataflow set SET to LOC.
+/* Set the location part of variable MEM_EXPR (LOC) in dataflow set
+   SET to LOC.
    Adjust the address first if it is stack pointer based.  */
 
 static void
-var_mem_delete_and_set (dataflow_set *set, rtx loc)
+var_mem_set (dataflow_set *set, rtx loc)
 {
   tree decl = MEM_EXPR (loc);
   HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
@@ -871,6 +888,16 @@ var_mem_delete_and_set (dataflow_set *set, rtx loc)
   set_variable_part (set, loc, decl, offset);
 }
 
+/* Delete and set the location part of variable MEM_EXPR (LOC)
+   in dataflow set SET to LOC.
+   Adjust the address first if it is stack pointer based.  */
+
+static void
+var_mem_delete_and_set (dataflow_set *set, rtx loc)
+{
+  var_mem_set (set, loc);
+}
+
 /* Delete the location part LOC from dataflow set SET.
    Adjust the address first if it is stack pointer based.  */
 
@@ -1547,7 +1574,7 @@ add_stores (rtx loc, rtx expr, void *insn)
                   && track_expr_p (REG_EXPR (loc)))
                  ? MO_SET : MO_CLOBBER);
       mo->u.loc = loc;
-      mo->insn = (rtx) insn;
+      mo->insn = NEXT_INSN ((rtx) insn);
     }
   else if (MEM_P (loc)
           && MEM_EXPR (loc)
@@ -1558,7 +1585,7 @@ add_stores (rtx loc, rtx expr, void *insn)
 
       mo->type = GET_CODE (expr) == CLOBBER ? MO_CLOBBER : MO_SET;
       mo->u.loc = loc;
-      mo->insn = (rtx) insn;
+      mo->insn = NEXT_INSN ((rtx) insn);
     }
 }
 
@@ -1589,6 +1616,16 @@ compute_bb_dataflow (basic_block bb)
            break;
 
          case MO_USE:
+           {
+             rtx loc = VTI (bb)->mos[i].u.loc;
+
+             if (GET_CODE (loc) == REG)
+               var_reg_set (out, loc);
+             else if (GET_CODE (loc) == MEM)
+               var_mem_set (out, loc);
+           }
+           break;
+
          case MO_SET:
            {
              rtx loc = VTI (bb)->mos[i].u.loc;
@@ -2356,6 +2393,18 @@ emit_notes_in_bb (basic_block bb)
            break;
 
          case MO_USE:
+           {
+             rtx loc = VTI (bb)->mos[i].u.loc;
+
+             if (GET_CODE (loc) == REG)
+               var_reg_set (&set, loc);
+             else
+               var_mem_set (&set, loc);
+
+             emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
+           }
+           break;
+
          case MO_SET:
            {
              rtx loc = VTI (bb)->mos[i].u.loc;
@@ -2365,10 +2414,7 @@ emit_notes_in_bb (basic_block bb)
              else
                var_mem_delete_and_set (&set, loc);
 
-             if (VTI (bb)->mos[i].type == MO_USE)
-               emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
-             else
-               emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
+             emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
            }
            break;
 
@@ -2383,9 +2429,9 @@ emit_notes_in_bb (basic_block bb)
                var_mem_delete (&set, loc);
 
              if (VTI (bb)->mos[i].type == MO_USE_NO_VAR)
-               emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
-             else
                emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
+             else
+               emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
            }
            break;
 
@@ -2598,15 +2644,18 @@ vt_initialize (void)
                }
 
              n1 = VTI (bb)->n_mos;
+             /* This will record NEXT_INSN (insn), such that we can
+                insert notes before it without worrying about any
+                notes that MO_USEs might emit after the insn.  */
              note_stores (PATTERN (insn), add_stores, insn);
              n2 = VTI (bb)->n_mos - 1;
 
-             /* Order the MO_SETs to be before MO_CLOBBERs.  */
+             /* Order the MO_CLOBBERs to be before MO_SETs.  */
              while (n1 < n2)
                {
-                 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_SET)
+                 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER)
                    n1++;
-                 while (n1 < n2 && VTI (bb)->mos[n2].type == MO_CLOBBER)
+                 while (n1 < n2 && VTI (bb)->mos[n2].type == MO_SET)
                    n2--;
                  if (n1 < n2)
                    {