On Wed, Jan 8, 2020 at 8:58 AM Jakub Jelinek wrote:
>
> Hi!
>
> On the following testcase, the peephole2s merge @stack_protect_set_1_
> with not the expected *mov{si,di}_internal, but *lea 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_,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
>
> PR target/93187
> * config/i386/i386.md (*stack_protect_set_2_ 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 struct H {
> + typedef D *I;
> + E l;
> + I foo ();
> + T t;
> + F bar (I, const T &);
> + F baz (const T &);
> +};
> +template
> +F
> +H::bar (I n, const T &o)
> +{
> + while (n)
> +if (l.g (t, o))
> + n = 0;
> + return 0;
> +}
> +template
> +F
> +H::baz (const T &n)
> +{
> + D *r = foo ();
> + F p = bar (r, n);
> + return p == 0 ? 0 : p;
> +}
> +template struct J {
> + H h;
> + B &q;
> + void baz () { h.baz (q); }
> +};
> +enum K { L };
> +template struct M;
> +template struct G {
> + using N = J;
> + N *operator->();
> +};
> +template struct M : public G {
> + using N = J;
> + N *foo () { return n; }
> + N *n;
> + int o;
> +};
> +template
> +inline typename G::N *
> +G::operator-> ()
> +{
> + N *n = static_cast> *>(this)->foo ();
> + return n;
> +}
> +struct B { bool qux (); };
> +struct O {
> + struct P { M 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
>