1 /* Only test on some 64-bit targets which do have bswap{si,di}2 patterns and
2    are either big or little endian (not pdp endian).  */
3 /* { dg-do run { target { lp64 && { i?86-*-* x86_64-*-* powerpc*-*-* aarch64*-*-* } } } } */
4 /* { dg-require-effective-target store_merge } */
5 /* { dg-options "-O2 -fdump-tree-store-merging" } */
6 
7 __attribute__((noipa)) void
f1(unsigned char * p,unsigned long long q)8 f1 (unsigned char *p, unsigned long long q)
9 {
10   p[0] = q;
11   p[1] = q >> 8;
12   p[2] = q >> 16;
13   p[3] = q >> 24;
14   p[4] = q >> 32;
15   p[5] = q >> 40;
16   p[6] = q >> 48;
17   p[7] = q >> 56;
18 }
19 
20 __attribute__((noipa)) void
f2(unsigned char * p,unsigned long long q)21 f2 (unsigned char *p, unsigned long long q)
22 {
23   p[0] = q >> 56;
24   p[1] = q >> 48;
25   p[2] = q >> 40;
26   p[3] = q >> 32;
27   p[4] = q >> 24;
28   p[5] = q >> 16;
29   p[6] = q >> 8;
30   p[7] = q;
31 }
32 
33 __attribute__((noipa)) void
f3(unsigned char * __restrict p,unsigned char * __restrict q)34 f3 (unsigned char *__restrict p, unsigned char *__restrict q)
35 {
36   unsigned char q3 = q[3];
37   unsigned char q2 = q[2];
38   unsigned char q1 = q[1];
39   unsigned char q0 = q[0];
40   p[0] = q3;
41   p[1] = q2;
42   p[2] = q1;
43   p[3] = q0;
44 }
45 
46 __attribute__((noipa)) void
f4(unsigned char * __restrict p,unsigned char * __restrict q)47 f4 (unsigned char *__restrict p, unsigned char *__restrict q)
48 {
49   p[0] = q[3];
50   p[1] = q[2];
51   p[2] = q[1];
52   p[3] = q[0];
53 }
54 
55 struct S { unsigned char a, b; unsigned short c; };
56 
57 __attribute__((noipa)) void
f5(struct S * __restrict p,struct S * __restrict q)58 f5 (struct S *__restrict p, struct S *__restrict q)
59 {
60 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
61   unsigned char pa = q->c >> 8;
62   unsigned char pb = q->c;
63   unsigned short pc = (q->a << 8) | q->b;
64 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
65   unsigned char pa = q->c;
66   unsigned char pb = q->c >> 8;
67   unsigned short pc = q->a | (q->b << 8);
68 #endif
69   p->a = pa;
70   p->b = pb;
71   p->c = pc;
72 }
73 
74 __attribute__((noipa)) void
f6(struct S * __restrict p,struct S * __restrict q)75 f6 (struct S *__restrict p, struct S *__restrict q)
76 {
77 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
78   p->a = q->c >> 8;
79   p->b = q->c;
80   p->c = (q->a << 8) | q->b;
81 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
82   p->a = q->c;
83   p->b = q->c >> 8;
84   p->c = q->a | (q->b << 8);
85 #endif
86 }
87 
88 struct T { unsigned long long a : 8, b : 8, c : 8, d : 8, e : 8, f : 8, g : 8, h : 8; };
89 
90 __attribute__((noipa)) void
f7(struct T * __restrict p,struct T * __restrict q)91 f7 (struct T *__restrict p, struct T *__restrict q)
92 {
93   p->a = q->h;
94   p->b = q->g;
95   p->c = q->f;
96   p->d = q->e;
97   p->e = q->d;
98   p->f = q->c;
99   p->g = q->b;
100   p->h = q->a;
101 }
102 
103 struct S b = { 0x11, 0x12,
104 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
105 	       0x1413
106 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
107 	       0x1314
108 #endif
109 	     };
110 struct T e = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28 };
111 
112 int
main()113 main ()
114 {
115   unsigned char a[8];
116   int i;
117   struct S c, d;
118   f1 (a, 0x0102030405060708ULL);
119   for (i = 0; i < 8; ++i)
120     if (a[i] != 8 - i)
121       __builtin_abort ();
122   f2 (a, 0x0102030405060708ULL);
123   for (i = 0; i < 8; ++i)
124     if (a[i] != 1 + i)
125       __builtin_abort ();
126   f3 (a, a + 4);
127   for (i = 0; i < 8; ++i)
128     if (a[i] != (i < 4 ? 8 - i : 1 + i))
129       __builtin_abort ();
130   f2 (a, 0x090a0b0c0d0e0f10ULL);
131   f4 (a + 4, a);
132   for (i = 0; i < 8; ++i)
133     if (a[i] != (i < 4 ? 9 + i : 16 - i))
134       __builtin_abort ();
135   f5 (&c, &b);
136   if (c.a != 0x14 || c.b != 0x13
137 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
138       || c.c != 0x1112
139 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
140       || c.c != 0x1211
141 #endif
142       )
143     __builtin_abort ();
144   f6 (&d, &c);
145   if (d.a != 0x11 || d.b != 0x12 || d.c != b.c)
146     __builtin_abort ();
147   struct T f;
148   f7 (&f, &e);
149   if (f.a != 0x28 || f.b != 0x27 || f.c != 0x26 || f.d != 0x25
150       || f.e != 0x24 || f.f != 0x23 || f.g != 0x22 || f.h != 0x21)
151     __builtin_abort ();
152   return 0;
153 }
154 
155 /* { dg-final { scan-tree-dump-times "Merging successful" 7 "store-merging" } } */
156 /* { dg-final { scan-tree-dump-times "__builtin_bswap64" 2 "store-merging" } } */
157 /* { dg-final { scan-tree-dump-times "__builtin_bswap32" 4 "store-merging" } } */
158