OSDN Git Service

*** empty log message ***
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 5 Apr 1992 16:34:53 +0000 (16:34 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 5 Apr 1992 16:34:53 +0000 (16:34 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@688 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cse.c
gcc/flags.h
gcc/toplev.c

index 04f638f..4552cac 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -2858,7 +2858,7 @@ simplify_unary_operation (code, mode, op, op_mode)
          break;
 
        case ABS:
-         if (REAL_VALUES_LESS (d, 0.0))
+         if (REAL_VALUE_NEGATIVE (d))
            d = REAL_VALUE_NEGATE (d);
          break;
 
@@ -3860,7 +3860,9 @@ simplify_relational_operation (code, mode, op0, op1)
            if (CONSTANT_P (op0) && op1 == const0_rtx)
              return const0_rtx;
 #endif
-           if (NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx)
+           if (NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx
+               /* On some machines, the ap reg can be 0 sometimes.  */
+               && op0 != arg_pointer_rtx)
              return const0_rtx;
            break;
          }
@@ -3871,7 +3873,9 @@ simplify_relational_operation (code, mode, op0, op1)
          if (CONSTANT_P (op0) && op1 == const0_rtx)
            return const_true_rtx;
 #endif
-         if (NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx)
+         if (NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx
+             /* On some machines, the ap reg can be 0 sometimes.  */
+             && op0 != arg_pointer_rtx)
            return const_true_rtx;
          break;
 
@@ -6577,6 +6581,65 @@ cse_around_loop (loop_start)
     }
 }
 \f
+/* Variable used for communications between the next two routines.  */
+
+static struct write_data skipped_writes_memory;
+
+/* Process one SET of an insn that was skipped.  We ignore CLOBBERs
+   since they are done elsewhere.  This function is called via note_stores.  */
+
+static void
+invalidate_skipped_set (dest, set)
+     rtx set;
+     rtx dest;
+{
+  if (GET_CODE (set) == CLOBBER
+#ifdef HAVE_cc0
+      || dest == cc0_rtx
+#endif
+      || dest == pc_rtx)
+    return;
+
+  if (GET_CODE (dest) == MEM)
+    note_mem_written (dest, &skipped_writes_memory);
+
+  if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
+      || (! skipped_writes_memory.all && ! cse_rtx_addr_varies_p (dest)))
+    invalidate (dest);
+}
+
+/* Invalidate all insns from START up to the end of the function or the
+   next label.  This called when we wish to CSE around a block that is
+   conditionally executed.  */
+
+static void
+invalidate_skipped_block (start)
+     rtx start;
+{
+  rtx insn;
+  int i;
+  static struct write_data init = {0, 0, 0, 0};
+  static struct write_data everything = {0, 1, 1, 1};
+
+  for (insn = start; insn && GET_CODE (insn) != CODE_LABEL;
+       insn = NEXT_INSN (insn))
+    {
+      if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+       continue;
+
+      skipped_writes_memory = init;
+
+      if (GET_CODE (insn) == CALL_INSN)
+       {
+         invalidate_for_call ();
+         skipped_writes_memory = everything;
+       }
+
+      note_stores (PATTERN (insn), invalidate_skipped_set);
+      invalidate_from_clobbers (&skipped_writes_memory, PATTERN (insn));
+    }
+}
+\f
 /* Used for communication between the following two routines; contains a
    value to be checked for modification.  */
 
@@ -6706,7 +6769,7 @@ cse_set_around_loop (x, insn, loop_start)
    The branch path indicates which branches should be followed.  If a non-zero
    path size is specified, the block should be rescanned and a different set
    of branches will be taken.  The branch path is only used if
-   FLAG_CSE_FOLLOW_JUMPS is non-zero.
+   FLAG_CSE_FOLLOW_JUMPS or FLAG_CSE_SKIP_BLOCKS is non-zero.
 
    DATA is a pointer to a struct cse_basic_block_data, defined below, that is
    used to describe the block.  It is filled in with the information about
@@ -6732,17 +6795,20 @@ struct cse_basic_block_data {
   struct branch_path {
     /* The branch insn. */
     rtx branch;
-    /* Whether it should be taken or not.  */
-    enum taken {TAKEN, NOT_TAKEN} status;
+    /* Whether it should be taken or not.  AROUND is the same as taken
+       except that it is used when the destination label is not preceded
+       by a BARRIER.  */
+    enum taken {TAKEN, NOT_TAKEN, AROUND} status;
   } path[PATHLENGTH];
 };
 
 void
-cse_end_of_basic_block (insn, data, follow_jumps, after_loop)
+cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
      rtx insn;
      struct cse_basic_block_data *data;
      int follow_jumps;
      int after_loop;
+     int skip_blocks;
 {
   rtx p = insn, q;
   int nsets = 0;
@@ -6757,7 +6823,7 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop)
      at least one branch must have been taken if PATH_SIZE is non-zero.  */
   while (path_size > 0)
     {
-      if (data->path[path_size - 1].status == TAKEN)
+      if (data->path[path_size - 1].status != NOT_TAKEN)
        {
          data->path[path_size - 1].status = NOT_TAKEN;
          break;
@@ -6802,15 +6868,15 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop)
        nsets += 1;
        
       if (INSN_CUID (p) > high_cuid)
-        high_cuid = INSN_CUID (p);
+       high_cuid = INSN_CUID (p);
       if (INSN_CUID (p) < low_cuid)
-        low_cuid = INSN_CUID(p);
+       low_cuid = INSN_CUID(p);
 
       /* See if this insn is in our branch path.  If it is and we are to
         take it, do so.  */
       if (path_entry < path_size && data->path[path_entry].branch == p)
        {
-         if (data->path[path_entry].status == TAKEN)
+         if (data->path[path_entry].status != NOT_TAKEN)
            p = JUMP_LABEL (p);
          
          /* Point to next entry in path, if any.  */
@@ -6820,8 +6886,14 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop)
       /* If this is a conditional jump, we can follow it if -fcse-follow-jumps
         was specified, we haven't reached our maximum path length, there are
         insns following the target of the jump, this is the only use of the
-        jump label, and the target label is preceded by a BARRIER.  */
-      else if (follow_jumps && path_size < PATHLENGTH - 1
+        jump label, and the target label is preceded by a BARRIER.
+
+        Alternatively, we can follow the jump if it branches around a
+        block of code and there are no other branches into the block.
+        In this case invalidate_skipped_block will be called to invalidate any
+        registers set in the block when following the jump.  */
+
+      else if ((follow_jumps || skip_blocks) && path_size < PATHLENGTH - 1
               && GET_CODE (p) == JUMP_INSN
               && GET_CODE (PATTERN (p)) == SET
               && GET_CODE (SET_SRC (PATTERN (p))) == IF_THEN_ELSE
@@ -6837,7 +6909,7 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop)
 
          /* If we ran into a BARRIER, this code is an extension of the
             basic block when the branch is taken.  */
-         if (q != 0 && GET_CODE (q) == BARRIER)
+         if (follow_jumps && q != 0 && GET_CODE (q) == BARRIER)
            {
              /* Don't allow ourself to keep walking around an
                 always-executed loop.  */
@@ -6865,8 +6937,40 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop)
              /* Mark block so we won't scan it again later.  */
              PUT_MODE (NEXT_INSN (p), QImode);
            }
+         /* Detect a branch around a block of code.  */
+         else if (skip_blocks && q != 0 && GET_CODE (q) != CODE_LABEL)
+           {
+             register rtx tmp;
+
+             if (next_real_insn (q) == next_real_insn (insn))
+               break;
+
+             for (i = 0; i < path_entry; i++)
+               if (data->path[i].branch == p)
+                 break;
+
+             if (i != path_entry)
+               break;
+
+             /* This is no_labels_between_p (p, q) with an added check for
+                reaching the end of a function (in case Q precedes P).  */
+             for (tmp = NEXT_INSN (p); tmp && tmp != q; tmp = NEXT_INSN (tmp))
+               if (GET_CODE (tmp) == CODE_LABEL)
+                 break;
+             
+             if (tmp == q)
+               {
+                 data->path[path_entry].branch = p;
+                 data->path[path_entry++].status = AROUND;
+
+                 path_size = path_entry;
+
+                 p = JUMP_LABEL (p);
+                 /* Mark block so we won't scan it again later.  */
+                 PUT_MODE (NEXT_INSN (p), QImode);
+               }
+           }
        }
-       
       p = NEXT_INSN (p);
     }
 
@@ -6878,7 +6982,7 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop)
   /* If all jumps in the path are not taken, set our path length to zero
      so a rescan won't be done.  */
   for (i = path_size - 1; i >= 0; i--)
-    if (data->path[i].status == TAKEN)
+    if (data->path[i].status != NOT_TAKEN)
       break;
 
   if (i == -1)
@@ -6998,9 +7102,8 @@ cse_main (f, nregs, after_loop, file)
   insn = f;
   while (insn)
     {
-      int tem;
-
-      cse_end_of_basic_block (insn, &val, flag_cse_follow_jumps, after_loop);
+      cse_end_of_basic_block (insn, &val, flag_cse_follow_jumps, after_loop,
+                             flag_cse_skip_blocks);
 
       /* If this basic block was already processed or has no sets, skip it.  */
       if (val.nsets == 0 || GET_MODE (insn) == QImode)
@@ -7042,7 +7145,8 @@ cse_main (f, nregs, after_loop, file)
             us a new branch path to investigate.  */
          cse_jumps_altered = 0;
          temp = cse_basic_block (insn, val.last, val.path, ! after_loop);
-         if (cse_jumps_altered == 0 || flag_cse_follow_jumps == 0)
+         if (cse_jumps_altered == 0
+             || (flag_cse_follow_jumps == 0 && flag_cse_skip_blocks == 0))
            insn = temp;
 
          cse_jumps_altered |= old_cse_jumps_altered;
@@ -7116,9 +7220,14 @@ cse_basic_block (from, to, next_branch, around_loop)
         to be taken, do so.  */
       if (next_branch->branch == insn)
        {
-         if (next_branch++->status == TAKEN)
+         enum taken status = next_branch++->status;
+         if (status != NOT_TAKEN)
            {
-             record_jump_equiv (insn, 1);
+             if (status == TAKEN)
+               record_jump_equiv (insn, 1);
+             else
+               invalidate_skipped_block (NEXT_INSN (insn));
+
              /* Set the last insn as the jump insn; it doesn't affect cc0.
                 Then follow this branch.  */
 #ifdef HAVE_cc0
@@ -7200,7 +7309,7 @@ cse_basic_block (from, to, next_branch, around_loop)
 
          to_usage = 0;
          val.path_size = 0;
-         cse_end_of_basic_block (insn, &val, 0, 0);
+         cse_end_of_basic_block (insn, &val, 0, 0, 0);
 
          /* If the tables we allocated have enough space left
             to handle all the SETs in the next basic block,
@@ -7230,7 +7339,8 @@ cse_basic_block (from, to, next_branch, around_loop)
      we can cse into the loop.  Don't do this if we changed the jump
      structure of a loop unless we aren't going to be following jumps.  */
 
-  if ((cse_jumps_altered == 0 || flag_cse_follow_jumps == 0)
+  if ((cse_jumps_altered == 0
+       || (flag_cse_follow_jumps == 0 && flag_cse_skip_blocks == 0))
       && around_loop && to != 0
       && GET_CODE (to) == NOTE && NOTE_LINE_NUMBER (to) == NOTE_INSN_LOOP_END
       && GET_CODE (PREV_INSN (to)) == JUMP_INSN
index 747e7c4..868b3e3 100644 (file)
@@ -192,6 +192,11 @@ extern int flag_unroll_all_loops;
 
 extern int flag_cse_follow_jumps;
 
+/* Nonzero for -fcse-skip-blocks:
+   have cse follow a branch around a block.  */
+
+extern int flag_cse_skip_blocks;
+
 /* Nonzero for -fexpensive-optimizations:
    perform miscellaneous relatively-expensive optimizations.  */
 extern int flag_expensive_optimizations;
@@ -220,6 +225,13 @@ extern int flag_no_peephole;
 
 extern int flag_volatile;
 
+/* Nonzero allows GCC to violate some IEEE or ANSI rules regarding math
+   operations in the interest of optimization.  For example it allows
+   GCC to assume arguments to sqrt are nonnegative numbers, allowing
+   faster code for sqrt to be generated. */
+
+extern int flag_fast_math;
+
 /* Nonzero means make functions that look like good inline candidates
    go inline.  */
 
index d7164d8..eb1d278 100644 (file)
@@ -293,6 +293,10 @@ int flag_float_store = 0;
 
 int flag_cse_follow_jumps;
 
+/* Nonzero for -fcse-skip-blocks:
+   have cse follow a branch around a block.  */
+int flag_cse_skip_blocks;
+
 /* Nonzero for -fexpensive-optimizations:
    perform miscellaneous relatively-expensive optimizations.  */
 int flag_expensive_optimizations;
@@ -451,6 +455,7 @@ struct { char *string; int *variable; int on_value;} f_options[] =
   {"defer-pop", &flag_defer_pop, 1},
   {"omit-frame-pointer", &flag_omit_frame_pointer, 1},
   {"cse-follow-jumps", &flag_cse_follow_jumps, 1},
+  {"cse-skip-blocks", &flag_cse_skip_blocks, 1},
   {"expensive-optimizations", &flag_expensive_optimizations, 1},
   {"thread-jumps", &flag_thread_jumps, 1},
   {"strength-reduce", &flag_strength_reduce, 1},
@@ -2593,6 +2598,7 @@ main (argc, argv, envp)
   if (optimize >= 2)
     {
       flag_cse_follow_jumps = 1;
+      flag_cse_skip_blocks = 1;
       flag_expensive_optimizations = 1;
       flag_strength_reduce = 1;
       flag_rerun_cse_after_loop = 1;