• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 < %s | FileCheck %s -check-prefix=CHECK-LE
2; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 < %s | FileCheck %s -check-prefix=CHECK-BE
3; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s -check-prefix=CHECK-NOVSX
4; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s -check-prefix=CHECK-NOVSX
5; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s -check-prefix=CHECK-BE-NOVSX
6; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s -check-prefix=CHECK-LE-NOVSX
7
8@x = common global <1 x i128> zeroinitializer, align 16
9@y = common global <1 x i128> zeroinitializer, align 16
10@a = common global i128 zeroinitializer, align 16
11@b = common global i128 zeroinitializer, align 16
12
13; VSX:
14;   %a is passed in register 34
15;   The value of 1 is stored in the TOC.
16;   On LE, ensure the value of 1 is swapped before being used (using xxswapd).
17; VMX (no VSX):
18;   %a is passed in register 2
19;   The value of 1 is stored in the TOC.
20;   No swaps are necessary when using P8 Vector instructions on LE
21define <1 x i128> @v1i128_increment_by_one(<1 x i128> %a) nounwind {
22       %tmp = add <1 x i128> %a, <i128 1>
23       ret <1 x i128> %tmp
24
25; FIXME: Seems a 128-bit literal is materialized by loading from the TOC. There
26;        should be a better way of doing this.
27
28; CHECK-LE-LABEL: @v1i128_increment_by_one
29; CHECK-LE: lxvd2x [[VAL:[0-9]+]], {{[0-9]+}}, {{[0-9]+}}
30; CHECK-LE: xxswapd 35, [[VAL]]
31; CHECK-LE: vadduqm 2, 2, 3
32; CHECK-LE: blr
33
34; CHECK-BE-LABEL: @v1i128_increment_by_one
35; CHECK-BE: lxvd2x 35, {{[0-9]+}}, {{[0-9]+}}
36; CHECK-BE-NOT: xxswapd
37; CHECK-BE: vadduqm 2, 2, 3
38; CHECK-BE-NOT: xxswapd 34, {{[0-9]+}}
39; CHECK-BE: blr
40
41; CHECK-NOVSX-LABEL: @v1i128_increment_by_one
42; CHECK-NOVSX-NOT: xxswapd {{[0-9]+}}, {{[0-9]+}}
43; CHECK-NOVSX-NOT: stxvd2x {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}}
44; CHECK-NOVSX: lvx [[VAL:[0-9]+]], {{[0-9]+}}, {{[0-9]+}}
45; CHECK-NOVSX-NOT: lxvd2x {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}}
46; CHECK-NOVSX-NOT: xxswapd {{[0-9]+}}, {{[0-9]+}}
47; CHECK-NOVSX: vadduqm 2, 2, [[VAL]]
48; CHECK-NOVSX: blr
49}
50
51; VSX:
52;   %a is passed in register 34
53;   %b is passed in register 35
54;   No swaps are necessary when using P8 Vector instructions on LE
55; VMX (no VSX):
56;   %a is passewd in register 2
57;   %b is passed in register 3
58;   On LE, do not need to swap contents of 2 and 3 because the lvx/stvx
59;   instructions no not swap elements
60define <1 x i128> @v1i128_increment_by_val(<1 x i128> %a, <1 x i128> %b) nounwind {
61       %tmp = add <1 x i128> %a, %b
62       ret <1 x i128> %tmp
63
64; CHECK-LE-LABEL: @v1i128_increment_by_val
65; CHECK-LE-NOT: xxswapd
66; CHECK-LE: adduqm 2, 2, 3
67; CHECK-LE: blr
68
69; CHECK-BE-LABEL: @v1i128_increment_by_val
70; CHECK-BE-NOT: xxswapd {{[0-9]+}}, 34
71; CHECK-BE-NOT: xxswapd {{[0-9]+}}, 35
72; CHECK-BE-NOT: xxswapd 34, [[RESULT]]
73; CHECK-BE: adduqm 2, 2, 3
74; CHECK-BE: blr
75
76; CHECK-NOVSX-LABEL: @v1i128_increment_by_val
77; CHECK-NOVSX-NOT: xxswapd 34, [[RESULT]]
78; CHECK-NOVSX: adduqm 2, 2, 3
79; CHECK-NOVSX: blr
80}
81
82; Little Endian (VSX and VMX):
83;   Lower 64-bits of %a are passed in register 3
84;   Upper 64-bits of %a are passed in register 4
85;   Increment lower 64-bits using addic (immediate value of 1)
86;   Increment upper 64-bits using add zero extended
87;   Results are placed in registers 3 and 4
88; Big Endian (VSX and VMX)
89;   Lower 64-bits of %a are passed in register 4
90;   Upper 64-bits of %a are passed in register 3
91;   Increment lower 64-bits using addic (immediate value of 1)
92;   Increment upper 64-bits using add zero extended
93;   Results are placed in registers 3 and 4
94define i128 @i128_increment_by_one(i128 %a) nounwind {
95       %tmp =  add i128 %a,  1
96       ret i128 %tmp
97; CHECK-LE-LABEL: @i128_increment_by_one
98; CHECK-LE: addic 3, 3, 1
99; CHECK-LE-NEXT: addze 4, 4
100; CHECK-LE: blr
101
102; CHECK-BE-LABEL: @i128_increment_by_one
103; CHECK-BE: addic 4, 4, 1
104; CHECK-BE-NEXT: addze 3, 3
105; CHECK-BE: blr
106
107; CHECK-LE-NOVSX-LABEL: @i128_increment_by_one
108; CHECK-LE-NOVSX: addic 3, 3, 1
109; CHECK-LE-NOVSX-NEXT: addze 4, 4
110; CHECK-LE-NOVSX: blr
111
112; CHECK-BE-NOVSX-LABEL: @i128_increment_by_one
113; CHECK-BE-NOVSX: addic 4, 4, 1
114; CHECK-BE-NOVSX-NEXT: addze 3, 3
115; CHECK-BE-NOVSX: blr
116}
117
118; Little Endian (VSX and VMX):
119;   Lower 64-bits of %a are passed in register 3
120;   Upper 64-bits of %a are passed in register 4
121;   Lower 64-bits of %b are passed in register 5
122;   Upper 64-bits of %b are passed in register 6
123;   Add the lower 64-bits using addc on registers 3 and 5
124;   Add the upper 64-bits using adde on registers 4 and 6
125;   Registers 3 and 4 should hold the result
126; Big Endian (VSX and VMX):
127;   Upper 64-bits of %a are passed in register 3
128;   Lower 64-bits of %a are passed in register 4
129;   Upper 64-bits of %b are passed in register 5
130;   Lower 64-bits of %b are passed in register 6
131;   Add the lower 64-bits using addc on registers 4 and 6
132;   Add the upper 64-bits using adde on registers 3 and 5
133;   Registers 3 and 4 should hold the result
134define i128 @i128_increment_by_val(i128 %a, i128 %b) nounwind {
135       %tmp =  add i128 %a, %b
136       ret i128 %tmp
137; CHECK-LE-LABEL: @i128_increment_by_val
138; CHECK-LE: addc 3, 3, 5
139; CHECK-LE-NEXT: adde 4, 4, 6
140; CHECK-LE: blr
141
142; CHECK-BE-LABEL: @i128_increment_by_val
143; CHECK-BE: addc 4, 4, 6
144; CHECK-BE-NEXT: adde 3, 3, 5
145; CHECK-BE: blr
146
147; CHECK-LE-NOVSX-LABEL: @i128_increment_by_val
148; CHECK-LE-NOVSX: addc 3, 3, 5
149; CHECK-LE-NOVSX-NEXT: adde 4, 4, 6
150; CHECK-LE-NOVSX: blr
151
152; CHECK-BE-NOVSX-LABEL: @i128_increment_by_val
153; CHECK-BE-NOVSX: addc 4, 4, 6
154; CHECK-BE-NOVSX-NEXT: adde 3, 3, 5
155; CHECK-BE-NOVSX: blr
156}
157
158
159; Callsites for the routines defined above.
160; Ensure the parameters are loaded in the same order that is expected by the
161; callee. See comments for individual functions above for details on registers
162; used for parameters.
163define <1 x i128> @call_v1i128_increment_by_one() nounwind {
164       %tmp = load <1 x i128>, <1 x i128>* @x, align 16
165       %ret = call <1 x i128> @v1i128_increment_by_one(<1 x i128> %tmp)
166       ret <1 x i128> %ret
167
168; CHECK-LE-LABEL: @call_v1i128_increment_by_one
169; CHECK-LE: lxvd2x [[PARAM:[0-9]+]], {{[0-9]+}}, {{[0-9]+}}
170; CHECK-LE: xxswapd 34, [[PARAM]]
171; CHECK-LE: bl v1i128_increment_by_one
172; CHECK-LE: blr
173
174; CHECK-BE-LABEL: @call_v1i128_increment_by_one
175; CHECK-BE: lxvw4x 34, {{[0-9]+}}, {{[0-9]+}}
176; CHECK-BE-NOT: xxswapd 34, {{[0-9]+}}
177; CHECK-BE: bl v1i128_increment_by_one
178; CHECK-BE: blr
179
180; CHECK-NOVSX-LABEL: @call_v1i128_increment_by_one
181; CHECK-NOVSX: lvx 2, {{[0-9]+}}, {{[0-9]+}}
182; CHECK-NOVSX-NOT: xxswapd {{[0-9]+}}, {{[0-9]+}}
183; CHECK-NOVSX: bl v1i128_increment_by_one
184; CHECK-NOVSX: blr
185}
186
187define <1 x i128> @call_v1i128_increment_by_val() nounwind {
188       %tmp = load <1 x i128>, <1 x i128>* @x, align 16
189       %tmp2 = load <1 x i128>, <1 x i128>* @y, align 16
190       %ret = call <1 x i128> @v1i128_increment_by_val(<1 x i128> %tmp, <1 x i128> %tmp2)
191       ret <1 x i128> %ret
192
193; CHECK-LE-LABEL: @call_v1i128_increment_by_val
194; CHECK-LE: lxvd2x [[PARAM1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}}
195; CHECK-LE: lxvd2x [[PARAM2:[0-9]+]], {{[0-9]+}}, {{[0-9]+}}
196; CHECK-LE-DAG: xxswapd 34, [[PARAM1]]
197; CHECK-LE-DAG: xxswapd 35, [[PARAM2]]
198; CHECK-LE: bl v1i128_increment_by_val
199; CHECK-LE: blr
200
201; CHECK-BE-LABEL: @call_v1i128_increment_by_val
202
203
204; CHECK-BE-DAG: lxvw4x 35, {{[0-9]+}}, {{[0-9]+}}
205; CHECK-BE-NOT: xxswapd 34, {{[0-9]+}}
206; CHECK-BE-NOT: xxswapd 35, {{[0-9]+}}
207; CHECK-BE: bl v1i128_increment_by_val
208; CHECK-BE: blr
209
210; CHECK-NOVSX-LABEL: @call_v1i128_increment_by_val
211; CHECK-NOVSX-DAG: lvx 2, {{[0-9]+}}, {{[0-9]+}}
212; CHECK-NOVSX-DAG: lvx 3, {{[0-9]+}}, {{[0-9]+}}
213; CHECK-NOVSX-NOT: xxswapd 34, {{[0-9]+}}
214; CHECK-NOVSX-NOT: xxswapd 35, {{[0-9]+}}
215; CHECK-NOVSX: bl v1i128_increment_by_val
216; CHECK-NOVSX: blr
217
218}
219
220define i128 @call_i128_increment_by_one() nounwind {
221       %tmp = load i128, i128* @a, align 16
222       %ret = call i128 @i128_increment_by_one(i128 %tmp)
223       ret i128 %ret
224;       %ret4 = call i128 @i128_increment_by_val(i128 %tmp2, i128 %tmp2)
225; CHECK-LE-LABEL: @call_i128_increment_by_one
226; CHECK-LE-DAG: ld 3, 0([[BASEREG:[0-9]+]])
227; CHECK-LE-DAG: ld 4, 8([[BASEREG]])
228; CHECK-LE: bl i128_increment_by_one
229; CHECK-LE: blr
230
231; CHECK-BE-LABEL: @call_i128_increment_by_one
232; CHECK-BE-DAG: ld 3, 0([[BASEREG:[0-9]+]])
233; CHECK-BE-DAG: ld 4, 8([[BASEREG]])
234; CHECK-BE: bl i128_increment_by_one
235; CHECK-BE: blr
236
237; CHECK-NOVSX-LABEL: @call_i128_increment_by_one
238; CHECK-NOVSX-DAG: ld 3, 0([[BASEREG:[0-9]+]])
239; CHECK-NOVSX-DAG: ld 4, 8([[BASEREG]])
240; CHECK-NOVSX: bl i128_increment_by_one
241; CHECK-NOVSX: blr
242}
243
244define i128 @call_i128_increment_by_val() nounwind {
245       %tmp = load i128, i128* @a, align 16
246       %tmp2 = load i128, i128* @b, align 16
247       %ret = call i128 @i128_increment_by_val(i128 %tmp, i128 %tmp2)
248       ret i128 %ret
249; CHECK-LE-LABEL: @call_i128_increment_by_val
250; CHECK-LE-DAG: ld 3, 0([[P1BASEREG:[0-9]+]])
251; CHECK-LE-DAG: ld 4, 8([[P1BASEREG]])
252; CHECK-LE-DAG: ld 5, 0([[P2BASEREG:[0-9]+]])
253; CHECK-LE-DAG: ld 6, 8([[P2BASEREG]])
254; CHECK-LE: bl i128_increment_by_val
255; CHECK-LE: blr
256
257; CHECK-BE-LABEL: @call_i128_increment_by_val
258; CHECK-BE-DAG: ld 3, 0([[P1BASEREG:[0-9]+]])
259; CHECK-BE-DAG: ld 4, 8([[P1BASEREG]])
260; CHECK-BE-DAG: ld 5, 0([[P2BASEREG:[0-9]+]])
261; CHECK-BE-DAG: ld 6, 8([[P2BASEREG]])
262; CHECK-BE: bl i128_increment_by_val
263; CHECK-BE: blr
264
265; CHECK-NOVSX-LABEL: @call_i128_increment_by_val
266; CHECK-NOVSX-DAG: ld 3, 0([[P1BASEREG:[0-9]+]])
267; CHECK-NOVSX-DAG: ld 4, 8([[P1BASEREG]])
268; CHECK-NOVSX-DAG: ld 5, 0([[P2BASEREG:[0-9]+]])
269; CHECK-NOVSX-DAG: ld 6, 8([[P2BASEREG]])
270; CHECK-NOVSX: bl i128_increment_by_val
271; CHECK-NOVSX: blr
272}
273
274
275