OLD | NEW |
1 ; Tests desired and undesired folding of load instructions into cast | 1 ; Tests desired and undesired folding of load instructions into cast |
2 ; instructions. The folding is only done when liveness analysis is performed, | 2 ; instructions. The folding is only done when liveness analysis is performed, |
3 ; so only O2 is tested. | 3 ; so only O2 is tested. |
4 | 4 |
5 ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s | 5 ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s |
6 | 6 |
7 ; Not testing trunc, or 32-bit bitcast, because the lowered code uses pretty | 7 ; Not testing trunc, or 32-bit bitcast, because the lowered code uses pretty |
8 ; much the same mov instructions regardless of whether folding is done. | 8 ; much the same mov instructions regardless of whether folding is done. |
9 | 9 |
10 define internal i32 @zext_fold(i32 %arg) { | 10 define internal i32 @zext_fold(i32 %arg) { |
11 entry: | 11 entry: |
12 %ptr = add i32 %arg, 200 | 12 %ptr = add i32 %arg, 200 |
13 %addr = inttoptr i32 %ptr to i8* | 13 %addr = inttoptr i32 %ptr to i8* |
14 %load = load i8* %addr, align 1 | 14 %load = load i8, i8* %addr, align 1 |
15 %result = zext i8 %load to i32 | 15 %result = zext i8 %load to i32 |
16 ret i32 %result | 16 ret i32 %result |
17 } | 17 } |
18 ; CHECK-LABEL: zext_fold | 18 ; CHECK-LABEL: zext_fold |
19 ; CHECK: movzx {{.*}},BYTE PTR [{{.*}}+0xc8] | 19 ; CHECK: movzx {{.*}},BYTE PTR [{{.*}}+0xc8] |
20 | 20 |
21 define internal i32 @zext_nofold(i32 %arg) { | 21 define internal i32 @zext_nofold(i32 %arg) { |
22 entry: | 22 entry: |
23 %ptr = add i32 %arg, 200 | 23 %ptr = add i32 %arg, 200 |
24 %addr = inttoptr i32 %ptr to i8* | 24 %addr = inttoptr i32 %ptr to i8* |
25 %load = load i8* %addr, align 1 | 25 %load = load i8, i8* %addr, align 1 |
26 %tmp1 = zext i8 %load to i32 | 26 %tmp1 = zext i8 %load to i32 |
27 %tmp2 = zext i8 %load to i32 | 27 %tmp2 = zext i8 %load to i32 |
28 %result = add i32 %tmp1, %tmp2 | 28 %result = add i32 %tmp1, %tmp2 |
29 ret i32 %result | 29 ret i32 %result |
30 } | 30 } |
31 ; Test that load folding does not happen. | 31 ; Test that load folding does not happen. |
32 ; CHECK-LABEL: zext_nofold | 32 ; CHECK-LABEL: zext_nofold |
33 ; CHECK-NOT: movzx {{.*}},BYTE PTR [{{.*}}+0xc8] | 33 ; CHECK-NOT: movzx {{.*}},BYTE PTR [{{.*}}+0xc8] |
34 | 34 |
35 define internal i32 @sext_fold(i32 %arg) { | 35 define internal i32 @sext_fold(i32 %arg) { |
36 entry: | 36 entry: |
37 %ptr = add i32 %arg, 200 | 37 %ptr = add i32 %arg, 200 |
38 %addr = inttoptr i32 %ptr to i8* | 38 %addr = inttoptr i32 %ptr to i8* |
39 %load = load i8* %addr, align 1 | 39 %load = load i8, i8* %addr, align 1 |
40 %result = sext i8 %load to i32 | 40 %result = sext i8 %load to i32 |
41 ret i32 %result | 41 ret i32 %result |
42 } | 42 } |
43 ; CHECK-LABEL: sext_fold | 43 ; CHECK-LABEL: sext_fold |
44 ; CHECK: movsx {{.*}},BYTE PTR [{{.*}}+0xc8] | 44 ; CHECK: movsx {{.*}},BYTE PTR [{{.*}}+0xc8] |
45 | 45 |
46 define internal i32 @sext_nofold(i32 %arg) { | 46 define internal i32 @sext_nofold(i32 %arg) { |
47 entry: | 47 entry: |
48 %ptr = add i32 %arg, 200 | 48 %ptr = add i32 %arg, 200 |
49 %addr = inttoptr i32 %ptr to i8* | 49 %addr = inttoptr i32 %ptr to i8* |
50 %load = load i8* %addr, align 1 | 50 %load = load i8, i8* %addr, align 1 |
51 %tmp1 = sext i8 %load to i32 | 51 %tmp1 = sext i8 %load to i32 |
52 %tmp2 = sext i8 %load to i32 | 52 %tmp2 = sext i8 %load to i32 |
53 %result = add i32 %tmp1, %tmp2 | 53 %result = add i32 %tmp1, %tmp2 |
54 ret i32 %result | 54 ret i32 %result |
55 } | 55 } |
56 ; Test that load folding does not happen. | 56 ; Test that load folding does not happen. |
57 ; CHECK-LABEL: sext_nofold | 57 ; CHECK-LABEL: sext_nofold |
58 ; CHECK-NOT: movsx {{.*}},BYTE PTR [{{.*}}+0xc8] | 58 ; CHECK-NOT: movsx {{.*}},BYTE PTR [{{.*}}+0xc8] |
59 | 59 |
60 define internal float @fptrunc_fold(i32 %arg) { | 60 define internal float @fptrunc_fold(i32 %arg) { |
61 entry: | 61 entry: |
62 %ptr = add i32 %arg, 200 | 62 %ptr = add i32 %arg, 200 |
63 %addr = inttoptr i32 %ptr to double* | 63 %addr = inttoptr i32 %ptr to double* |
64 %load = load double* %addr, align 8 | 64 %load = load double, double* %addr, align 8 |
65 %result = fptrunc double %load to float | 65 %result = fptrunc double %load to float |
66 ret float %result | 66 ret float %result |
67 } | 67 } |
68 ; CHECK-LABEL: fptrunc_fold | 68 ; CHECK-LABEL: fptrunc_fold |
69 ; CHECK: cvtsd2ss {{.*}},QWORD PTR [{{.*}}+0xc8] | 69 ; CHECK: cvtsd2ss {{.*}},QWORD PTR [{{.*}}+0xc8] |
70 | 70 |
71 define internal float @fptrunc_nofold(i32 %arg) { | 71 define internal float @fptrunc_nofold(i32 %arg) { |
72 entry: | 72 entry: |
73 %ptr = add i32 %arg, 200 | 73 %ptr = add i32 %arg, 200 |
74 %addr = inttoptr i32 %ptr to double* | 74 %addr = inttoptr i32 %ptr to double* |
75 %load = load double* %addr, align 8 | 75 %load = load double, double* %addr, align 8 |
76 %tmp1 = fptrunc double %load to float | 76 %tmp1 = fptrunc double %load to float |
77 %tmp2 = fptrunc double %load to float | 77 %tmp2 = fptrunc double %load to float |
78 %result = fadd float %tmp1, %tmp2 | 78 %result = fadd float %tmp1, %tmp2 |
79 ret float %result | 79 ret float %result |
80 } | 80 } |
81 ; Test that load folding does not happen. | 81 ; Test that load folding does not happen. |
82 ; CHECK-LABEL: fptrunc_nofold | 82 ; CHECK-LABEL: fptrunc_nofold |
83 ; CHECK-NOT: cvtsd2ss {{.*}},QWORD PTR [{{.*}}+0xc8] | 83 ; CHECK-NOT: cvtsd2ss {{.*}},QWORD PTR [{{.*}}+0xc8] |
84 | 84 |
85 define internal double @fpext_fold(i32 %arg) { | 85 define internal double @fpext_fold(i32 %arg) { |
86 entry: | 86 entry: |
87 %ptr = add i32 %arg, 200 | 87 %ptr = add i32 %arg, 200 |
88 %addr = inttoptr i32 %ptr to float* | 88 %addr = inttoptr i32 %ptr to float* |
89 %load = load float* %addr, align 4 | 89 %load = load float, float* %addr, align 4 |
90 %result = fpext float %load to double | 90 %result = fpext float %load to double |
91 ret double %result | 91 ret double %result |
92 } | 92 } |
93 ; CHECK-LABEL: fpext_fold | 93 ; CHECK-LABEL: fpext_fold |
94 ; CHECK: cvtss2sd {{.*}},DWORD PTR [{{.*}}+0xc8] | 94 ; CHECK: cvtss2sd {{.*}},DWORD PTR [{{.*}}+0xc8] |
95 | 95 |
96 define internal double @fpext_nofold(i32 %arg) { | 96 define internal double @fpext_nofold(i32 %arg) { |
97 entry: | 97 entry: |
98 %ptr = add i32 %arg, 200 | 98 %ptr = add i32 %arg, 200 |
99 %addr = inttoptr i32 %ptr to float* | 99 %addr = inttoptr i32 %ptr to float* |
100 %load = load float* %addr, align 4 | 100 %load = load float, float* %addr, align 4 |
101 %tmp1 = fpext float %load to double | 101 %tmp1 = fpext float %load to double |
102 %tmp2 = fpext float %load to double | 102 %tmp2 = fpext float %load to double |
103 %result = fadd double %tmp1, %tmp2 | 103 %result = fadd double %tmp1, %tmp2 |
104 ret double %result | 104 ret double %result |
105 } | 105 } |
106 ; Test that load folding does not happen. | 106 ; Test that load folding does not happen. |
107 ; CHECK-LABEL: fpext_nofold | 107 ; CHECK-LABEL: fpext_nofold |
108 ; CHECK-NOT: cvtss2sd {{.*}},DWORD PTR [{{.*}}+0xc8] | 108 ; CHECK-NOT: cvtss2sd {{.*}},DWORD PTR [{{.*}}+0xc8] |
109 | 109 |
110 define internal i32 @fptoui_fold(i32 %arg) { | 110 define internal i32 @fptoui_fold(i32 %arg) { |
111 entry: | 111 entry: |
112 %ptr = add i32 %arg, 200 | 112 %ptr = add i32 %arg, 200 |
113 %addr = inttoptr i32 %ptr to double* | 113 %addr = inttoptr i32 %ptr to double* |
114 %load = load double* %addr, align 8 | 114 %load = load double, double* %addr, align 8 |
115 %result = fptoui double %load to i16 | 115 %result = fptoui double %load to i16 |
116 %result2 = zext i16 %result to i32 | 116 %result2 = zext i16 %result to i32 |
117 ret i32 %result2 | 117 ret i32 %result2 |
118 } | 118 } |
119 ; CHECK-LABEL: fptoui_fold | 119 ; CHECK-LABEL: fptoui_fold |
120 ; CHECK: cvttsd2si {{.*}},QWORD PTR [{{.*}}+0xc8] | 120 ; CHECK: cvttsd2si {{.*}},QWORD PTR [{{.*}}+0xc8] |
121 | 121 |
122 define internal i32 @fptoui_nofold(i32 %arg) { | 122 define internal i32 @fptoui_nofold(i32 %arg) { |
123 entry: | 123 entry: |
124 %ptr = add i32 %arg, 200 | 124 %ptr = add i32 %arg, 200 |
125 %addr = inttoptr i32 %ptr to double* | 125 %addr = inttoptr i32 %ptr to double* |
126 %load = load double* %addr, align 8 | 126 %load = load double, double* %addr, align 8 |
127 %tmp1 = fptoui double %load to i16 | 127 %tmp1 = fptoui double %load to i16 |
128 %tmp2 = fptoui double %load to i16 | 128 %tmp2 = fptoui double %load to i16 |
129 %result = add i16 %tmp1, %tmp2 | 129 %result = add i16 %tmp1, %tmp2 |
130 %result2 = zext i16 %result to i32 | 130 %result2 = zext i16 %result to i32 |
131 ret i32 %result2 | 131 ret i32 %result2 |
132 } | 132 } |
133 ; Test that load folding does not happen. | 133 ; Test that load folding does not happen. |
134 ; CHECK-LABEL: fptoui_nofold | 134 ; CHECK-LABEL: fptoui_nofold |
135 ; CHECK-NOT: cvttsd2si {{.*}},QWORD PTR [{{.*}}+0xc8] | 135 ; CHECK-NOT: cvttsd2si {{.*}},QWORD PTR [{{.*}}+0xc8] |
136 | 136 |
137 define internal i32 @fptosi_fold(i32 %arg) { | 137 define internal i32 @fptosi_fold(i32 %arg) { |
138 entry: | 138 entry: |
139 %ptr = add i32 %arg, 200 | 139 %ptr = add i32 %arg, 200 |
140 %addr = inttoptr i32 %ptr to double* | 140 %addr = inttoptr i32 %ptr to double* |
141 %load = load double* %addr, align 8 | 141 %load = load double, double* %addr, align 8 |
142 %result = fptosi double %load to i16 | 142 %result = fptosi double %load to i16 |
143 %result2 = zext i16 %result to i32 | 143 %result2 = zext i16 %result to i32 |
144 ret i32 %result2 | 144 ret i32 %result2 |
145 } | 145 } |
146 ; CHECK-LABEL: fptosi_fold | 146 ; CHECK-LABEL: fptosi_fold |
147 ; CHECK: cvttsd2si {{.*}},QWORD PTR [{{.*}}+0xc8] | 147 ; CHECK: cvttsd2si {{.*}},QWORD PTR [{{.*}}+0xc8] |
148 | 148 |
149 define internal i32 @fptosi_nofold(i32 %arg) { | 149 define internal i32 @fptosi_nofold(i32 %arg) { |
150 entry: | 150 entry: |
151 %ptr = add i32 %arg, 200 | 151 %ptr = add i32 %arg, 200 |
152 %addr = inttoptr i32 %ptr to double* | 152 %addr = inttoptr i32 %ptr to double* |
153 %load = load double* %addr, align 8 | 153 %load = load double, double* %addr, align 8 |
154 %tmp1 = fptosi double %load to i16 | 154 %tmp1 = fptosi double %load to i16 |
155 %tmp2 = fptosi double %load to i16 | 155 %tmp2 = fptosi double %load to i16 |
156 %result = add i16 %tmp1, %tmp2 | 156 %result = add i16 %tmp1, %tmp2 |
157 %result2 = zext i16 %result to i32 | 157 %result2 = zext i16 %result to i32 |
158 ret i32 %result2 | 158 ret i32 %result2 |
159 } | 159 } |
160 ; Test that load folding does not happen. | 160 ; Test that load folding does not happen. |
161 ; CHECK-LABEL: fptosi_nofold | 161 ; CHECK-LABEL: fptosi_nofold |
162 ; CHECK-NOT: cvttsd2si {{.*}},QWORD PTR [{{.*}}+0xc8] | 162 ; CHECK-NOT: cvttsd2si {{.*}},QWORD PTR [{{.*}}+0xc8] |
163 | 163 |
164 define internal double @uitofp_fold(i32 %arg) { | 164 define internal double @uitofp_fold(i32 %arg) { |
165 entry: | 165 entry: |
166 %ptr = add i32 %arg, 200 | 166 %ptr = add i32 %arg, 200 |
167 %addr = inttoptr i32 %ptr to i16* | 167 %addr = inttoptr i32 %ptr to i16* |
168 %load = load i16* %addr, align 1 | 168 %load = load i16, i16* %addr, align 1 |
169 %result = uitofp i16 %load to double | 169 %result = uitofp i16 %load to double |
170 ret double %result | 170 ret double %result |
171 } | 171 } |
172 ; CHECK-LABEL: uitofp_fold | 172 ; CHECK-LABEL: uitofp_fold |
173 ; CHECK: movzx {{.*}},WORD PTR [{{.*}}+0xc8] | 173 ; CHECK: movzx {{.*}},WORD PTR [{{.*}}+0xc8] |
174 | 174 |
175 define internal double @uitofp_nofold(i32 %arg) { | 175 define internal double @uitofp_nofold(i32 %arg) { |
176 entry: | 176 entry: |
177 %ptr = add i32 %arg, 200 | 177 %ptr = add i32 %arg, 200 |
178 %addr = inttoptr i32 %ptr to i16* | 178 %addr = inttoptr i32 %ptr to i16* |
179 %load = load i16* %addr, align 1 | 179 %load = load i16, i16* %addr, align 1 |
180 %tmp1 = uitofp i16 %load to double | 180 %tmp1 = uitofp i16 %load to double |
181 %tmp2 = uitofp i16 %load to double | 181 %tmp2 = uitofp i16 %load to double |
182 %result = fadd double %tmp1, %tmp2 | 182 %result = fadd double %tmp1, %tmp2 |
183 ret double %result | 183 ret double %result |
184 } | 184 } |
185 ; Test that load folding does not happen. | 185 ; Test that load folding does not happen. |
186 ; CHECK-LABEL: uitofp_nofold | 186 ; CHECK-LABEL: uitofp_nofold |
187 ; CHECK-NOT: movzx {{.*}},WORD PTR [{{.*}}+0xc8] | 187 ; CHECK-NOT: movzx {{.*}},WORD PTR [{{.*}}+0xc8] |
188 | 188 |
189 define internal double @sitofp_fold(i32 %arg) { | 189 define internal double @sitofp_fold(i32 %arg) { |
190 entry: | 190 entry: |
191 %ptr = add i32 %arg, 200 | 191 %ptr = add i32 %arg, 200 |
192 %addr = inttoptr i32 %ptr to i16* | 192 %addr = inttoptr i32 %ptr to i16* |
193 %load = load i16* %addr, align 1 | 193 %load = load i16, i16* %addr, align 1 |
194 %result = sitofp i16 %load to double | 194 %result = sitofp i16 %load to double |
195 ret double %result | 195 ret double %result |
196 } | 196 } |
197 ; CHECK-LABEL: sitofp_fold | 197 ; CHECK-LABEL: sitofp_fold |
198 ; CHECK: movsx {{.*}},WORD PTR [{{.*}}+0xc8] | 198 ; CHECK: movsx {{.*}},WORD PTR [{{.*}}+0xc8] |
199 | 199 |
200 define internal double @sitofp_nofold(i32 %arg) { | 200 define internal double @sitofp_nofold(i32 %arg) { |
201 entry: | 201 entry: |
202 %ptr = add i32 %arg, 200 | 202 %ptr = add i32 %arg, 200 |
203 %addr = inttoptr i32 %ptr to i16* | 203 %addr = inttoptr i32 %ptr to i16* |
204 %load = load i16* %addr, align 1 | 204 %load = load i16, i16* %addr, align 1 |
205 %tmp1 = sitofp i16 %load to double | 205 %tmp1 = sitofp i16 %load to double |
206 %tmp2 = sitofp i16 %load to double | 206 %tmp2 = sitofp i16 %load to double |
207 %result = fadd double %tmp1, %tmp2 | 207 %result = fadd double %tmp1, %tmp2 |
208 ret double %result | 208 ret double %result |
209 } | 209 } |
210 ; Test that load folding does not happen. | 210 ; Test that load folding does not happen. |
211 ; CHECK-LABEL: sitofp_nofold | 211 ; CHECK-LABEL: sitofp_nofold |
212 ; CHECK-NOT: movsx {{.*}},WORD PTR [{{.*}}+0xc8] | 212 ; CHECK-NOT: movsx {{.*}},WORD PTR [{{.*}}+0xc8] |
213 | 213 |
214 define internal double @bitcast_i64_fold(i32 %arg) { | 214 define internal double @bitcast_i64_fold(i32 %arg) { |
215 entry: | 215 entry: |
216 %ptr = add i32 %arg, 200 | 216 %ptr = add i32 %arg, 200 |
217 %addr = inttoptr i32 %ptr to i64* | 217 %addr = inttoptr i32 %ptr to i64* |
218 %load = load i64* %addr, align 1 | 218 %load = load i64, i64* %addr, align 1 |
219 %result = bitcast i64 %load to double | 219 %result = bitcast i64 %load to double |
220 ret double %result | 220 ret double %result |
221 } | 221 } |
222 ; CHECK-LABEL: bitcast_i64_fold | 222 ; CHECK-LABEL: bitcast_i64_fold |
223 ; CHECK: movq {{.*}},QWORD PTR [{{.*}}+0xc8] | 223 ; CHECK: movq {{.*}},QWORD PTR [{{.*}}+0xc8] |
224 | 224 |
225 define internal double @bitcast_i64_nofold(i32 %arg) { | 225 define internal double @bitcast_i64_nofold(i32 %arg) { |
226 entry: | 226 entry: |
227 %ptr = add i32 %arg, 200 | 227 %ptr = add i32 %arg, 200 |
228 %addr = inttoptr i32 %ptr to i64* | 228 %addr = inttoptr i32 %ptr to i64* |
229 %load = load i64* %addr, align 1 | 229 %load = load i64, i64* %addr, align 1 |
230 %tmp1 = bitcast i64 %load to double | 230 %tmp1 = bitcast i64 %load to double |
231 %tmp2 = bitcast i64 %load to double | 231 %tmp2 = bitcast i64 %load to double |
232 %result = fadd double %tmp1, %tmp2 | 232 %result = fadd double %tmp1, %tmp2 |
233 ret double %result | 233 ret double %result |
234 } | 234 } |
235 ; Test that load folding does not happen. | 235 ; Test that load folding does not happen. |
236 ; CHECK-LABEL: bitcast_i64_nofold | 236 ; CHECK-LABEL: bitcast_i64_nofold |
237 ; CHECK-NOT: movq {{.*}},QWORD PTR [{{.*}}+0xc8] | 237 ; CHECK-NOT: movq {{.*}},QWORD PTR [{{.*}}+0xc8] |
238 | 238 |
239 define internal i64 @bitcast_double_fold(i32 %arg) { | 239 define internal i64 @bitcast_double_fold(i32 %arg) { |
240 entry: | 240 entry: |
241 %ptr = add i32 %arg, 200 | 241 %ptr = add i32 %arg, 200 |
242 %addr = inttoptr i32 %ptr to double* | 242 %addr = inttoptr i32 %ptr to double* |
243 %load = load double* %addr, align 8 | 243 %load = load double, double* %addr, align 8 |
244 %result = bitcast double %load to i64 | 244 %result = bitcast double %load to i64 |
245 ret i64 %result | 245 ret i64 %result |
246 } | 246 } |
247 ; CHECK-LABEL: bitcast_double_fold | 247 ; CHECK-LABEL: bitcast_double_fold |
248 ; CHECK-NOT: QWORD PTR | 248 ; CHECK-NOT: QWORD PTR |
249 ; CHECK: mov {{.*}},DWORD PTR [{{.*}}+0xc8] | 249 ; CHECK: mov {{.*}},DWORD PTR [{{.*}}+0xc8] |
250 ; CHECK: mov {{.*}},DWORD PTR [{{.*}}+0xcc] | 250 ; CHECK: mov {{.*}},DWORD PTR [{{.*}}+0xcc] |
251 ; CHECK-NOT: QWORD PTR | 251 ; CHECK-NOT: QWORD PTR |
252 | 252 |
253 define internal i64 @bitcast_double_nofold(i32 %arg) { | 253 define internal i64 @bitcast_double_nofold(i32 %arg) { |
254 entry: | 254 entry: |
255 %ptr = add i32 %arg, 200 | 255 %ptr = add i32 %arg, 200 |
256 %addr = inttoptr i32 %ptr to double* | 256 %addr = inttoptr i32 %ptr to double* |
257 %load = load double* %addr, align 8 | 257 %load = load double, double* %addr, align 8 |
258 %tmp1 = bitcast double %load to i64 | 258 %tmp1 = bitcast double %load to i64 |
259 %tmp2 = bitcast double %load to i64 | 259 %tmp2 = bitcast double %load to i64 |
260 %result = add i64 %tmp1, %tmp2 | 260 %result = add i64 %tmp1, %tmp2 |
261 ret i64 %result | 261 ret i64 %result |
262 } | 262 } |
263 ; Test that load folding does not happen. | 263 ; Test that load folding does not happen. |
264 ; CHECK-LABEL: bitcast_double_nofold | 264 ; CHECK-LABEL: bitcast_double_nofold |
265 ; CHECK: QWORD PTR | 265 ; CHECK: QWORD PTR |
266 ; CHECK: QWORD PTR | 266 ; CHECK: QWORD PTR |
OLD | NEW |