===================================================================
@@ -1959,3 +1959,20 @@ (define_predicate "fusion_offsettable_me
return offsettable_nonstrict_memref_p (op);
})
+
+;; Return true if the operand is a virtual or frame register. The register
+;; allocator gets confused if a virtual/frame register is used in a splat
+;; operation when -fstack-protector is used.
+(define_predicate "virtual_or_frame_reg_operand"
+ (match_code "reg,subreg")
+{
+ HOST_WIDE_INT r;
+ if (SUBREG_P (op))
+ op = SUBREG_REG (op);
+
+ if (!REG_P (op))
+ return 0;
+
+ r = REGNO (op);
+ return REGNO_PTR_FRAME_P (r);
+})
===================================================================
@@ -2397,6 +2397,20 @@ (define_insn "vsx_splat_<mode>"
lxvdsx %x0,%y1"
[(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
+;; Virtual/frame registers cause problems because they are replaced by a PLUS
+;; operation which confuses RELOAD if -fstack-protector is used. Add a
+;; splitter to copy such registers to a temporary
+(define_split
+ [(set (match_operand:V2DI 0 "vsx_register_operand" "")
+ (vec_duplicate:V2DI
+ (match_operand:DI 1 "virtual_or_frame_reg_operand" "")))]
+ "TARGET_VSX && TARGET_POWERPC64 && can_create_pseudo_p ()"
+ [(match_dup 2) (match_dup 1)
+ (match_dup 0) (vec_duplicate:VSX_D (match_dup 2))]
+{
+ operands[2] = gen_reg_rtx (DImode);
+})
+
;; V4SI splat (ISA 3.0)
;; When SI's are allowed in VSX registers, add XXSPLTW support
(define_expand "vsx_splat_<mode>"
@@ -2411,6 +2425,17 @@ (define_expand "vsx_splat_<mode>"
operands[1] = force_reg (<VS_scalar>mode, operands[1]);
})
+(define_split
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "")
+ (vec_duplicate:V4SI
+ (match_operand:SI 1 "virtual_or_frame_reg_operand" "")))]
+ "TARGET_P9_VECTOR && !TARGET_POWERPC64 && can_create_pseudo_p ()"
+ [(match_dup 2) (match_dup 1)
+ (match_dup 0) (vec_duplicate:VSX_D (match_dup 2))]
+{
+ operands[2] = gen_reg_rtx (SImode);
+})
+
(define_insn "*vsx_splat_v4si_internal"
[(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,wa")
(vec_duplicate:V4SI
===================================================================
@@ -0,0 +1,56 @@
+/* { dg-do compile { target { powerpc64*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O3 -fstack-protector" } */
+
+class A;
+template <typename _Tp, int m, int n> class B {
+public:
+ _Tp val[m * n];
+};
+class C {
+public:
+ C(A);
+};
+struct D {
+ D();
+ unsigned long &operator[](int);
+ unsigned long *p;
+};
+class A {
+public:
+ template <typename _Tp, int m, int n> A(const B<_Tp, m, n> &, bool);
+ int rows, cols;
+ unsigned char *data;
+ unsigned char *datastart;
+ unsigned char *dataend;
+ unsigned char *datalimit;
+ D step;
+};
+template <typename _Tp, int m, int n>
+A::A(const B<_Tp, m, n> &p1, bool)
+ : rows(m), cols(n) {
+ step[0] = cols * sizeof(_Tp);
+ datastart = data = (unsigned char *)p1.val;
+ datalimit = dataend = datastart + rows * step[0];
+}
+class F {
+public:
+ static void compute(C);
+ template <typename _Tp, int m, int n, int nm>
+ static void compute(const B<_Tp, m, n> &, B<_Tp, nm, 1> &, B<_Tp, m, nm> &,
+ B<_Tp, n, nm> &);
+};
+D::D() {}
+unsigned long &D::operator[](int p1) { return p[p1]; }
+template <typename _Tp, int m, int n, int nm>
+void F::compute(const B<_Tp, m, n> &, B<_Tp, nm, 1> &, B<_Tp, m, nm> &,
+ B<_Tp, n, nm> &p4) {
+ A a(p4, false);
+ compute(a);
+}
+void fn1() {
+ B<double, 4, 4> b, c, e;
+ B<double, 4, 1> d;
+ F::compute(b, d, c, e);
+}