diff mbox series

Fix x86 ICE when peepholing2 @stack_protect_set_1_<mode> with *lea<mode> (PR target/93187)

Message ID 20200108075851.GH10088@tucnak
State New
Headers show
Series Fix x86 ICE when peepholing2 @stack_protect_set_1_<mode> with *lea<mode> (PR target/93187) | expand

Commit Message

Jakub Jelinek Jan. 8, 2020, 7:58 a.m. UTC
Hi!

On the following testcase, the peephole2s merge @stack_protect_set_1_<mode>
with not the expected *mov{si,di}_internal, but *lea<mode> instead -
which looks like a mov, but uses address_no_seg_operand predicate/Ts
constraint.  The peephole2s check that operand with several smaller
predicates, as we do not want to match anything not matched by the
constraints used in the *stack_protect_set_{2_<mode>,3} patterns,
and I thought those predicates together are subset of general_operand,
which is used as the predicate in those patterns,
but apparently that is not the case.  So this patch also verifies
the operand is general_operand.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2020-01-07  Jakub Jelinek  <jakub@redhat.com>

	PR target/93187
	* config/i386/i386.md (*stack_protect_set_2_<mode> peephole2,
	*stack_protect_set_3 peephole2): Also check that the second
	insns source is general_operand.

	* g++.dg/opt/pr93187.C: New test.


	Jakub

Comments

Uros Bizjak Jan. 8, 2020, 3:37 p.m. UTC | #1
On Wed, Jan 8, 2020 at 8:58 AM Jakub Jelinek <jakub@redhat.com> wrote:
>
> Hi!
>
> On the following testcase, the peephole2s merge @stack_protect_set_1_<mode>
> with not the expected *mov{si,di}_internal, but *lea<mode> instead -
> which looks like a mov, but uses address_no_seg_operand predicate/Ts
> constraint.  The peephole2s check that operand with several smaller
> predicates, as we do not want to match anything not matched by the
> constraints used in the *stack_protect_set_{2_<mode>,3} patterns,
> and I thought those predicates together are subset of general_operand,
> which is used as the predicate in those patterns,
> but apparently that is not the case.  So this patch also verifies
> the operand is general_operand.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2020-01-07  Jakub Jelinek  <jakub@redhat.com>
>
>         PR target/93187
>         * config/i386/i386.md (*stack_protect_set_2_<mode> peephole2,
>         *stack_protect_set_3 peephole2): Also check that the second
>         insns source is general_operand.
>
>         * g++.dg/opt/pr93187.C: New test.

OK.

Thanks,
Uros.

> --- gcc/config/i386/i386.md.jj  2020-01-07 18:12:48.043555173 +0100
> +++ gcc/config/i386/i386.md     2020-01-07 20:18:27.666952849 +0100
> @@ -20084,6 +20084,7 @@ (define_peephole2
>    (set (match_operand:SI 3 "general_reg_operand")
>         (match_operand:SI 4))]
>   "REGNO (operands[2]) == REGNO (operands[3])
> +  && general_operand (operands[4], SImode)
>    && (general_reg_operand (operands[4], SImode)
>        || memory_operand (operands[4], SImode)
>        || immediate_operand (operands[4], SImode))
> @@ -20128,6 +20129,7 @@ (define_peephole2
>              (clobber (reg:CC FLAGS_REG))])
>    (set (match_dup 2) (match_operand:DI 3))]
>   "TARGET_64BIT
> +  && general_operand (operands[3], DImode)
>    && (general_reg_operand (operands[3], DImode)
>        || memory_operand (operands[3], DImode)
>        || x86_64_zext_immediate_operand (operands[3], DImode)
> --- gcc/testsuite/g++.dg/opt/pr93187.C.jj       2020-01-07 20:20:29.467117172 +0100
> +++ gcc/testsuite/g++.dg/opt/pr93187.C  2020-01-07 20:21:40.459047146 +0100
> @@ -0,0 +1,77 @@
> +// PR target/93187
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-O2" }
> +// { dg-additional-options "-fstack-protector-strong" { target fstack_protector } }
> +// { dg-additional-options "-fpie" { target pie } }
> +
> +struct A;
> +struct B;
> +struct C { int operator () (B, const B &); };
> +struct D { typedef int *d; };
> +struct E { C g; };
> +struct F { F (D::d); friend bool operator==(F &, const int &); };
> +template <typename T, typename> struct H {
> +  typedef D *I;
> +  E l;
> +  I foo ();
> +  T t;
> +  F bar (I, const T &);
> +  F baz (const T &);
> +};
> +template <typename T, typename U>
> +F
> +H<T, U>::bar (I n, const T &o)
> +{
> +  while (n)
> +    if (l.g (t, o))
> +      n = 0;
> +  return 0;
> +}
> +template <typename T, typename U>
> +F
> +H<T, U>::baz (const T &n)
> +{
> +  D *r = foo ();
> +  F p = bar (r, n);
> +  return p == 0 ? 0 : p;
> +}
> +template <typename, typename U> struct J {
> +  H<B, U> h;
> +  B &q;
> +  void baz () { h.baz (q); }
> +};
> +enum K { L };
> +template <typename, K = L> struct M;
> +template <int> struct G {
> +  using N = J<int, A>;
> +  N *operator->();
> +};
> +template <typename, K T> struct M : public G<T> {
> +  using N = J<int, A>;
> +  N *foo () { return n; }
> +  N *n;
> +  int o;
> +};
> +template <int N>
> +inline typename G<N>::N *
> +G<N>::operator-> ()
> +{
> +  N *n = static_cast<M<J<int, A>> *>(this)->foo ();
> +  return n;
> +}
> +struct B { bool qux (); };
> +struct O {
> +  struct P { M<int> p; };
> +  static thread_local P o;
> +  int baz () const;
> +};
> +thread_local O::P O::o;
> +B be;
> +int
> +O::baz () const
> +{
> +  do
> +    o.p->baz ();
> +  while (be.qux ());
> +  __builtin_unreachable ();
> +}
>
>         Jakub
>
diff mbox series

Patch

--- gcc/config/i386/i386.md.jj	2020-01-07 18:12:48.043555173 +0100
+++ gcc/config/i386/i386.md	2020-01-07 20:18:27.666952849 +0100
@@ -20084,6 +20084,7 @@  (define_peephole2
   (set (match_operand:SI 3 "general_reg_operand")
        (match_operand:SI 4))]
  "REGNO (operands[2]) == REGNO (operands[3])
+  && general_operand (operands[4], SImode)
   && (general_reg_operand (operands[4], SImode)
       || memory_operand (operands[4], SImode)
       || immediate_operand (operands[4], SImode))
@@ -20128,6 +20129,7 @@  (define_peephole2
 	     (clobber (reg:CC FLAGS_REG))])
   (set (match_dup 2) (match_operand:DI 3))]
  "TARGET_64BIT
+  && general_operand (operands[3], DImode)
   && (general_reg_operand (operands[3], DImode)
       || memory_operand (operands[3], DImode)
       || x86_64_zext_immediate_operand (operands[3], DImode)
--- gcc/testsuite/g++.dg/opt/pr93187.C.jj	2020-01-07 20:20:29.467117172 +0100
+++ gcc/testsuite/g++.dg/opt/pr93187.C	2020-01-07 20:21:40.459047146 +0100
@@ -0,0 +1,77 @@ 
+// PR target/93187
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+// { dg-additional-options "-fstack-protector-strong" { target fstack_protector } }
+// { dg-additional-options "-fpie" { target pie } }
+
+struct A;
+struct B;
+struct C { int operator () (B, const B &); };
+struct D { typedef int *d; };
+struct E { C g; };
+struct F { F (D::d); friend bool operator==(F &, const int &); };
+template <typename T, typename> struct H {
+  typedef D *I;
+  E l;
+  I foo ();
+  T t;
+  F bar (I, const T &);
+  F baz (const T &);
+};
+template <typename T, typename U>
+F
+H<T, U>::bar (I n, const T &o)
+{
+  while (n)
+    if (l.g (t, o))
+      n = 0;
+  return 0;
+}
+template <typename T, typename U>
+F
+H<T, U>::baz (const T &n)
+{
+  D *r = foo ();
+  F p = bar (r, n);
+  return p == 0 ? 0 : p;
+}
+template <typename, typename U> struct J {
+  H<B, U> h;
+  B &q;
+  void baz () { h.baz (q); }
+};
+enum K { L };
+template <typename, K = L> struct M;
+template <int> struct G {
+  using N = J<int, A>;
+  N *operator->();
+};
+template <typename, K T> struct M : public G<T> {
+  using N = J<int, A>;
+  N *foo () { return n; }
+  N *n;
+  int o;
+};
+template <int N>
+inline typename G<N>::N *
+G<N>::operator-> ()
+{
+  N *n = static_cast<M<J<int, A>> *>(this)->foo ();
+  return n;
+}
+struct B { bool qux (); };
+struct O {
+  struct P { M<int> p; };
+  static thread_local P o;
+  int baz () const;
+};
+thread_local O::P O::o;
+B be;
+int
+O::baz () const
+{
+  do
+    o.p->baz ();
+  while (be.qux ());
+  __builtin_unreachable ();
+}