I think the compactsi makes no sense for ARCv2 without the add_s reg, reg,PCL instruction. Moreover, I have proposed a patch about this issue months ago, See: https://gcc.gnu.org/ml/gcc-patches/2016-04/msg01462.html. However, our maintainer is missing in action.
Cheers, Claudiu > -----Original Message----- > From: Andrew Burgess [mailto:andrew.burg...@embecosm.com] > Sent: Thursday, June 30, 2016 1:43 AM > To: gcc-patches@gcc.gnu.org; g...@amylaar.uk > Cc: claudiu.zissule...@synopsys.com; Andrew Burgess > <andrew.burg...@embecosm.com> > Subject: [PATCH] gcc/arc: Avoid add_s REG,REG,pcl on ARCv2 targets > > The ARCv2 targets don't support add_s REG,REG,pcl like earlier ARC > targets did. This instruction format is used when generating case jump > tables. > > This commit updates the code so that ARCv2 targets avoid the unsupported > instruction. This does mean the code is slightly longer on ARCv2, so > the instruction length has changed accordingly. > > gcc/ChangeLog: > > * config/arc/arc.md (casesi_compact_jump): Avoid generating add_s > REG,REG,pcl on ARCv2 targets. > > gcc/testsuite/ChangeLog: > > * gcc.target/arc/switch-1.c: New file. > --- > gcc/ChangeLog | 5 ++++ > gcc/config/arc/arc.md | 50 > ++++++++++++++++++--------------- > gcc/testsuite/ChangeLog | 4 +++ > gcc/testsuite/gcc.target/arc/switch-1.c | 42 > +++++++++++++++++++++++++++ > 4 files changed, 79 insertions(+), 22 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/arc/switch-1.c > > diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md > index 1102c53..0f39d49 100644 > --- a/gcc/config/arc/arc.md > +++ b/gcc/config/arc/arc.md > @@ -3950,6 +3950,7 @@ > int unalign = arc_get_unalign (); > rtx xop[3]; > const char *s; > + int vec_offset = TARGET_V2 ? 12 : 10; > > xop[0] = operands[0]; > xop[2] = operands[2]; > @@ -3962,11 +3963,11 @@ > 2 of these are for alignment, and are anticipated in the length > of the ADDR_DIFF_VEC. */ > if (unalign && !satisfies_constraint_Rcq (xop[0])) > - s = \"add2 %2,pcl,%0\n\tld_s %2,[%2,12]\"; > + s = \"add2 %2,pcl,%0\n\tld_s %2,[%2,12]\"; /* Length = 6 bytes. */ > else if (unalign) > - s = \"add_s %2,%0,2\n\tld.as %2,[pcl,%2]\"; > + s = \"add_s %2,%0,2\n\tld.as %2,[pcl,%2]\"; /* Length = 6 bytes. */ > else > - s = \"add %2,%0,2\n\tld.as %2,[pcl,%2]\"; > + s = \"add %2,%0,2\n\tld.as %2,[pcl,%2]\"; /* Length = 8 bytes. */ > arc_clear_unalign (); > break; > case HImode: > @@ -3974,26 +3975,26 @@ > { > if (satisfies_constraint_Rcq (xop[0])) > { > - s = \"add_s %2,%0,%1\n\tld%_.as %2,[pcl,%2]\"; > - xop[1] = GEN_INT ((10 - unalign) / 2U); > + s = \"add_s %2,%0,%1\n\tld%_.as %2,[pcl,%2]\"; /* Length = 6 > bytes. */ > + xop[1] = GEN_INT ((vec_offset - unalign) / 2U); > } > else > { > - s = \"add1 %2,pcl,%0\n\tld%__s %2,[%2,%1]\"; > - xop[1] = GEN_INT (10 + unalign); > + s = \"add1 %2,pcl,%0\n\tld%__s %2,[%2,%1]\"; /* Length = 6 > bytes. */ > + xop[1] = GEN_INT (vec_offset + unalign); > } > } > else > { > if (satisfies_constraint_Rcq (xop[0])) > { > - s = \"add_s %2,%0,%1\n\tld%_.x.as %2,[pcl,%2]\"; > - xop[1] = GEN_INT ((10 - unalign) / 2U); > + s = \"add_s %2,%0,%1\n\tld%_.x.as %2,[pcl,%2]\"; /* Length = 6 > bytes. */ > + xop[1] = GEN_INT ((vec_offset - unalign) / 2U); > } > else > { > - s = \"add1 %2,pcl,%0\n\tld%__s.x %2,[%2,%1]\"; > - xop[1] = GEN_INT (10 + unalign); > + s = \"add1 %2,pcl,%0\n\tld%__s.x %2,[%2,%1]\"; /* Length = 6 > bytes. */ > + xop[1] = GEN_INT (vec_offset + unalign); > } > } > arc_toggle_unalign (); > @@ -4001,17 +4002,18 @@ > case QImode: > if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) > { > - if ((rtx_equal_p (xop[2], xop[0]) > - || find_reg_note (insn, REG_DEAD, xop[0])) > + if (!TARGET_V2 > + && (rtx_equal_p (xop[2], xop[0]) > + || find_reg_note (insn, REG_DEAD, xop[0])) > && satisfies_constraint_Rcq (xop[0])) > { > - s = \"add_s %0,%0,pcl\n\tldb_s %2,[%0,%1]\"; > - xop[1] = GEN_INT (8 + unalign); > + s = \"add %0,%0,pcl\n\tldb_s %2,[%0,%1]\"; /* Length = 6 > bytes. */ > + xop[1] = GEN_INT ((vec_offset - 2) + unalign); > } > else > { > - s = \"add %2,%0,pcl\n\tldb_s %2,[%2,%1]\"; > - xop[1] = GEN_INT (10 + unalign); > + s = \"add %2,%0,pcl\n\tldb_s %2,[%2,%1]\"; /* Length = 6 > bytes. */ > + xop[1] = GEN_INT (vec_offset + unalign); > arc_toggle_unalign (); > } > } > @@ -4019,14 +4021,14 @@ > || find_reg_note (insn, REG_DEAD, xop[0])) > && satisfies_constraint_Rcq (xop[0])) > { > - s = \"add_s %0,%0,%1\n\tldb.x %2,[pcl,%0]\"; > - xop[1] = GEN_INT (10 - unalign); > + s = \"add_s %0,%0,%1\n\tldb.x %2,[pcl,%0]\"; /* Length = 6 bytes. > */ > + xop[1] = GEN_INT (vec_offset - unalign); > arc_toggle_unalign (); > } > else > { > /* ??? Length is 12. */ > - s = \"add %2,%0,%1\n\tldb.x %2,[pcl,%2]\"; > + s = \"add %2,%0,%1\n\tldb.x %2,[pcl,%2]\"; /* Length = 8 bytes. > */ > xop[1] = GEN_INT (8 + unalign); > } > break; > @@ -4034,9 +4036,13 @@ > gcc_unreachable (); > } > output_asm_insn (s, xop); > - return \"add_s %2,%2,pcl\n\tj_s%* [%2]\"; > + if (TARGET_V2) > + return \"add %2,%2,pcl\n\tj_s%* [%2]\"; /* Length = 6 bytes. */ > + else > + return \"add_s %2,%2,pcl\n\tj_s%* [%2]\"; /* Length = 4 bytes. */ > }" > - [(set_attr "length" "10") > + [(set (attr "length") > + (if_then_else (match_test "TARGET_V2") (const_int 12) (const_int > 10))) > (set_attr "type" "jump") > (set_attr "iscompact" "true") > (set_attr "cond" "nocond")]) > diff --git a/gcc/testsuite/gcc.target/arc/switch-1.c > b/gcc/testsuite/gcc.target/arc/switch-1.c > new file mode 100644 > index 0000000..f68b719 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arc/switch-1.c > @@ -0,0 +1,42 @@ > +/* { dg-do compile } */ > +/* { dg-options "-mcpu=arcem -Os -Wall -Werror" } */ > + > +/* { dg-final { scan-assembler-not "add_s\[ \t\]+r\[0-9\]+,r\[0-9\]+,pcl" } } > */ > + > +/* Unfortunately the following pragma is required in order to allow > + compiling with -Wall -Werror, but still skip one of the possible switch > + cases in this test. */ > +#pragma GCC diagnostic ignored "-Wswitch" > + > +typedef struct { > + struct { > + struct { > + enum { > + REG_SAVED_OFFSET, > + REG_SAVED_REG, > + REG_SAVED_EXP, > + REG_SAVED_VAL_OFFSET, > + REG_SAVED_VAL_EXP > + } how; > + } reg[1]; > + } regs; > +} _Unwind_FrameState; > + > +_Unwind_FrameState a; > + > +extern void fn2 (void); > + > +void fn1() { > + switch (a.regs.reg[0].how) { > + case REG_SAVED_OFFSET: > + /* Specifically don't handle REG_SAVED_REG in this switch statement, > + this causes GCC to generate the specific switch-jump-vector table > + that triggered a bug on ARCv2 targets. */ > + /* case REG_SAVED_REG: */ > + case REG_SAVED_EXP: > + case REG_SAVED_VAL_OFFSET: > + fn2(); > + case REG_SAVED_VAL_EXP: > + fn2(); > + } > +} > -- > 2.6.4