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