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" } } */