OSDN Git Service

* combine.c (check_promoted_subreg, record_promoted_value): New
authordavem <davem@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 6 Dec 1999 19:45:38 +0000 (19:45 +0000)
committerdavem <davem@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 6 Dec 1999 19:45:38 +0000 (19:45 +0000)
functions.
(combine_instructions): Use them to retain nonzero and sign bit
information after SUBREGs are eliminated by optimizations in
this pass if PROMOTE_FUNCTION_RETURN.

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

gcc/ChangeLog
gcc/combine.c

index f2c3181..119a1db 100644 (file)
        always use move_by_pieces to avoid infinite recursion.
        (restore_fixed_argument_area): Likewise.
 
+       * combine.c (check_promoted_subreg, record_promoted_value): New
+       functions.
+       (combine_instructions): Use them to retain nonzero and sign bit
+       information after SUBREGs are eliminated by optimizations in
+       this pass if PROMOTE_FUNCTION_RETURN.
+
 Mon Dec  6 12:24:52 1999  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * fold-const.c (optimize_bit_field_compare): Only use one mode
index f55bb66..825d8a7 100644 (file)
@@ -403,6 +403,9 @@ static enum rtx_code simplify_comparison  PROTO((enum rtx_code, rtx *, rtx *));
 static int reversible_comparison_p  PROTO((rtx));
 static void update_table_tick  PROTO((rtx));
 static void record_value_for_reg  PROTO((rtx, rtx, rtx));
+#ifdef PROMOTE_FUNCTION_RETURN
+static void check_promoted_subreg PROTO((rtx, rtx));
+#endif
 static void record_dead_and_set_regs_1  PROTO((rtx, rtx, void *));
 static void record_dead_and_set_regs  PROTO((rtx));
 static int get_last_value_validate  PROTO((rtx *, rtx, int, int));
@@ -608,6 +611,12 @@ combine_instructions (f, nregs)
 
       else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
        {
+#ifdef PROMOTE_FUNCTION_RETURN
+         /* See if we know about function return values before this
+            insn based upon SUBREG flags.  */
+         check_promoted_subreg (insn, PATTERN (insn));
+#endif
+
          /* Try this insn with each insn it links back to.  */
 
          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
@@ -11048,6 +11057,90 @@ record_dead_and_set_regs (insn)
 
   note_stores (PATTERN (insn), record_dead_and_set_regs_1, insn);
 }
+
+#ifdef PROMOTE_FUNCTION_RETURN
+/* If a SUBREG has the promoted bit set, it is in fact a property of the
+   register present in the SUBREG, so for each such SUBREG go back and
+   adjust nonzero and sign bit information of the registers that are
+   known to have some zero/sign bits set.
+
+   This is needed because when combine blows the SUBREGs away, the
+   information on zero/sign bits is lost and further combines can be
+   missed because of that.  */
+
+static void
+record_promoted_value (insn, subreg)
+    rtx insn;
+    rtx subreg;
+{
+  rtx links, links2, set;
+  int regno = REGNO (SUBREG_REG (subreg));
+  enum machine_mode mode = GET_MODE (subreg);
+
+  if (GET_MODE_BITSIZE (mode) >= HOST_BITS_PER_WIDE_INT)
+    return;
+
+  for (links = LOG_LINKS (insn); links; )
+    {
+      insn = XEXP (links, 0);
+      set = single_set (insn);
+
+      if (! set || GET_CODE (SET_DEST (set)) != REG
+         || REGNO (SET_DEST (set)) != regno
+         || GET_MODE (SET_DEST (set)) != GET_MODE (SUBREG_REG (subreg)))
+       {
+         links = XEXP (links, 1);
+         continue;
+       }
+
+      if (reg_last_set [regno] == insn)
+        {
+         if (SUBREG_PROMOTED_UNSIGNED_P (subreg))
+           reg_last_set_nonzero_bits [regno] &= GET_MODE_MASK (mode);
+        }
+
+      if (GET_CODE (SET_SRC (set)) == REG)
+       {
+         regno = REGNO (SET_SRC (set));
+         links = LOG_LINKS (insn);
+       }
+      else
+       break;
+    }
+}
+
+/* Scan X for promoted SUBREGs.  For each one found,
+   note what it implies to the registers used in it.  */
+
+static void
+check_promoted_subreg (insn, x)
+    rtx insn;
+    rtx x;
+{
+  if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
+      && GET_CODE (SUBREG_REG (x)) == REG)
+    record_promoted_value (insn, x);
+  else
+    {
+      const char *format = GET_RTX_FORMAT (GET_CODE (x));
+      int i, j;
+
+      for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
+       switch (format [i])
+         {
+         case 'e':
+           check_promoted_subreg (insn, XEXP (x, i));
+           break;
+         case 'V':
+         case 'E':
+           if (XVEC (x, i) != 0)
+             for (j = 0; j < XVECLEN (x, i); j++)
+               check_promoted_subreg (insn, XVECEXP (x, i, j));
+           break;
+         }
+    }
+}
+#endif
 \f
 /* Utility routine for the following function.  Verify that all the registers
    mentioned in *LOC are valid when *LOC was part of a value set when