Hi,

The -mjsr option in RX should ensure the that BSR instruction is not
generated, only JSR instruction should be generated.
However this does not work as expected: BSR instruction still gets generated
even if -mjsr is passed in the command line.
This is reproducible even if test cases from the gcc testsuite, for example:
gcc.c-torture\compile\920625-1.c
gcc.c-torture\compile\20051216-1.c
gcc.dg\torture\builtin-explog-1.c

The following patch fixes this issue by adding a new constraint to
call_internal and call_value_internal.
The patch also contains a test case which I created as follows:
1. I copied gcc.c-torture\compile\20051216-1.c  to gcc.target\rx and renamed
to mjsr.c
2. added the following lines to scan the assembly files for BSR. If BSR is
present the test fails.
/* { dg-do compile } */
/* { dg-options "-O2 -mjsr" } */
/* { dg-final { scan-assembler-not "bsr" } } */

Regression test is OK, tested with the following command:
make -k check-gcc RUNTESTFLAGS=--target_board=rx-sim

Please let me know if this is OK. Thank you!

Best Regards,
Sebastian

Index: ChangeLog
===================================================================
--- ChangeLog   (revision 256278)
+++ ChangeLog   (working copy)
@@ -1,3 +1,10 @@
+2018-01-05  Sebastian Perta  <sebastian.pe...@renesas.com>
+
+       * config/rx/constraints.md: added new constraint CALL_OP_SYMBOL_REF 
+       to allow or block "symbol_ref" depending on value of TARGET_JSR
+       * config/rx/rx.md: use CALL_OP_SYMBOL_REF in call_internal and 
+       call_value_internal insns
+
 2018-01-05  Richard Sandiford  <richard.sandif...@linaro.org>
 
        * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Don't
Index: config/rx/constraints.md
===================================================================
--- config/rx/constraints.md    (revision 256278)
+++ config/rx/constraints.md    (working copy)
@@ -106,3 +106,9 @@
        )
   )
 )
+
+(define_constraint "CALL_OP_SYMBOL_REF"
+"constraint for call instructions using symbol ref"
+(and (match_test "!TARGET_JSR")
+     (match_code "symbol_ref"))
+)
Index: config/rx/rx.md
===================================================================
--- config/rx/rx.md     (revision 256278)
+++ config/rx/rx.md     (working copy)
@@ -438,7 +438,7 @@
 )
 
 (define_insn "call_internal"
-  [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
+  [(call (mem:QI (match_operand:SI 0 "rx_call_operand"
"r,CALL_OP_SYMBOL_REF"))
         (const_int 0))
    (clobber (reg:CC CC_REG))]
   ""
@@ -466,7 +466,7 @@
 
 (define_insn "call_value_internal"
   [(set (match_operand                  0 "register_operand" "=r,r")
-       (call (mem:QI (match_operand:SI 1 "rx_call_operand"   "r,Symbol"))
+       (call (mem:QI (match_operand:SI 1 "rx_call_operand"
"r,CALL_OP_SYMBOL_REF"))
              (const_int 0)))
    (clobber (reg:CC CC_REG))]
   ""
Index: testsuite/gcc.target/rx/mjsr.c
===================================================================
--- testsuite/gcc.target/rx/mjsr.c      (nonexistent)
+++ testsuite/gcc.target/rx/mjsr.c      (working copy)
@@ -0,0 +1,134 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mjsr" } */
+
+void *malloc (__SIZE_TYPE__);
+void *realloc (void *, __SIZE_TYPE__);
+
+struct A { double x, y; };
+struct B { double x0, y0, x1, y1; };
+struct C { int n_points; int dir; struct B bbox; struct A *points; };
+struct D { int n_segs; struct C segs[1]; };
+
+void foo (int, int, int *, int, int *, struct A **, int *, int *,
+         struct D *, int *, struct D **, int *, int **);
+int baz (struct A, struct A, struct A, struct A);
+
+static void
+bar (struct D *svp, int *n_points_max,
+     struct A p, int *seg_map, int *active_segs, int i)
+{
+  int asi, n_points;
+  struct C *seg;
+
+  asi = seg_map[active_segs[i]];
+  seg = &svp->segs[asi];
+  n_points = seg->n_points;
+  seg->points = ((struct A *)
+               realloc (seg->points, (n_points_max[asi] <<= 1) * sizeof
(struct A)));
+  seg->points[n_points] = p;
+  seg->bbox.y1 = p.y;
+  seg->n_points++;
+}
+
+struct D *
+test (struct D *vp)
+{
+  int *active_segs, n_active_segs, *cursor, seg_idx;
+  double y, share_x;
+  int tmp1, tmp2, asi, i, j, *n_ips, *n_ips_max, n_segs_max;
+  struct A **ips, p_curs, *pts;
+  struct D *new_vp;
+  int *n_points_max, *seg_map, first_share;
+
+  n_segs_max = 16;
+  new_vp = (struct D *) malloc (sizeof (struct D) +
+                               (n_segs_max - 1) * sizeof (struct C));
+  new_vp->n_segs = 0;
+
+  if (vp->n_segs == 0)
+    return new_vp;
+
+  active_segs = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+  cursor = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+
+  seg_map = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+  n_ips = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+  n_ips_max = ((int *) malloc ((vp->n_segs) * sizeof (int)));
+  ips = ((struct A * *) malloc ((vp->n_segs) * sizeof (struct A *)));
+
+  n_points_max = ((int *) malloc ((n_segs_max) * sizeof (int)));
+
+  n_active_segs = 0;
+  seg_idx = 0;
+  y = vp->segs[0].points[0].y;
+  while (seg_idx < vp->n_segs || n_active_segs > 0)
+    {
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         if (vp->segs[asi].n_points - 1 == cursor[asi] &&
+             vp->segs[asi].points[cursor[asi]].y == y)
+           i--;
+       }
+
+      while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y)
+       {
+         cursor[seg_idx] = 0;
+         n_ips[seg_idx] = 1;
+         n_ips_max[seg_idx] = 2;
+         ips[seg_idx] =
+           ((struct A *) malloc ((n_ips_max[seg_idx]) * sizeof (struct
A)));
+         ips[seg_idx][0] = vp->segs[seg_idx].points[0];
+         pts = ((struct A *) malloc ((16) * sizeof (struct A)));
+         pts[0] = vp->segs[seg_idx].points[0];
+         tmp1 = seg_idx;
+         for (j = i; j < n_active_segs; j++)
+           {
+             tmp2 = active_segs[j];
+             active_segs[j] = tmp1;
+             tmp1 = tmp2;
+           }
+         active_segs[n_active_segs] = tmp1;
+         n_active_segs++;
+         seg_idx++;
+       }
+      first_share = -1;
+      share_x = 0;
+
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         p_curs = ips[asi][1];
+         if (p_curs.y == y)
+           {
+             bar (new_vp, n_points_max,
+                  p_curs, seg_map, active_segs, i);
+
+             n_ips[asi]--;
+             for (j = 0; j < n_ips[asi]; j++)
+               ips[asi][j] = ips[asi][j + 1];
+
+             if (first_share < 0 || p_curs.x != share_x)
+               {
+                 foo (first_share, i,
+                      active_segs, n_active_segs,
+                      cursor, ips, n_ips, n_ips_max, vp, seg_map,
+                      &new_vp, &n_segs_max, &n_points_max);
+                 first_share = i;
+                 share_x = p_curs.x;
+               }
+           }
+         else
+           {
+             foo (first_share, i,
+                  active_segs, n_active_segs,
+                  cursor, ips, n_ips, n_ips_max, vp, seg_map,
+                  &new_vp, &n_segs_max, &n_points_max);
+             first_share = -1;
+           }
+       }
+    }
+  return new_vp;
+}
+
+/* { dg-final { scan-assembler-not "bsr" } } */

Reply via email to