gcse.c (run_jump_opt_after_gcse): New variable.
authorJeffrey A Law <law@cygnus.com>
Wed, 10 Mar 1999 19:45:18 +0000 (19:45 +0000)
committerJeff Law <law@gcc.gnu.org>
Wed, 10 Mar 1999 19:45:18 +0000 (12:45 -0700)
        * gcse.c (run_jump_opt_after_gcse): New variable.
        (gcse_main): Returns an integer.
        (hash_scan_set): Record initializations from CONST_DOUBLEs too.
        (try_replace_reg): Update some comments.
        (cprop_insn): Allow propagation into some JUMP_INSNs too.
        * rtl.h (gcse_main): Update prototype.
        * toplev.c (rest_of_compilation): If gcse_main returns nonzero,
        then run a jump optimization pass.
        * jump.c (delete_barrier_successors): Delete nop jumps too.

From-SVN: r25673

gcc/ChangeLog
gcc/gcse.c
gcc/jump.c
gcc/rtl.h
gcc/toplev.c

index 93012fe9303f4549d70f2c0091d5ee64e7d7f0b9..6c0b0c2bd2c5aab87713d36858d9dd810ebc56c9 100644 (file)
@@ -1,3 +1,15 @@
+Wed Mar 10 20:28:29 1999  Jeffrey A Law  (law@cygnus.com)
+
+       * gcse.c (run_jump_opt_after_gcse): New variable.
+       (gcse_main): Returns an integer.
+       (hash_scan_set): Record initializations from CONST_DOUBLEs too.
+       (try_replace_reg): Update some comments.
+       (cprop_insn): Allow propagation into some JUMP_INSNs too.
+       * rtl.h (gcse_main): Update prototype.
+       * toplev.c (rest_of_compilation): If gcse_main returns nonzero,
+       then run a jump optimization pass.
+       * jump.c (delete_barrier_successors): Delete nop jumps too.
+
 Wed Mar 10 19:04:31 1999  J"orn Rennecke <amylaar@cygnus.co.uk>
 
        * sh.c (fp_arith_reg_operand): Actually test if reg is suitable
index e9d4afae6613a46a6d0fceeb7b4b37313456868f..a80570400d8d55edcdcf7b978844b5c23885fbd8 100644 (file)
@@ -188,7 +188,7 @@ yyy
 
    4) Perform global cse.
 
-   5) Perform another pass of copy/constant propagation [only if PRE].
+   5) Perform another pass of copy/constant propagation.
 
    Two passes of copy/constant propagation are done because the first one
    enables more GCSE and the second one helps to clean up the copies that
@@ -333,6 +333,15 @@ static int_list_ptr *s_succs;
 static int *num_preds;
 static int *num_succs;
 
+/* Note whether or not we should run jump optimization after gcse.  We
+   want to do this for two cases.
+
+    * If we changed any jumps via cprop.
+
+    * If we added any labels via edge splitting.  */
+
+static int run_jump_opt_after_gcse;
+
 /* Hash table of expressions.  */
 
 struct expr
@@ -648,7 +657,7 @@ static void add_label_notes       PROTO ((rtx, rtx));
 /* Entry point for global common subexpression elimination.
    F is the first instruction in the function.  */
 
-void
+int
 gcse_main (f, file)
      rtx f;
      FILE *file;
@@ -661,10 +670,12 @@ gcse_main (f, file)
   /* Point to release obstack data from for each pass.  */
   char *gcse_obstack_bottom;
 
+  run_jump_opt_after_gcse = 0;
+
   /* It's impossible to construct a correct control flow graph in the
      presense of setjmp, so just punt to be safe.  */
   if (current_function_calls_setjmp)
-    return;
+    return 0;
    
   /* For calling dump_foo fns from gdb.  */
   debug_stderr = stderr;
@@ -677,7 +688,7 @@ gcse_main (f, file)
     {
       /* Free storage allocated by find_basic_blocks.  */
       free_basic_block_vars (0);
-      return;
+      return 0;
     }
 
   /* See what modes support reg/reg copy operations.  */
@@ -778,6 +789,7 @@ gcse_main (f, file)
   free_bb_mem ();
   /* Free storage allocated by find_basic_blocks.  */
   free_basic_block_vars (0);
+  return run_jump_opt_after_gcse;
 }
 \f
 /* Misc. utilities.  */
@@ -1800,7 +1812,8 @@ hash_scan_set (pat, insn, set_p)
                    && REGNO (src) >= FIRST_PSEUDO_REGISTER
                    && can_copy_p [GET_MODE (dest)])
                   /* ??? CONST_INT:wip */
-                  || GET_CODE (src) == CONST_INT)
+                  || GET_CODE (src) == CONST_INT
+                  || GET_CODE (src) == CONST_DOUBLE)
               /* A copy is not available if its src or dest is subsequently
                  modified.  Here we want to search from INSN+1 on, but
                  oprs_available_p searches from INSN on.  */
@@ -3690,6 +3703,11 @@ static int
 try_replace_reg (from, to, insn)
      rtx from, to, insn;
 {
+  /* If this fails we could try to simplify the result of the
+     replacement and attempt to recognize the simplified insn.
+
+     But we need a general simplify_rtx that doesn't have pass
+     specific state variables.  I'm not aware of one at the moment.  */
   return validate_replace_src (from, to, insn);
 }
 
@@ -3723,8 +3741,10 @@ cprop_insn (insn)
   struct reg_use *reg_used;
   int changed = 0;
 
-  /* ??? For now only propagate into SETs.  */
-  if (GET_CODE (insn) != INSN
+  /* Only propagate into SETs.  Note that a conditional jump is a
+     SET with pc_rtx as the destination.  */
+  if ((GET_CODE (insn) != INSN
+       && GET_CODE (insn) != JUMP_INSN)
       || GET_CODE (PATTERN (insn)) != SET)
     return 0;
 
@@ -3760,9 +3780,12 @@ cprop_insn (insn)
        abort ();
       src = SET_SRC (pat);
 
-      if (GET_CODE (src) == CONST_INT)
+      /* Constant propagation.  */
+      if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
        {
-         if (try_replace_reg (reg_used->reg_rtx, src, insn))
+         /* Handle normal insns first.  */
+         if (GET_CODE (insn) == INSN
+             && try_replace_reg (reg_used->reg_rtx, src, insn))
            {
              changed = 1;
              const_prop_count++;
@@ -3770,13 +3793,90 @@ cprop_insn (insn)
                {
                  fprintf (gcse_file, "CONST-PROP: Replacing reg %d in insn %d with constant ",
                           regno, INSN_UID (insn));
-                 fprintf (gcse_file, HOST_WIDE_INT_PRINT_DEC, INTVAL (src));
+                 print_rtl (gcse_file, src);
                  fprintf (gcse_file, "\n");
                }
 
              /* The original insn setting reg_used may or may not now be
                 deletable.  We leave the deletion to flow.  */
            }
+
+         /* Try to propagate a CONST_INT into a conditional jump.
+            We're pretty specific about what we will handle in this
+            code, we can extend this as necessary over time.
+
+            Right now the insn in question must look like
+
+            (set (pc) (if_then_else ...))
+
+            Note this does not currently handle machines which use cc0.  */
+         else if (GET_CODE (insn) == JUMP_INSN && condjump_p (insn))
+           {
+             /* We want a copy of the JUMP_INSN so we can modify it
+                in-place as needed without effecting the original.  */
+             rtx copy = copy_rtx (insn);
+             rtx set = PATTERN (copy);
+             rtx temp;
+
+             /* Replace the register with the appropriate constant.  */
+             replace_rtx (SET_SRC (set), reg_used->reg_rtx, src);
+
+             temp = simplify_ternary_operation (GET_CODE (SET_SRC (set)),
+                                                GET_MODE (SET_SRC (set)),
+                                                GET_MODE (XEXP (SET_SRC (set), 0)),
+                                                XEXP (SET_SRC (set), 0),
+                                                XEXP (SET_SRC (set), 1),
+                                                XEXP (SET_SRC (set), 2));
+
+             /* If no simplification can be made, then try the next
+                register.  */
+             if (temp)
+               SET_SRC (set) = temp;
+             else
+               continue;
+
+             /* That may have changed the structure of TEMP, so
+                force it to be rerecognized if it has not turned
+                into a nop or unconditional jump.  */
+               
+             INSN_CODE (copy) = -1;
+             if ((SET_DEST (set) == pc_rtx
+                  && (SET_SRC (set) == pc_rtx
+                      || GET_CODE (SET_SRC (set)) == LABEL_REF))
+                 || recog (PATTERN (copy), copy, NULL) >= 0)
+               {
+                 /* This has either become an unconditional jump
+                    or a nop-jump.  We'd like to delete nop jumps
+                    here, but doing so confuses gcse.  So we just
+                    make the replacement and let later passes
+                    sort things out.  */
+                 PATTERN (insn) = set;
+                 INSN_CODE (insn) = -1;
+
+                 /* One less use of the label this insn used to jump to
+                    if we turned this into a NOP jump.  */
+                 if (SET_SRC (set) == pc_rtx && JUMP_LABEL (insn) != 0)
+                   --LABEL_NUSES (JUMP_LABEL (insn));
+
+                 /* If this has turned into an unconditional jump,
+                    then put a barrier after it so that the unreachable
+                    code will be deleted.  */
+                 if (GET_CODE (SET_SRC (set)) == LABEL_REF)
+                   emit_barrier_after (insn);
+
+                 run_jump_opt_after_gcse = 1;
+
+                 changed = 1;
+                 const_prop_count++;
+                 if (gcse_file != NULL)
+                   {
+                     fprintf (gcse_file, "CONST-PROP: Replacing reg %d in insn %d with constant ",
+                              regno, INSN_UID (insn));
+                     print_rtl (gcse_file, src);
+                     fprintf (gcse_file, "\n");
+                   }
+               }
+           }
        }
       else if (GET_CODE (src) == REG
               && REGNO (src) >= FIRST_PSEUDO_REGISTER
index 7d25a97d3c5a6df29a07e37ea22865faa03a762c..4ffeeff3f2186f16e12ab7e6fda0c967303603be 100644 (file)
@@ -2076,7 +2076,9 @@ init_label_info (f)
   return largest_uid;
 }
 
-/* Delete insns following barriers, up to next label.  */
+/* Delete insns following barriers, up to next label. 
+
+   Also delete no-op jumps created by gcse.  */
 static void
 delete_barrier_successors (f)
      rtx f;
@@ -2098,6 +2100,14 @@ delete_barrier_successors (f)
            }
          /* INSN is now the code_label.  */
        }
+      /* Also remove (set (pc) (pc)) insns which can be created by
+        gcse.  We eliminate such insns now to avoid having them
+        cause problems later.  */
+      else if (GET_CODE (insn) == JUMP_INSN
+              && SET_SRC (PATTERN (insn)) == pc_rtx
+              && SET_DEST (PATTERN (insn)) == pc_rtx)
+       insn = delete_insn (insn);
+
       else
        insn = NEXT_INSN (insn);
     }
index bee3f052c3d2da9571d9e91854f0f822883be7c9..7f4460f19346051fba8544b6611be38fc081f715 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1452,7 +1452,7 @@ extern rtx expand_mult_highpart           PROTO ((enum machine_mode, rtx,
 
 /* In gcse.c */
 #ifdef BUFSIZ
-extern void gcse_main                  PROTO ((rtx, FILE *));
+extern int gcse_main                   PROTO ((rtx, FILE *));
 #endif
 
 /* In global.c */
index 2cc2885ca61f4ab25bcaee284e2ddea92e9d8490..f9a4c204ad13592aa8c1850e1e803a34ba787a9e 100644 (file)
@@ -3789,7 +3789,16 @@ rest_of_compilation (decl)
       if (gcse_dump)
        open_dump_file (".gcse", IDENTIFIER_POINTER (DECL_NAME (decl)));
 
-      TIMEVAR (gcse_time, gcse_main (insns, rtl_dump_file));
+      TIMEVAR (gcse_time, tem = gcse_main (insns, rtl_dump_file));
+
+      /* If gcse altered any jumps, rerun jump optimizations to clean
+        things up.  */
+      if (tem)
+       {
+         TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
+                                            !JUMP_NOOP_MOVES,
+                                            !JUMP_AFTER_REGSCAN));
+        }
 
       if (gcse_dump)
        {