re PR target/51244 ([SH] Inefficient conditional branch and code around T bit)
authorOleg Endo <olegendo@gcc.gnu.org>
Sat, 3 Nov 2012 12:01:01 +0000 (12:01 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Sat, 3 Nov 2012 12:01:01 +0000 (12:01 +0000)
PR target/51244
* config/sh/sh.md (*cbranch_t): Allow splitting after reload.
Allow going beyond current basic block before reload when looking for
the reg set insn.
* config/sh/sh.c (sh_find_set_of_reg): Don't stop at labels.

PR target/51244
* gcc.target/sh/pr51244-18.c: New.
* gcc.target/sh/pr51244-19.c: New.

From-SVN: r193119

gcc/ChangeLog
gcc/config/sh/sh.c
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr51244-18.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr51244-19.c [new file with mode: 0644]

index 59a51f3d8877b7d6bc198a136f06a12470a15f19..8af3547cd4e4fd2aca45b230eed4930dc0fe3888 100644 (file)
@@ -1,3 +1,11 @@
+2012-11-03  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/51244
+       * config/sh/sh.md (*cbranch_t): Allow splitting after reload.
+       Allow going beyond current basic block before reload when looking for
+       the reg set insn.
+       * config/sh/sh.c (sh_find_set_of_reg): Don't stop at labels.
+
 2012-11-02  Jan Hubicka  <jh@suse.cz>
 
        * tree-ssa-loop-niter.c (discover_iteration_bound_by_body_walk): Add
index 40afdb4378437c9e5ad74f7ea3e210d1d42212c7..25573b36982093bca02b489126962d6bdbeb330b 100644 (file)
@@ -13486,7 +13486,7 @@ sh_find_set_of_reg (rtx reg, rtx insn, rtx(*stepfunc)(rtx))
   for (result.insn = stepfunc (insn); result.insn != NULL_RTX;
        result.insn = stepfunc (result.insn))
     {
-      if (LABEL_P (result.insn) || BARRIER_P (result.insn))
+      if (BARRIER_P (result.insn))
        return result;
       if (!NONJUMP_INSN_P (result.insn))
        continue;
index 6b1fdbeaa355755c7a354bb928838e5d54135b2b..a002304845ee9d00903f4f6dc30fcb31c15814cb 100644 (file)
@@ -8167,13 +8167,15 @@ label:
 {
   return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
 }
-  "&& can_create_pseudo_p ()"
+  "&& 1"
   [(set (pc) (if_then_else (eq (reg:SI T_REG) (match_dup 2))
                           (label_ref (match_dup 0))
                           (pc)))]
 {
   /* Try to find missed test and branch combine opportunities which result
      in redundant T bit tests before conditional branches.
+     This is done not only after combine (and before reload) but in every
+     split pass, because some opportunities are formed also after combine.
      FIXME: Probably this would not be needed if CCmode was used
      together with TARGET_FIXED_CONDITION_CODE_REGS.  */
 
@@ -8212,8 +8214,11 @@ label:
 
   while (true)
     {
+      /* It's not safe to go beyond the current basic block after reload.  */
       set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn,
-                                         prev_nonnote_insn_bb);
+                                         reload_completed
+                                         ? prev_nonnote_insn_bb
+                                         : prev_nonnote_insn);
       if (s1.set_src == NULL_RTX)
        break;
 
index 872282654700a00039f790954f875545589958d3..2f5d1f77dba1b9bca3a097ae6feacc79b37fb303 100644 (file)
@@ -1,3 +1,9 @@
+2012-11-03  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/51244
+       * gcc.target/sh/pr51244-18.c: New.
+       * gcc.target/sh/pr51244-19.c: New.
+
 2012-11-03  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * gcc.target/mips/octeon-exts-7.c (bar): Make sure the extraction of
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-18.c b/gcc/testsuite/gcc.target/sh/pr51244-18.c
new file mode 100644 (file)
index 0000000..dbfb990
--- /dev/null
@@ -0,0 +1,102 @@
+/* Check that no unnecessary T bit stores are done before conditional
+   branches.
+   This case was extracted from the CSiBE set and contained the following
+   sequence:
+       cmp/hi  r1,r0
+       movt    r1
+       tst     r1,r1
+       bt      .L12
+       mov.l   @r10,r1
+   In this reduced code the movt and tst insns were only present in the
+   unwanted sequence.  Thus, if we see any tst or movt insns, something is
+   not working as expected.  This test requires -O2 because the T bit stores
+   in question will be eliminated in additional insn split passes after
+   reload.  */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
+/* { dg-final { scan-assembler-not "movt|tst" } } */
+
+typedef char Char;
+typedef unsigned char Bool;
+typedef unsigned char UChar;
+typedef int Int32;
+typedef unsigned int UInt32;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+static inline Bool
+mainGtU (UInt32 i1, UInt32 i2, UChar* block, UInt16* quadrant, UInt32 nblock,
+        Int32* budget)
+{
+  Int32 k;
+  UChar c1, c2;
+  UInt16 s1, s2;
+  k = nblock + 8;
+  do
+    {
+      c1 = block[i1];
+      c2 = block[i2];
+      if (c1 != c2)
+       return (c1 > c2);
+      s1 = quadrant[i1];
+      s2 = quadrant[i2];
+      if (s1 != s2)
+       return (s1 > s2);
+
+      i1++; i2++;
+      k -= 8;
+   } while (k >= 0);
+
+  return 0;
+}
+
+static inline void
+mainSimpleSort (UInt32* ptr, UChar* block, UInt16* quadrant, Int32 nblock,
+               Int32 lo, Int32 hi, Int32 d, Int32* budget)
+{
+  Int32 i, j, h, bigN, hp;
+  UInt32 v;
+  bigN = hi - lo + 1;
+  hp = 0;
+  h = 1;
+  j = lo + h;
+  v = ptr[j];
+
+  while (mainGtU (ptr[j-h]+d, v+d, block, quadrant, nblock, budget))
+    {
+      ptr[j] = ptr[j-h];
+      j = j - h;
+    }
+}
+
+static inline void
+mainQSort3 (UInt32* ptr, UChar* block, UInt16* quadrant, Int32 nblock,
+           Int32 loSt, Int32 hiSt, Int32 dSt, Int32* budget)
+{
+  Int32 unLo, unHi, ltLo, gtHi;
+  Int32 sp, lo, hi, d;
+
+  Int32 stackLo[100];
+  Int32 stackHi[100];
+  Int32 stackD [100];
+
+  sp = 0;
+  stackLo[sp] = loSt;
+  stackHi[sp] = hiSt;
+  stackD [sp] = dSt;
+  lo = stackLo[sp];
+  hi = stackHi[sp];
+  d = stackD [sp];
+  mainSimpleSort (ptr, block, quadrant, nblock, lo, hi, d, budget);
+}
+
+void
+mainSort (UInt32* ptr, UChar* block, UInt16* quadrant, UInt32* ftab,
+         Int32 nblock, Int32 verb, Int32* budget)
+{
+  Int32 sb = 0;
+  Int32 lo = ftab[sb] & (~((1 << 21)));
+  Int32 hi = (ftab[sb+1] & (~((1 << 21)))) - 1;
+  mainQSort3 (ptr, block, quadrant, nblock, lo, hi, 2, budget);
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-19.c b/gcc/testsuite/gcc.target/sh/pr51244-19.c
new file mode 100644 (file)
index 0000000..4d4f781
--- /dev/null
@@ -0,0 +1,75 @@
+/* Check that no unnecessary T bit stores are done before conditional
+   branches.
+   This case was extracted from the CSiBE set and contained the following
+   sequence:
+       mov.l   @(8,r4),r2
+       mov.l   @(4,r4),r3
+       cmp/gt  r2,r3
+       movt    r2
+.L3:
+       tst     r2,r2
+       bt/s    .L12
+       mov     #-1,r0
+
+       .....
+
+       mov.l   @r4,r2
+       tst     r2,r2
+       bra     .L3
+       movt    r2
+
+   In this reduced code the movt insns were only present in the
+   unwanted sequences.  Thus, if we see any movt insns, something is not
+   working as expected.  This test requires -O2 because the T bit stores
+   in question will be eliminated in additional insn split passes after
+   reload.  */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
+/* { dg-final { scan-assembler-not "movt" } } */
+
+struct request
+{
+ unsigned long nr_sectors;
+};
+
+struct request_list
+{
+ int count;
+};
+
+struct request_queue
+{
+ struct request_list rq;
+ volatile int nr_sectors;
+ int max_queue_sectors;
+ int can_throttle;
+ unsigned long bounce_pfn;
+};
+
+typedef struct request_queue request_queue_t;
+
+static inline int
+blk_oversized_queue (request_queue_t* q)
+{
+  if (q->can_throttle)
+    return q->nr_sectors > q->max_queue_sectors;
+  return q->rq.count == 0;
+}
+
+struct request*
+get_request (request_queue_t* q, int rw)
+{
+  struct request* rq = ((void*)0);
+  struct request_list *rl = &q->rq;
+
+  if (blk_oversized_queue (q))
+    {
+      if ((rw == 1) || (rw == 0))
+       return ((void*)0);
+      if (blk_oversized_queue (q))
+       return ((void*)0);
+    }
+
+  return (void*)-100;
+}