Hi!

On the following testcase on aarch64 the combiner propagates
(clobber:TI (const_int 0)) into a DEBUG_INSN.  Such clobbers are
specific to the combiner, created by gen_lowpart_for_combine:
 fail:
  return gen_rtx_CLOBBER (omode, const0_rtx);
which can be embedded anywhere and the combiner hopes they never match
anything.  That is hopefully the case of all instructions that go through
recog, but for DEBUG_INSNs we don't have any strict rules on what matches
and what doesn't and so if combiner calls propagate_for_debug with
src containing such clobbers embedded in it, it will happily propagate it
into DEBUG_INSNs and cause problems later (in this case ICEs during LRA).

The following patch ensures that if such clobbers would be propagated into
some DEBUG_INSNs that such DEBUG_INSNs are reset to the unknown state.
propagate_for_debug uses volatile_insn_p check to determine if something
needs to be reset after propagation and the patch replaces the combiner
specific clobbers with UNSPEC_VOLATILE that volatile_insn_p will return
true on and thus valtrack.c reset those DEBUG_INSNs.

Bootstrapped/regtested on x86_64-linux and i686-linux and tested in
cross to aarch64-linux on the testcase, ok for trunk?

2021-04-09  Jakub Jelinek  <ja...@redhat.com>

        PR debug/99830
        * combine.c (combine_propagate_for_debug): New function.
        (try_combine): Use combine_propagate_for_debug instead of
        propagate_for_debug.

        * gcc.dg/pr99830.c: New test.

--- gcc/combine.c.jj    2021-04-07 12:35:03.060224972 +0200
+++ gcc/combine.c       2021-04-08 16:22:17.851459742 +0200
@@ -2610,6 +2610,30 @@ count_auto_inc (rtx, rtx, rtx, rtx, rtx,
   return 0;
 }
 
+/* Wrapper around propagate_for_debug to deal with gen_lowpart_for_combine
+   (clobber (const_int 0)).  In normal insns a clobber of const0_rtx nested
+   somewhere will cause the pattern not to be recognized, but in debug insns
+   it doesn't, one needs to use something on which volatile_insn_p is true
+   instead.  */
+
+static void
+combine_propagate_for_debug (rtx_insn *insn, rtx_insn *last, rtx dest, rtx src,
+                            basic_block this_basic_block)
+{
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, src, ALL)
+    {
+      const_rtx x = *iter;
+      if (GET_CODE (x) == CLOBBER && XEXP (x, 0) == const0_rtx)
+       {
+         src = gen_rtx_UNSPEC_VOLATILE (GET_MODE (dest),
+                                        gen_rtvec (1, const0_rtx), -1);
+         break;
+       }
+    }
+  propagate_for_debug (insn, last, dest, src, this_basic_block);
+}
+
 /* Try to combine the insns I0, I1 and I2 into I3.
    Here I0, I1 and I2 appear earlier than I3.
    I0 and I1 can be zero; then we combine just I2 into I3, or I1 and I2 into
@@ -4200,8 +4224,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
                   i2src while its original mode is temporarily
                   restored, and then clear i2scratch so that we don't
                   do it again later.  */
-               propagate_for_debug (i2, last_combined_insn, reg, i2src,
-                                    this_basic_block);
+               combine_propagate_for_debug (i2, last_combined_insn, reg,
+                                            i2src, this_basic_block);
                i2scratch = false;
                /* Put back the new mode.  */
                adjust_reg_mode (reg, new_mode);
@@ -4235,12 +4259,13 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
                   with this copy we have created; then, replace the
                   copy with the SUBREG of the original shared reg,
                   once again changed to the new mode.  */
-               propagate_for_debug (first, last, reg, tempreg,
-                                    this_basic_block);
+               combine_propagate_for_debug (first, last, reg, tempreg,
+                                            this_basic_block);
                adjust_reg_mode (reg, new_mode);
-               propagate_for_debug (first, last, tempreg,
-                                    lowpart_subreg (old_mode, reg, new_mode),
-                                    this_basic_block);
+               combine_propagate_for_debug (first, last, tempreg,
+                                            lowpart_subreg (old_mode, reg,
+                                                            new_mode),
+                                            this_basic_block);
              }
          }
     }
@@ -4499,16 +4524,16 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
     if (newi2pat)
       {
        if (MAY_HAVE_DEBUG_BIND_INSNS && i2scratch)
-         propagate_for_debug (i2, last_combined_insn, i2dest, i2src,
-                              this_basic_block);
+         combine_propagate_for_debug (i2, last_combined_insn, i2dest, i2src,
+                                      this_basic_block);
        INSN_CODE (i2) = i2_code_number;
        PATTERN (i2) = newi2pat;
       }
     else
       {
        if (MAY_HAVE_DEBUG_BIND_INSNS && i2src)
-         propagate_for_debug (i2, last_combined_insn, i2dest, i2src,
-                              this_basic_block);
+         combine_propagate_for_debug (i2, last_combined_insn, i2dest, i2src,
+                                      this_basic_block);
        SET_INSN_DELETED (i2);
       }
 
@@ -4517,8 +4542,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
        LOG_LINKS (i1) = NULL;
        REG_NOTES (i1) = 0;
        if (MAY_HAVE_DEBUG_BIND_INSNS)
-         propagate_for_debug (i1, last_combined_insn, i1dest, i1src,
-                              this_basic_block);
+         combine_propagate_for_debug (i1, last_combined_insn, i1dest, i1src,
+                                      this_basic_block);
        SET_INSN_DELETED (i1);
       }
 
@@ -4527,8 +4552,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
        LOG_LINKS (i0) = NULL;
        REG_NOTES (i0) = 0;
        if (MAY_HAVE_DEBUG_BIND_INSNS)
-         propagate_for_debug (i0, last_combined_insn, i0dest, i0src,
-                              this_basic_block);
+         combine_propagate_for_debug (i0, last_combined_insn, i0dest, i0src,
+                                      this_basic_block);
        SET_INSN_DELETED (i0);
       }
 
--- gcc/testsuite/gcc.dg/pr99830.c.jj   2021-04-08 16:39:44.243774333 +0200
+++ gcc/testsuite/gcc.dg/pr99830.c      2021-04-08 16:28:40.463175738 +0200
@@ -0,0 +1,10 @@
+/* PR debug/99830 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -fno-expensive-optimizations -fno-split-wide-types -g" } 
*/
+
+int foo (long a, __int128 b, short c, int d, unsigned e, __int128 f)
+{
+  __builtin_memmove (2 + (char *) &f, foo, 1);
+  c >>= (char) f;
+  return c;
+}

        Jakub

Reply via email to