1 /* { dg-do compile { target { powerpc64le-*-* } } } */
2 /* { dg-require-effective-target powerpc_p8vector_ok } */
3 /* { dg-options "-mdejagnu-cpu=power8 -O3 " } */
4 
5 /* Previous versions of this test required that the assembler does not
6    contain xxpermdi or xxswapd.  However, with the more sophisticated
7    code generation used today, it is now possible that xxpermdi (aka
8    xxswapd) show up without being part of a lxvd2x or stxvd2x
9    sequence.  */
10 
11 #include <altivec.h>
12 
13 extern void abort (void);
14 
15 const vector char y = { 0, 1, 2, 3,
16 			4, 5, 6, 7,
17 			8, 9, 10, 11,
18 			12, 13, 14, 15 };
19 
20 vector char x, z;
21 
22 vector char
foo(void)23 foo (void)
24 {
25   return y;			/* Remove 1 swap and use lvx.  */
26 }
27 
28 vector char
foo1(void)29 foo1 (void)
30 {
31   x = y;			/* Remove 2 redundant swaps here.  */
32   return x;			/* Remove 1 swap and use lvx.  */
33 }
34 
35 void __attribute__ ((noinline))
fill_local(vector char * vp)36 fill_local (vector char *vp)
37 {
38   *vp = x;			/* Remove 2 redundant swaps here.  */
39 }
40 
41 /* Test aligned load from local.  */
42 vector char
foo2(void)43 foo2 (void)
44 {
45   vector char v;
46 
47   /* Need to be clever here because v will normally reside in a
48      register rather than memory.  */
49   fill_local (&v);
50   return v;			/* Remove 1 swap and use lvx.  */
51 }
52 
53 
54 /* Test aligned load from pointer.  */
55 vector char
foo3(vector char * arg)56 foo3 (vector char *arg)
57 {
58   return *arg;			/* Remove 1 swap and use lvx.  */
59 }
60 
61 /* In this structure, the compiler should insert padding to assure
62    that a_vector is properly aligned.  */
63 struct bar {
64   char a_field;
65   vector char a_vector;
66 };
67 
68 vector char
foo4(struct bar * bp)69 foo4 (struct bar *bp)
70 {
71   return bp->a_vector;		/* Remove 1 swap and use lvx.  */
72 }
73 
74 /* Test aligned store to global.  */
75 void
baz(vector char arg)76 baz (vector char arg)
77 {
78   x = arg;			/* Remove 1 swap and use stvx.  */
79 }
80 
81 void __attribute__ ((noinline))
copy_local(vector char * arg)82 copy_local (vector char *arg)
83 {
84   x = *arg;			/* Remove 2 redundant swaps.  */
85 }
86 
87 
88 /* Test aligned store to local.  */
89 void
baz1(vector char arg)90 baz1 (vector char arg)
91 {
92   vector char v;
93 
94   /* Need cleverness, because v will normally reside in a register
95      rather than memory.  */
96   v = arg;			/* Aligned store to local: remove 1
97 				   swap and use stvx.  */
98   copy_local (&v);
99 }
100 
101 /* Test aligned store to pointer.  */
102 void
baz2(vector char * arg1,vector char arg2)103 baz2 (vector char *arg1, vector char arg2)
104 {
105   /* Assume arg2 resides in register.  */
106   *arg1 = arg2;			/* Remove 1 swap and use stvx.  */
107 }
108 
109 void
baz3(struct bar * bp,vector char v)110 baz3 (struct bar *bp, vector char v)
111 {
112   /* Assume v resides in register.  */
113   bp->a_vector = v;		/* Remove 1 swap and use stvx.  */
114 }
115 
116 int
main(int argc,char * argv[])117 main (int argc, char *argv[])
118 {
119   vector char fetched_value = foo ();
120   if (fetched_value[0] != 0 || fetched_value[15] != 15)
121     abort ();
122 
123   fetched_value = foo1 ();
124   if (fetched_value[1] != 1 || fetched_value[14] != 14)
125     abort ();
126 
127   fetched_value = foo2 ();
128   if (fetched_value[2] != 2 || fetched_value[13] != 13)
129     abort ();
130 
131   fetched_value = foo3 (&x);
132   if (fetched_value[3] != 3 || fetched_value[12] != 12)
133     abort ();
134 
135   struct bar a_struct;
136   a_struct.a_vector = x;	/* Remove 2 redundant swaps.  */
137   fetched_value = foo4 (&a_struct);
138   if (fetched_value[4] != 4 || fetched_value[11] != 11)
139     abort ();
140 
141   for (int i = 0; i < 16; i++)
142     z[i] = 15 - i;
143 
144   baz (z);
145   if (x[0] != 15 || x[15] != 0)
146     abort ();
147 
148   vector char source = { 8, 7, 6, 5, 4, 3, 2, 1,
149 			 0, 9, 10, 11, 12, 13, 14, 15 };
150 
151   baz1 (source);
152   if (x[3] != 5 || x[8] != 0)
153     abort ();
154 
155   vector char dest;
156   baz2 (&dest, source);
157   if (dest[4] != 4 || dest[1] != 7)
158     abort ();
159 
160   baz3 (&a_struct, source);
161   if (a_struct.a_vector[7] != 1 || a_struct.a_vector[15] != 15)
162     abort ();
163 
164   return 0;
165 }
166