]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/36194 (Truncation optimization in combine can remove necessary trunc...
authorAdam Nemet <anemet@caviumnetworks.com>
Tue, 20 May 2008 18:42:09 +0000 (18:42 +0000)
committerAdam Nemet <nemet@gcc.gnu.org>
Tue, 20 May 2008 18:42:09 +0000 (18:42 +0000)
PR middle-end/36194
* combine.c (check_conversion): Rename to check_promoted_subreg.
Don't call record_truncated_value from here.
(record_truncated_value): Turn it into a for_each_rtx callback.
(record_truncated_values): New function.
(combine_instructions): Call note_uses with
record_truncated_values.  Change name of check_conversion to
check_promoted_subreg.

testsuite/

* gcc.dg/pr36194.c: New test.

From-SVN: r135670

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr36194.c [new file with mode: 0644]

index 7dfeca077deed7f06c1825f6fa3f168b731856ea..ab330d52284052ec9257bd1064769c0fbc68e2e5 100644 (file)
@@ -1,3 +1,14 @@
+2008-05-20  Adam Nemet  <anemet@caviumnetworks.com>
+
+       PR middle-end/36194
+       * combine.c (check_conversion): Rename to check_promoted_subreg.
+       Don't call record_truncated_value from here.
+       (record_truncated_value): Turn it into a for_each_rtx callback.
+       (record_truncated_values): New function.
+       (combine_instructions): Call note_uses with
+       record_truncated_values.  Change name of check_conversion to
+       check_promoted_subreg.
+
 2008-05-20  Joseph Myers  <joseph@codesourcery.com>
 
        * doc/install.texi2html: Generate gcc-vers.texi in $DESTDIR not
index 4667b236461f431bf18c8d75d9abdd4c45446f08..4806cdfa6d076fa069a564558e3c5f376bd33a79 100644 (file)
@@ -430,7 +430,7 @@ static rtx gen_lowpart_for_combine (enum machine_mode, rtx);
 static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
 static void update_table_tick (rtx);
 static void record_value_for_reg (rtx, rtx, rtx);
-static void check_conversions (rtx, rtx);
+static void check_promoted_subreg (rtx, rtx);
 static void record_dead_and_set_regs_1 (rtx, rtx, void *);
 static void record_dead_and_set_regs (rtx);
 static int get_last_value_validate (rtx *, rtx, int, int);
@@ -447,7 +447,8 @@ static int insn_cuid (rtx);
 static void record_promoted_value (rtx, rtx);
 static int unmentioned_reg_p_1 (rtx *, void *);
 static bool unmentioned_reg_p (rtx, rtx);
-static void record_truncated_value (rtx);
+static int record_truncated_value (rtx *, void *);
+static void record_truncated_values (rtx *, void *);
 static bool reg_truncated_to_mode (enum machine_mode, rtx);
 static rtx gen_lowpart_or_truncate (enum machine_mode, rtx);
 \f
@@ -819,7 +820,12 @@ combine_instructions (rtx f, unsigned int nregs)
            {
              /* See if we know about function return values before this
                 insn based upon SUBREG flags.  */
-             check_conversions (insn, PATTERN (insn));
+             check_promoted_subreg (insn, PATTERN (insn));
+
+             /* See if we can find hardregs and subreg of pseudos in
+                narrower modes.  This could help turning TRUNCATEs
+                into SUBREGs.  */
+             note_uses (&PATTERN (insn), record_truncated_values, NULL);
 
              /* Try this insn with each insn it links back to.  */
 
@@ -11138,13 +11144,15 @@ reg_truncated_to_mode (enum machine_mode mode, rtx x)
   return false;
 }
 
-/* X is a REG or a SUBREG.  If X is some sort of a truncation record
-   it.  For non-TRULY_NOOP_TRUNCATION targets we might be able to turn
-   a truncate into a subreg using this information.  */
+/* Callback for for_each_rtx.  If *P is a hard reg or a subreg record the mode
+   that the register is accessed in.  For non-TRULY_NOOP_TRUNCATION targets we
+   might be able to turn a truncate into a subreg using this information.
+   Return -1 if traversing *P is complete or 0 otherwise.  */
 
-static void
-record_truncated_value (rtx x)
+static int
+record_truncated_value (rtx *p, void *data ATTRIBUTE_UNUSED)
 {
+  rtx x = *p;
   enum machine_mode truncated_mode;
 
   if (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x)))
@@ -11153,11 +11161,11 @@ record_truncated_value (rtx x)
       truncated_mode = GET_MODE (x);
 
       if (GET_MODE_SIZE (original_mode) <= GET_MODE_SIZE (truncated_mode))
-       return;
+       return -1;
 
       if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (truncated_mode),
                                 GET_MODE_BITSIZE (original_mode)))
-       return;
+       return -1;
 
       x = SUBREG_REG (x);
     }
@@ -11166,7 +11174,7 @@ record_truncated_value (rtx x)
   else if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
     truncated_mode = GET_MODE (x);
   else
-    return;
+    return 0;
 
   if (reg_stat[REGNO (x)].truncated_to_mode == 0
       || reg_stat[REGNO (x)].truncation_label < label_tick
@@ -11176,23 +11184,30 @@ record_truncated_value (rtx x)
       reg_stat[REGNO (x)].truncated_to_mode = truncated_mode;
       reg_stat[REGNO (x)].truncation_label = label_tick;
     }
+
+  return -1;
 }
 
-/* Scan X for promoted SUBREGs and truncated REGs.  For each one
-   found, note what it implies to the registers used in it.  */
+/* Callback for note_uses.  Find hardregs and subregs of pseudos and
+   the modes they are used in.  This can help truning TRUNCATEs into
+   SUBREGs.  */
 
 static void
-check_conversions (rtx insn, rtx x)
+record_truncated_values (rtx *x, void *data ATTRIBUTE_UNUSED)
 {
-  if (GET_CODE (x) == SUBREG || REG_P (x))
-    {
-      if (GET_CODE (x) == SUBREG
-         && SUBREG_PROMOTED_VAR_P (x)
-         && REG_P (SUBREG_REG (x)))
-       record_promoted_value (insn, x);
+  for_each_rtx (x, record_truncated_value, NULL);
+}
 
-      record_truncated_value (x);
-    }
+/* Scan X for promoted SUBREGs.  For each one found,
+   note what it implies to the registers used in it.  */
+
+static void
+check_promoted_subreg (rtx insn, rtx x)
+{
+  if (GET_CODE (x) == SUBREG
+      && SUBREG_PROMOTED_VAR_P (x)
+      && REG_P (SUBREG_REG (x)))
+    record_promoted_value (insn, x);
   else
     {
       const char *format = GET_RTX_FORMAT (GET_CODE (x));
@@ -11202,13 +11217,13 @@ check_conversions (rtx insn, rtx x)
        switch (format[i])
          {
          case 'e':
-           check_conversions (insn, XEXP (x, i));
+           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_conversions (insn, XVECEXP (x, i, j));
+               check_promoted_subreg (insn, XVECEXP (x, i, j));
            break;
          }
     }
index 5915396416237389e6e97cf27950ada242f48b9f..5fbc969a70078b290d05093a0ebdc20238306521 100644 (file)
@@ -1,3 +1,8 @@
+2008-05-20  Adam Nemet  <anemet@caviumnetworks.com>
+
+       PR middle-end/36194
+       * gcc.dg/pr36194.c: New test.
+
 2008-05-19  Release Manager
 
        * GCC 4.2.4 released.
diff --git a/gcc/testsuite/gcc.dg/pr36194.c b/gcc/testsuite/gcc.dg/pr36194.c
new file mode 100644 (file)
index 0000000..3d2195b
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+void abort (void);
+
+__attribute__ ((noinline)) void
+f (int i)
+{
+  if (i != 0x87654321)
+    abort ();
+  asm ("");
+}
+
+__attribute__ ((noinline)) void
+g (long long a)
+{
+  f (a);
+  asm ("");
+}
+
+main ()
+{
+  g (0x1234567887654321ll);
+  return 0;
+}