2020-01-08 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.
+
PR target/93174
* config/i386/i386.md (addcarry<mode>_0): Use nonimmediate_operand
predicate for output operand instead of register_operand.
(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))
(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)
--- /dev/null
+// 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 ();
+}