1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=sparc-unknown-linux-gnu | FileCheck %s --check-prefixes=SPARC
3 ; RUN: llc < %s -mtriple=sparc64-unknown-linux-gnu | FileCheck %s --check-prefixes=SPARC64
5 define { i128, i8 } @muloti_test(i128 %l, i128 %r) unnamed_addr #0 {
6 ; SPARC-LABEL: muloti_test:
7 ; SPARC: .cfi_startproc
8 ; SPARC-NEXT: ! %bb.0: ! %start
9 ; SPARC-NEXT: save %sp, -120, %sp
10 ; SPARC-NEXT: .cfi_def_cfa_register %fp
11 ; SPARC-NEXT: .cfi_window_save
12 ; SPARC-NEXT: .cfi_register %o7, %i7
13 ; SPARC-NEXT: ld [%fp+92], %l4
14 ; SPARC-NEXT: ld [%fp+96], %g2
15 ; SPARC-NEXT: umul %i2, %i5, %g3
16 ; SPARC-NEXT: rd %y, %g4
17 ; SPARC-NEXT: st %g4, [%fp+-12] ! 4-byte Folded Spill
18 ; SPARC-NEXT: umul %i4, %i3, %g4
19 ; SPARC-NEXT: rd %y, %l0
20 ; SPARC-NEXT: st %l0, [%fp+-16] ! 4-byte Folded Spill
21 ; SPARC-NEXT: st %g2, [%sp+96]
22 ; SPARC-NEXT: umul %i5, %i3, %l0
23 ; SPARC-NEXT: rd %y, %l6
24 ; SPARC-NEXT: st %l4, [%sp+92]
25 ; SPARC-NEXT: umul %l4, %i1, %l2
26 ; SPARC-NEXT: rd %y, %l1
27 ; SPARC-NEXT: st %l1, [%fp+-4] ! 4-byte Folded Spill
28 ; SPARC-NEXT: add %g4, %g3, %g3
29 ; SPARC-NEXT: umul %i0, %g2, %g4
30 ; SPARC-NEXT: rd %y, %l1
31 ; SPARC-NEXT: st %l1, [%fp+-8] ! 4-byte Folded Spill
32 ; SPARC-NEXT: add %l6, %g3, %l3
33 ; SPARC-NEXT: umul %i1, %g2, %g2
34 ; SPARC-NEXT: rd %y, %l1
35 ; SPARC-NEXT: add %g4, %l2, %g3
36 ; SPARC-NEXT: add %l1, %g3, %l2
37 ; SPARC-NEXT: addcc %g2, %l0, %l7
38 ; SPARC-NEXT: mov %g0, %l0
39 ; SPARC-NEXT: addxcc %l2, %l3, %l5
40 ; SPARC-NEXT: mov %l0, %o0
41 ; SPARC-NEXT: mov %l0, %o1
42 ; SPARC-NEXT: mov %i2, %o2
43 ; SPARC-NEXT: mov %i3, %o3
44 ; SPARC-NEXT: mov %l0, %o4
45 ; SPARC-NEXT: call __multi3
46 ; SPARC-NEXT: mov %l0, %o5
47 ; SPARC-NEXT: addcc %o1, %l7, %i3
48 ; SPARC-NEXT: addxcc %o0, %l5, %g2
49 ; SPARC-NEXT: mov 1, %g3
50 ; SPARC-NEXT: cmp %g2, %o0
51 ; SPARC-NEXT: bcs .LBB0_2
52 ; SPARC-NEXT: mov %g3, %o4
53 ; SPARC-NEXT: ! %bb.1: ! %start
54 ; SPARC-NEXT: mov %l0, %o4
55 ; SPARC-NEXT: .LBB0_2: ! %start
56 ; SPARC-NEXT: cmp %i3, %o1
57 ; SPARC-NEXT: bcs .LBB0_4
58 ; SPARC-NEXT: mov %g3, %g4
59 ; SPARC-NEXT: ! %bb.3: ! %start
60 ; SPARC-NEXT: mov %l0, %g4
61 ; SPARC-NEXT: .LBB0_4: ! %start
62 ; SPARC-NEXT: cmp %g2, %o0
63 ; SPARC-NEXT: be .LBB0_6
65 ; SPARC-NEXT: ! %bb.5: ! %start
66 ; SPARC-NEXT: mov %o4, %g4
67 ; SPARC-NEXT: .LBB0_6: ! %start
68 ; SPARC-NEXT: cmp %i2, 0
69 ; SPARC-NEXT: bne .LBB0_8
70 ; SPARC-NEXT: mov %g3, %i2
71 ; SPARC-NEXT: ! %bb.7: ! %start
72 ; SPARC-NEXT: mov %l0, %i2
73 ; SPARC-NEXT: .LBB0_8: ! %start
74 ; SPARC-NEXT: cmp %i4, 0
75 ; SPARC-NEXT: bne .LBB0_10
76 ; SPARC-NEXT: mov %g3, %o1
77 ; SPARC-NEXT: ! %bb.9: ! %start
78 ; SPARC-NEXT: mov %l0, %o1
79 ; SPARC-NEXT: .LBB0_10: ! %start
80 ; SPARC-NEXT: ld [%fp+-16], %l5 ! 4-byte Folded Reload
81 ; SPARC-NEXT: cmp %l5, 0
82 ; SPARC-NEXT: bne .LBB0_12
83 ; SPARC-NEXT: mov %g3, %o0
84 ; SPARC-NEXT: ! %bb.11: ! %start
85 ; SPARC-NEXT: mov %l0, %o0
86 ; SPARC-NEXT: .LBB0_12: ! %start
87 ; SPARC-NEXT: ld [%fp+-12], %l5 ! 4-byte Folded Reload
88 ; SPARC-NEXT: cmp %l5, 0
89 ; SPARC-NEXT: bne .LBB0_14
90 ; SPARC-NEXT: mov %g3, %l5
91 ; SPARC-NEXT: ! %bb.13: ! %start
92 ; SPARC-NEXT: mov %l0, %l5
93 ; SPARC-NEXT: .LBB0_14: ! %start
94 ; SPARC-NEXT: cmp %l3, %l6
95 ; SPARC-NEXT: bcs .LBB0_16
96 ; SPARC-NEXT: mov %g3, %l3
97 ; SPARC-NEXT: ! %bb.15: ! %start
98 ; SPARC-NEXT: mov %l0, %l3
99 ; SPARC-NEXT: .LBB0_16: ! %start
100 ; SPARC-NEXT: cmp %l4, 0
101 ; SPARC-NEXT: bne .LBB0_18
102 ; SPARC-NEXT: mov %g3, %l4
103 ; SPARC-NEXT: ! %bb.17: ! %start
104 ; SPARC-NEXT: mov %l0, %l4
105 ; SPARC-NEXT: .LBB0_18: ! %start
106 ; SPARC-NEXT: cmp %i0, 0
107 ; SPARC-NEXT: bne .LBB0_20
108 ; SPARC-NEXT: mov %g3, %l7
109 ; SPARC-NEXT: ! %bb.19: ! %start
110 ; SPARC-NEXT: mov %l0, %l7
111 ; SPARC-NEXT: .LBB0_20: ! %start
112 ; SPARC-NEXT: ld [%fp+-8], %l6 ! 4-byte Folded Reload
113 ; SPARC-NEXT: cmp %l6, 0
114 ; SPARC-NEXT: bne .LBB0_22
115 ; SPARC-NEXT: mov %g3, %l6
116 ; SPARC-NEXT: ! %bb.21: ! %start
117 ; SPARC-NEXT: mov %l0, %l6
118 ; SPARC-NEXT: .LBB0_22: ! %start
119 ; SPARC-NEXT: and %o1, %i2, %i2
120 ; SPARC-NEXT: ld [%fp+-4], %o1 ! 4-byte Folded Reload
121 ; SPARC-NEXT: cmp %o1, 0
122 ; SPARC-NEXT: and %l7, %l4, %o1
123 ; SPARC-NEXT: bne .LBB0_24
124 ; SPARC-NEXT: mov %g3, %l4
125 ; SPARC-NEXT: ! %bb.23: ! %start
126 ; SPARC-NEXT: mov %l0, %l4
127 ; SPARC-NEXT: .LBB0_24: ! %start
128 ; SPARC-NEXT: or %i2, %o0, %l7
129 ; SPARC-NEXT: cmp %l2, %l1
130 ; SPARC-NEXT: or %o1, %l6, %l2
131 ; SPARC-NEXT: bcs .LBB0_26
132 ; SPARC-NEXT: mov %g3, %i2
133 ; SPARC-NEXT: ! %bb.25: ! %start
134 ; SPARC-NEXT: mov %l0, %i2
135 ; SPARC-NEXT: .LBB0_26: ! %start
136 ; SPARC-NEXT: or %l7, %l5, %l1
137 ; SPARC-NEXT: or %i5, %i4, %i4
138 ; SPARC-NEXT: cmp %i4, 0
139 ; SPARC-NEXT: or %l2, %l4, %l2
140 ; SPARC-NEXT: bne .LBB0_28
141 ; SPARC-NEXT: mov %g3, %i4
142 ; SPARC-NEXT: ! %bb.27: ! %start
143 ; SPARC-NEXT: mov %l0, %i4
144 ; SPARC-NEXT: .LBB0_28: ! %start
145 ; SPARC-NEXT: or %l1, %l3, %i5
146 ; SPARC-NEXT: or %i1, %i0, %i0
147 ; SPARC-NEXT: cmp %i0, 0
148 ; SPARC-NEXT: bne .LBB0_30
149 ; SPARC-NEXT: or %l2, %i2, %i0
150 ; SPARC-NEXT: ! %bb.29: ! %start
151 ; SPARC-NEXT: mov %l0, %g3
152 ; SPARC-NEXT: .LBB0_30: ! %start
153 ; SPARC-NEXT: and %g3, %i4, %i1
154 ; SPARC-NEXT: or %i1, %i0, %i0
155 ; SPARC-NEXT: or %i0, %i5, %i0
156 ; SPARC-NEXT: or %i0, %g4, %i0
157 ; SPARC-NEXT: and %i0, 1, %i4
158 ; SPARC-NEXT: mov %g2, %i0
159 ; SPARC-NEXT: mov %i3, %i1
160 ; SPARC-NEXT: mov %o2, %i2
162 ; SPARC-NEXT: restore %g0, %o3, %o3
164 ; SPARC64-LABEL: muloti_test:
165 ; SPARC64: .cfi_startproc
166 ; SPARC64-NEXT: .register %g2, #scratch
167 ; SPARC64-NEXT: ! %bb.0: ! %start
168 ; SPARC64-NEXT: save %sp, -176, %sp
169 ; SPARC64-NEXT: .cfi_def_cfa_register %fp
170 ; SPARC64-NEXT: .cfi_window_save
171 ; SPARC64-NEXT: .cfi_register %o7, %i7
172 ; SPARC64-NEXT: srax %i2, 63, %o0
173 ; SPARC64-NEXT: srax %i1, 63, %o2
174 ; SPARC64-NEXT: mov %i2, %o1
175 ; SPARC64-NEXT: call __multi3
176 ; SPARC64-NEXT: mov %i1, %o3
177 ; SPARC64-NEXT: mov %o0, %i4
178 ; SPARC64-NEXT: mov %o1, %i5
179 ; SPARC64-NEXT: srax %i0, 63, %o0
180 ; SPARC64-NEXT: srax %i3, 63, %o2
181 ; SPARC64-NEXT: mov %i0, %o1
182 ; SPARC64-NEXT: call __multi3
183 ; SPARC64-NEXT: mov %i3, %o3
184 ; SPARC64-NEXT: mov %o0, %l0
185 ; SPARC64-NEXT: add %o1, %i5, %i5
186 ; SPARC64-NEXT: mov 0, %o0
187 ; SPARC64-NEXT: mov %i1, %o1
188 ; SPARC64-NEXT: mov %o0, %o2
189 ; SPARC64-NEXT: call __multi3
190 ; SPARC64-NEXT: mov %i3, %o3
191 ; SPARC64-NEXT: add %o0, %i5, %i1
192 ; SPARC64-NEXT: mov %g0, %i3
193 ; SPARC64-NEXT: cmp %i1, %o0
194 ; SPARC64-NEXT: mov %i3, %i5
195 ; SPARC64-NEXT: movcs %xcc, 1, %i5
196 ; SPARC64-NEXT: cmp %i4, 0
197 ; SPARC64-NEXT: mov %i3, %i4
198 ; SPARC64-NEXT: movne %xcc, 1, %i4
199 ; SPARC64-NEXT: cmp %l0, 0
200 ; SPARC64-NEXT: mov %i3, %g2
201 ; SPARC64-NEXT: movne %xcc, 1, %g2
202 ; SPARC64-NEXT: cmp %i2, 0
203 ; SPARC64-NEXT: mov %i3, %i2
204 ; SPARC64-NEXT: movne %xcc, 1, %i2
205 ; SPARC64-NEXT: cmp %i0, 0
206 ; SPARC64-NEXT: movne %xcc, 1, %i3
207 ; SPARC64-NEXT: and %i3, %i2, %i0
208 ; SPARC64-NEXT: or %i0, %g2, %i0
209 ; SPARC64-NEXT: or %i0, %i4, %i0
210 ; SPARC64-NEXT: or %i0, %i5, %i0
211 ; SPARC64-NEXT: srl %i0, 0, %i2
212 ; SPARC64-NEXT: mov %i1, %i0
214 ; SPARC64-NEXT: restore %g0, %o1, %o1
216 %0 = tail call { i128, i1 } @llvm.umul.with.overflow.i128(i128 %l, i128 %r) #2
217 %1 = extractvalue { i128, i1 } %0, 0
218 %2 = extractvalue { i128, i1 } %0, 1
219 %3 = zext i1 %2 to i8
220 %4 = insertvalue { i128, i8 } undef, i128 %1, 0
221 %5 = insertvalue { i128, i8 } %4, i8 %3, 1
225 ; Function Attrs: nounwind readnone speculatable
226 declare { i128, i1 } @llvm.umul.with.overflow.i128(i128, i128) #1
228 attributes #0 = { nounwind readnone uwtable }
229 attributes #1 = { nounwind readnone speculatable }
230 attributes #2 = { nounwind }