On Tue, Mar 08, 2022 at 10:24:50AM -0600, Segher Boessenkool wrote:
> On Tue, Mar 08, 2022 at 05:12:43PM +0100, Jakub Jelinek wrote:
> > On Tue, Mar 08, 2022 at 09:49:15AM -0600, Segher Boessenkool wrote:
> > > > But like I said above, even if we didn't copy these XVECLEN 0 rtvecs,
> > > > the crash would not go away.
> > > 
> > > An rtvec should never have length 0.  Look at gen_rtvec for another
> > > example.
> > 
> > That is not true.  In case of ASM_OPERANDS, lots of code relies that it
> > can use ASM_OPERANDS_{INPUT,LABEL}_LENGTH without checking if
> > ASM_OPERANDS_{INPUT,LABEL}_VEC is non-NULL.  Those ASM*LENGTH macros are
> > defined as XVECLEN which I believe will just segfault if the vec is NULL:
> > #define XVECLEN(RTX, N)         GET_NUM_ELEM (XVEC (RTX, N))
> > #define GET_NUM_ELEM(RTVEC)             ((RTVEC)->num_elem)
> > #define XVEC(RTX, N)    (RTL_CHECK2 (RTX, N, 'E', 'V').rt_rtvec)
> > cfgexpand.cc as Marek said will allocate even zero length vectors using
> > rtvec_alloc (0):
> >   rtvec argvec = rtvec_alloc (ninputs);
> >   rtvec constraintvec = rtvec_alloc (ninputs);
> >   rtvec labelvec = rtvec_alloc (nlabels);
> > or e.g. in
> >   PATTERN (insn) = gen_rtx_ASM_OPERANDS (VOIDmode, ggc_strdup (""), "", 0,
> >                                          rtvec_alloc (0),
> >                                          rtvec_alloc (0),
> >                                          ASM_OPERANDS_LABEL_VEC (tmp),
> >                                          ASM_OPERANDS_SOURCE_LOCATION(tmp));
> 
> Wow, what a mess.  And this part is completely undocumented even :-(
> It seems unintentional (and wrong) to me, but yes we are in stage 4, if
> we want to clean this up one way or the other, now is not the time.

Yeah.  I guess rtvec_alloc should either assert n > 0 or return NULL_RTVEC
when n == 0.

> In that case: your patch looks good to me Marek.

Thanks.  I've tweaked the patch to use ASM_OPERANDS_LABEL_LENGTH rather than
GET_NUM_ELEM.  I'll push it if it passes testing on x86_64-pc-linux-gnu.

-- >8 --
In r270550, Jakub fixed classify_insn to handle asm goto: if the asm can
jump to a label, the insn should be a JUMP_INSN.

However, as the following testcase shows, non-null ASM_OPERANDS_LABEL_VEC
doesn't guarantee that the rtx has any actual labels it can branch to.
Here, the rtvec has 0 elements because expand_asm_stmt created it:

  rtvec labelvec = rtvec_alloc (nlabels); // nlabels == 0

This causes an ICE in update_br_prob_note: BRANCH_EDGE (bb) crashes
because there's no branch edge.  I think we can fix this by checking
that there is at least one label the asm can jump to before wrapping
the ASM_OPERANDS in a JUMP_INSN.

        PR rtl-optimization/104777

gcc/ChangeLog:

        * rtl.cc (classify_insn): For ASM_OPERANDS, return JUMP_INSN only if
        ASM_OPERANDS_LABEL_VEC has at least one element.

gcc/testsuite/ChangeLog:

        * gcc.dg/torture/tls/pr104777.c: New test.
---
 gcc/rtl.cc                                  |  4 +--
 gcc/testsuite/gcc.dg/torture/tls/pr104777.c | 30 +++++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/tls/pr104777.c

diff --git a/gcc/rtl.cc b/gcc/rtl.cc
index f17474bfee1..d383ae9c099 100644
--- a/gcc/rtl.cc
+++ b/gcc/rtl.cc
@@ -765,7 +765,7 @@ classify_insn (rtx x)
     return CALL_INSN;
   if (ANY_RETURN_P (x))
     return JUMP_INSN;
-  if (GET_CODE (x) == ASM_OPERANDS && ASM_OPERANDS_LABEL_VEC (x))
+  if (GET_CODE (x) == ASM_OPERANDS && ASM_OPERANDS_LABEL_LENGTH (x) > 0)
     return JUMP_INSN;
   if (GET_CODE (x) == SET)
     {
@@ -794,7 +794,7 @@ classify_insn (rtx x)
       if (has_return_p)
        return JUMP_INSN;
       if (GET_CODE (XVECEXP (x, 0, 0)) == ASM_OPERANDS
-         && ASM_OPERANDS_LABEL_VEC (XVECEXP (x, 0, 0)))
+         && ASM_OPERANDS_LABEL_LENGTH (XVECEXP (x, 0, 0)) > 0)
        return JUMP_INSN;
     }
 #ifdef GENERATOR_FILE
diff --git a/gcc/testsuite/gcc.dg/torture/tls/pr104777.c 
b/gcc/testsuite/gcc.dg/torture/tls/pr104777.c
new file mode 100644
index 00000000000..abaf59731fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/tls/pr104777.c
@@ -0,0 +1,30 @@
+/* PR rtl-optimization/104777 */
+/* { dg-do compile } */
+/* { dg-require-effective-target tls } */
+ 
+int savestate_r;
+int savestate_ssb;
+extern void abort();
+__thread int  loop;
+void f (void)
+{
+  int savestate_r0_5;
+  int savestate_r1_6;
+
+  __asm__("" : "=m" (savestate_ssb), "=r" (savestate_r));
+  savestate_r0_5 = savestate_r;
+  if (savestate_r0_5 == 0)
+  {
+    __asm__ __volatile__("" :  : "m" (loop));
+    abort ();
+  }
+
+  __asm__("" : "=m" (savestate_ssb), "=r" (savestate_r));
+  savestate_r1_6 = savestate_r;
+  if (savestate_r1_6 != 0)
+    return;
+
+  __asm__ __volatile__("" :  : "m" (loop));
+  abort ();
+
+}

base-commit: 058d19b42ad4c4c22635f70db6913a80884aedec
-- 
2.35.1

Reply via email to