]> gcc.gnu.org Git - gcc.git/commitdiff
emit-rtl.c (subreg_hard_regno): Check that register is representable.
authorJan Hubicka <jh@suse.cz>
Thu, 17 Apr 2003 23:31:41 +0000 (01:31 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 17 Apr 2003 23:31:41 +0000 (23:31 +0000)
* emit-rtl.c (subreg_hard_regno):  Check that register is representable.
* reload.c (reload_inner_reg_of_subreg):  When register is not
representable, reload the whole thing.
(find_reloads): Likewsie.
* rtlanal.c (subreg_representable_p):  New function.

* profile.c (compute_branch_probabilities):  Cleanup sanity checking;
allow negative probabilities for edges from the call to exit.
(branch_prob): Do not add fake edges for functions that may return twice

From-SVN: r65757

gcc/ChangeLog
gcc/emit-rtl.c
gcc/profile.c
gcc/reload.c
gcc/rtl.h
gcc/rtlanal.c

index 71135aeb6889ed49df0b7740b14fb3434f4e55e7..7c393c51660885ebd55fb9afaa3547d59122312a 100644 (file)
@@ -1,3 +1,15 @@
+Fri Apr 18 01:28:51 CEST 2003  Jan Hubicka  <jh@suse.cz>
+
+       * emit-rtl.c (subreg_hard_regno):  Check that register is representable.
+       * reload.c (reload_inner_reg_of_subreg):  When register is not
+       representable, reload the whole thing.
+       (find_reloads): Likewsie.
+       * rtlanal.c (subreg_representable_p):  New function.
+
+       * profile.c (compute_branch_probabilities):  Cleanup sanity checking;
+       allow negative probabilities for edges from the call to exit.
+       (branch_prob): Do not add fake edges for functions that may return twice
+
 2003-04-17  DJ Delorie  <dj@redhat.com>
 
        * toplev.c (target_options): Add value field.
index 058100c07726e1b3674c8256c177039ed40cada5..7048aee61dfe5fefa3ea557f481b1635e9151981 100644 (file)
@@ -1081,7 +1081,11 @@ subreg_hard_regno (x, check_mode)
     abort ();
   if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
     abort ();
-
+#ifdef ENABLE_CHECKING
+  if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg),
+                                     SUBREG_BYTE (x), mode))
+    abort ();
+#endif
   /* Catch non-congruent offsets too.  */
   byte_offset = SUBREG_BYTE (x);
   if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
index 99ddd3bc7d49e25c99fee028ac74be90d08737f5..afabe20a42f95036a33134a169b3afc28b05185b 100644 (file)
@@ -674,22 +674,47 @@ compute_branch_probabilities ()
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
       edge e;
-      gcov_type total;
       rtx note;
 
-      total = bb->count;
-      if (total)
+      if (bb->count < 0)
        {
-         for (e = bb->succ; e; e = e->succ_next)
+         error ("corrupted profile info: number of iterations for basic block %d thought to be %i",
+                bb->index, (int)bb->count);
+         bb->count = 0;
+       }
+      for (e = bb->succ; e; e = e->succ_next)
+       {
+         /* Function may return twice in the cased the called fucntion is
+            setjmp or calls fork, but we can't represent this by extra
+            edge from the entry, since extra edge from the exit is
+            already present.  We get negative frequency from the entry
+            point.  */
+         if ((e->count < 0
+              && e->dest == EXIT_BLOCK_PTR)
+             || (e->count > bb->count
+                 && e->dest != EXIT_BLOCK_PTR))
            {
-               e->probability = (e->count * REG_BR_PROB_BASE + total / 2) / total;
-               if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
-                 {
-                   error ("corrupted profile info: prob for %d-%d thought to be %d",
-                          e->src->index, e->dest->index, e->probability);
-                   e->probability = REG_BR_PROB_BASE / 2;
-                 }
+             rtx insn = bb->end;
+
+             while (GET_CODE (insn) != CALL_INSN
+                    && insn != bb->head
+                    && keep_with_call_p (insn))
+               insn = PREV_INSN (insn);
+             if (GET_CODE (insn) == CALL_INSN)
+               e->count = e->count < 0 ? 0 : bb->count;
            }
+         if (e->count < 0 || e->count > bb->count)
+           {
+             error ("corrupted profile info: number of executions for edge %d-%d thought to be %i",
+                    e->src->index, e->dest->index,
+                    (int)e->count);
+             e->count = bb->count / 2;
+           }
+       }
+      if (bb->count)
+       {
+         for (e = bb->succ; e; e = e->succ_next)
+           e->probability = (e->count * REG_BR_PROB_BASE + bb->count / 2) / bb->count;
          if (bb->index >= 0
              && any_condjump_p (bb->end)
              && bb->succ->succ_next)
@@ -730,6 +755,8 @@ compute_branch_probabilities ()
         calls).  */
       else
        {
+         int total = 0;
+
          for (e = bb->succ; e; e = e->succ_next)
            if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
              total ++;
@@ -873,36 +900,13 @@ branch_prob ()
     {
       int need_exit_edge = 0, need_entry_edge = 0;
       int have_exit_edge = 0, have_entry_edge = 0;
-      rtx insn;
       edge e;
 
-      /* Add fake edges from entry block to the call insns that may return
-        twice.  The CFG is not quite correct then, as call insn plays more
-        role of CODE_LABEL, but for our purposes, everything should be OK,
-        as we never insert code to the beginning of basic block.  */
-      for (insn = bb->head; insn != NEXT_INSN (bb->end);
-          insn = NEXT_INSN (insn))
-       {
-         if (GET_CODE (insn) == CALL_INSN
-             && find_reg_note (insn, REG_SETJMP, NULL))
-           {
-             if (GET_CODE (bb->head) == CODE_LABEL
-                 || insn != NEXT_INSN (bb->head))
-               {
-                 e = split_block (bb, PREV_INSN (insn));
-                 make_edge (ENTRY_BLOCK_PTR, e->dest, EDGE_FAKE);
-                 break;
-               }
-             else
-               {
-                 /* We should not get abort here, as call to setjmp should not
-                    be the very first instruction of function.  */
-                 if (bb == ENTRY_BLOCK_PTR)
-                   abort ();
-                 make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
-               }
-           }
-       }
+      /* Functions returning multiple times are not handled by extra edges.
+         Instead we simply allow negative counts on edges from exit to the
+         block past call and corresponding probabilities.  We can't go
+         with the extra edges because that would result in flowgraph that
+        needs to have fake edges outside the spanning tree.  */
 
       for (e = bb->succ; e; e = e->succ_next)
        {
index e360e26c0daeb6a4e0547225bc0e938d8136f825..bc3c1771d972ca38cc2ea4492cd3a411a47286e4 100644 (file)
@@ -2880,6 +2880,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              if (GET_CODE (SUBREG_REG (operand)) == REG
                  && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
                {
+                 if (!subreg_offset_representable_p
+                       (REGNO (SUBREG_REG (operand)),
+                        GET_MODE (SUBREG_REG (operand)),
+                        SUBREG_BYTE (operand),
+                        GET_MODE (operand)))
+                    force_reload = 1;
                  offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
                                                 GET_MODE (SUBREG_REG (operand)),
                                                 SUBREG_BYTE (operand),
@@ -2935,26 +2941,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                          )
 #endif
                      )
-                 /* This following hunk of code should no longer be
-                    needed at all with SUBREG_BYTE.  If you need this
-                    code back, please explain to me why so I can
-                    fix the real problem.  -DaveM */
-#if 0
-                 /* Subreg of a hard reg which can't handle the subreg's mode
-                    or which would handle that mode in the wrong number of
-                    registers for subregging to work.  */
-                 || (GET_CODE (operand) == REG
-                     && REGNO (operand) < FIRST_PSEUDO_REGISTER
-                     && ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
-                          && (GET_MODE_SIZE (GET_MODE (operand))
-                              > UNITS_PER_WORD)
-                          && ((GET_MODE_SIZE (GET_MODE (operand))
-                               / UNITS_PER_WORD)
-                              != HARD_REGNO_NREGS (REGNO (operand),
-                                                   GET_MODE (operand))))
-                         || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
-                                                  operand_mode[i])))
-#endif
                  )
                force_reload = 1;
            }
@@ -5272,6 +5258,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
                                                       SUBREG_BYTE (orig_op1),
                                                       GET_MODE (orig_op1))));
          }
+       /* Plus in the index register may be created only as a result of
+          register remateralization for expresion like &localvar*4.  Reload it.
+          It may be possible to combine the displacement on the outer level,
+          but it is probably not worthwhile to do so.  */
+       if (context)
+         {
+           find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
+                                 opnum, ADDR_TYPE (type), ind_levels, insn);
+           push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
+                        (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+                        GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+           return 1;
+         }
 
        if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
            || code0 == ZERO_EXTEND || code1 == MEM)
index eb78ba6d1764154ae647ea5541f8617c9878629b..b78e9e78db38881075e17ee7afdbe1ac550931c7 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1038,6 +1038,10 @@ extern unsigned int subreg_regno_offset  PARAMS ((unsigned int,
                                                         enum machine_mode, 
                                                         unsigned int, 
                                                         enum machine_mode));
+extern bool subreg_offset_representable_p      PARAMS ((unsigned int, 
+                                                        enum machine_mode, 
+                                                        unsigned int, 
+                                                        enum machine_mode));
 extern unsigned int subreg_regno       PARAMS ((rtx));
 
 /* 1 if RTX is a subreg containing a reg that is already known to be
index f7923c2a87dbea55087c0498834e7c67cc1c25e3..3b024adc89d0402dba162b420c19a858b27dc72e 100644 (file)
@@ -3387,6 +3387,77 @@ subreg_regno_offset (xregno, xmode, offset, ymode)
   return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
 }
 
+/* This function returns true when the offset is representable via
+   subreg_offset in the given regno.
+   xregno - A regno of an inner hard subreg_reg (or what will become one).
+   xmode  - The mode of xregno.
+   offset - The byte offset.
+   ymode  - The mode of a top level SUBREG (or what may become one).
+   RETURN - The regno offset which would be used.  */
+bool
+subreg_offset_representable_p (xregno, xmode, offset, ymode)
+     unsigned int xregno;
+     enum machine_mode xmode;
+     unsigned int offset;
+     enum machine_mode ymode;
+{
+  int nregs_xmode, nregs_ymode;
+  int mode_multiple, nregs_multiple;
+  int y_offset;
+
+  if (xregno >= FIRST_PSEUDO_REGISTER)
+    abort ();
+
+  nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
+  nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
+
+  /* paradoxical subregs are always valid.  */
+  if (offset == 0
+      && nregs_ymode > nregs_xmode
+      && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
+         ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+    return true;
+
+  /* Lowpart subregs are always valid.  */
+  if (offset == subreg_lowpart_offset (ymode, xmode))
+    return true;
+
+#ifdef ENABLE_CHECKING
+  /* This should always pass, otherwise we don't know how to verify the
+     constraint. 
+
+     These conditions may be relaxed but subreg_offset would need to be
+     redesigned.  */
+  if (GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode)
+      || GET_MODE_SIZE (ymode) % nregs_ymode
+      || mode_for_size (GET_MODE_SIZE (ymode) / nregs_ymode,
+                       MODE_INT, 0) == VOIDmode
+      || nregs_xmode % nregs_ymode)
+    abort ();
+#endif
+
+  /* The XMODE value can be seen as an vector of NREGS_XMODE
+     values.  The subreg must represent an lowpart of given field.
+     Compute what field it is.  */
+  offset -= subreg_lowpart_offset (mode_for_size (GET_MODE_SIZE (ymode)
+                                                 / nregs_ymode,
+                                                 MODE_INT, 0), xmode);
+
+  /* size of ymode must not be greater than the size of xmode.  */
+  mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
+  if (mode_multiple == 0)
+    abort ();
+
+  y_offset = offset / GET_MODE_SIZE (ymode);
+  nregs_multiple =  nregs_xmode / nregs_ymode;
+#ifdef ENABLE_CHECKING
+  if (offset % GET_MODE_SIZE (ymode)
+      || mode_multiple % nregs_multiple)
+    abort ();
+#endif
+  return (!(y_offset % (mode_multiple / nregs_multiple)));
+}
+
 /* Return the final regno that a subreg expression refers to.  */
 unsigned int
 subreg_regno (x)
This page took 0.082142 seconds and 5 git commands to generate.