On Wed, Jan 8, 2020 at 8:58 AM Jakub Jelinek <ja...@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 <ja...@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 >