OLD | NEW |
1 ; Assembly test for simple arithmetic operations. | 1 ; Assembly test for simple arithmetic operations. |
2 | 2 |
3 ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ | 3 ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ |
4 ; RUN: --target x8632 -i %s --args -O2 \ | 4 ; RUN: --target x8632 -i %s --args -O2 \ |
5 ; RUN: | %if --need=target_X8632 --command FileCheck %s | 5 ; RUN: | %if --need=target_X8632 --command FileCheck %s |
6 | 6 |
7 ; TODO(jvoung): Stop skipping unimplemented parts (via --skip-unimplemented) | 7 ; TODO(jvoung): Stop skipping unimplemented parts (via --skip-unimplemented) |
8 ; once enough infrastructure is in. Also, switch to --filetype=obj | 8 ; once enough infrastructure is in. Also, switch to --filetype=obj |
9 ; when possible. | 9 ; when possible. |
10 ; RUN: %if --need=target_ARM32 --need=allow_dump \ | 10 ; RUN: %if --need=target_ARM32 --need=allow_dump \ |
11 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target arm32 \ | 11 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target arm32 \ |
12 ; RUN: -i %s --args -O2 --skip-unimplemented \ | 12 ; RUN: -i %s --args -O2 --skip-unimplemented \ |
13 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ | 13 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ |
14 ; RUN: --command FileCheck --check-prefix ARM32 %s | 14 ; RUN: --command FileCheck --check-prefix ARM32 %s |
15 ; RUN: %if --need=target_ARM32 --need=allow_dump \ | 15 ; RUN: %if --need=target_ARM32 --need=allow_dump \ |
16 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target arm32 \ | 16 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target arm32 \ |
17 ; RUN: -i %s --args -O2 --mattr=hwdiv-arm --skip-unimplemented \ | 17 ; RUN: -i %s --args -O2 --mattr=hwdiv-arm --skip-unimplemented \ |
18 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ | 18 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ |
19 ; RUN: --command FileCheck --check-prefix ARM32HWDIV %s | 19 ; RUN: --command FileCheck --check-prefix ARM32HWDIV %s |
20 ; RUN: %if --need=target_ARM32 --need=allow_dump \ | 20 ; RUN: %if --need=target_ARM32 --need=allow_dump \ |
21 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target arm32 \ | 21 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target arm32 \ |
22 ; RUN: -i %s --args -Om1 --skip-unimplemented \ | 22 ; RUN: -i %s --args -Om1 --skip-unimplemented \ |
23 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ | 23 ; RUN: | %if --need=target_ARM32 --need=allow_dump \ |
24 ; RUN: --command FileCheck --check-prefix ARM32 %s | 24 ; RUN: --command FileCheck --check-prefix ARM32 %s |
25 | 25 |
26 define i32 @Add(i32 %a, i32 %b) { | 26 define internal i32 @Add(i32 %a, i32 %b) { |
27 entry: | 27 entry: |
28 %add = add i32 %b, %a | 28 %add = add i32 %b, %a |
29 ret i32 %add | 29 ret i32 %add |
30 } | 30 } |
31 ; CHECK-LABEL: Add | 31 ; CHECK-LABEL: Add |
32 ; CHECK: add e | 32 ; CHECK: add e |
33 ; ARM32-LABEL: Add | 33 ; ARM32-LABEL: Add |
34 ; ARM32: add r | 34 ; ARM32: add r |
35 | 35 |
36 define i32 @And(i32 %a, i32 %b) { | 36 define internal i32 @And(i32 %a, i32 %b) { |
37 entry: | 37 entry: |
38 %and = and i32 %b, %a | 38 %and = and i32 %b, %a |
39 ret i32 %and | 39 ret i32 %and |
40 } | 40 } |
41 ; CHECK-LABEL: And | 41 ; CHECK-LABEL: And |
42 ; CHECK: and e | 42 ; CHECK: and e |
43 ; ARM32-LABEL: And | 43 ; ARM32-LABEL: And |
44 ; ARM32: and r | 44 ; ARM32: and r |
45 | 45 |
46 define i32 @Or(i32 %a, i32 %b) { | 46 define internal i32 @Or(i32 %a, i32 %b) { |
47 entry: | 47 entry: |
48 %or = or i32 %b, %a | 48 %or = or i32 %b, %a |
49 ret i32 %or | 49 ret i32 %or |
50 } | 50 } |
51 ; CHECK-LABEL: Or | 51 ; CHECK-LABEL: Or |
52 ; CHECK: or e | 52 ; CHECK: or e |
53 ; ARM32-LABEL: Or | 53 ; ARM32-LABEL: Or |
54 ; ARM32: orr r | 54 ; ARM32: orr r |
55 | 55 |
56 define i32 @Xor(i32 %a, i32 %b) { | 56 define internal i32 @Xor(i32 %a, i32 %b) { |
57 entry: | 57 entry: |
58 %xor = xor i32 %b, %a | 58 %xor = xor i32 %b, %a |
59 ret i32 %xor | 59 ret i32 %xor |
60 } | 60 } |
61 ; CHECK-LABEL: Xor | 61 ; CHECK-LABEL: Xor |
62 ; CHECK: xor e | 62 ; CHECK: xor e |
63 ; ARM32-LABEL: Xor | 63 ; ARM32-LABEL: Xor |
64 ; ARM32: eor r | 64 ; ARM32: eor r |
65 | 65 |
66 define i32 @Sub(i32 %a, i32 %b) { | 66 define internal i32 @Sub(i32 %a, i32 %b) { |
67 entry: | 67 entry: |
68 %sub = sub i32 %a, %b | 68 %sub = sub i32 %a, %b |
69 ret i32 %sub | 69 ret i32 %sub |
70 } | 70 } |
71 ; CHECK-LABEL: Sub | 71 ; CHECK-LABEL: Sub |
72 ; CHECK: sub e | 72 ; CHECK: sub e |
73 ; ARM32-LABEL: Sub | 73 ; ARM32-LABEL: Sub |
74 ; ARM32: sub r | 74 ; ARM32: sub r |
75 | 75 |
76 define i32 @Mul(i32 %a, i32 %b) { | 76 define internal i32 @Mul(i32 %a, i32 %b) { |
77 entry: | 77 entry: |
78 %mul = mul i32 %b, %a | 78 %mul = mul i32 %b, %a |
79 ret i32 %mul | 79 ret i32 %mul |
80 } | 80 } |
81 ; CHECK-LABEL: Mul | 81 ; CHECK-LABEL: Mul |
82 ; CHECK: imul e | 82 ; CHECK: imul e |
83 ; ARM32-LABEL: Mul | 83 ; ARM32-LABEL: Mul |
84 ; ARM32: mul r | 84 ; ARM32: mul r |
85 | 85 |
86 ; Check for a valid ARM mul instruction where operands have to be registers. | 86 ; Check for a valid ARM mul instruction where operands have to be registers. |
87 ; On the other hand x86-32 does allow an immediate. | 87 ; On the other hand x86-32 does allow an immediate. |
88 define i32 @MulImm(i32 %a, i32 %b) { | 88 define internal i32 @MulImm(i32 %a, i32 %b) { |
89 entry: | 89 entry: |
90 %mul = mul i32 %a, 99 | 90 %mul = mul i32 %a, 99 |
91 ret i32 %mul | 91 ret i32 %mul |
92 } | 92 } |
93 ; CHECK-LABEL: MulImm | 93 ; CHECK-LABEL: MulImm |
94 ; CHECK: imul e{{.*}},e{{.*}},0x63 | 94 ; CHECK: imul e{{.*}},e{{.*}},0x63 |
95 ; ARM32-LABEL: MulImm | 95 ; ARM32-LABEL: MulImm |
96 ; ARM32: mov {{.*}}, #99 | 96 ; ARM32: mov {{.*}}, #99 |
97 ; ARM32: mul r{{.*}}, r{{.*}}, r{{.*}} | 97 ; ARM32: mul r{{.*}}, r{{.*}}, r{{.*}} |
98 | 98 |
99 ; Check for a valid addressing mode in the x86-32 mul instruction when | 99 ; Check for a valid addressing mode in the x86-32 mul instruction when |
100 ; the second source operand is an immediate. | 100 ; the second source operand is an immediate. |
101 define i64 @MulImm64(i64 %a) { | 101 define internal i64 @MulImm64(i64 %a) { |
102 entry: | 102 entry: |
103 %mul = mul i64 %a, 99 | 103 %mul = mul i64 %a, 99 |
104 ret i64 %mul | 104 ret i64 %mul |
105 } | 105 } |
106 ; NOTE: the lowering is currently a bit inefficient for small 64-bit constants. | 106 ; NOTE: the lowering is currently a bit inefficient for small 64-bit constants. |
107 ; The top bits of the immediate are 0, but the instructions modeling that | 107 ; The top bits of the immediate are 0, but the instructions modeling that |
108 ; multiply by 0 are not eliminated (see expanded 64-bit ARM lowering). | 108 ; multiply by 0 are not eliminated (see expanded 64-bit ARM lowering). |
109 ; CHECK-LABEL: MulImm64 | 109 ; CHECK-LABEL: MulImm64 |
110 ; CHECK: mov {{.*}},0x63 | 110 ; CHECK: mov {{.*}},0x63 |
111 ; CHECK: mov {{.*}},0x0 | 111 ; CHECK: mov {{.*}},0x0 |
112 ; CHECK-NOT: mul {{[0-9]+}} | 112 ; CHECK-NOT: mul {{[0-9]+}} |
113 ; | 113 ; |
114 ; ARM32-LABEL: MulImm64 | 114 ; ARM32-LABEL: MulImm64 |
115 ; ARM32: movw {{.*}}, #99 | 115 ; ARM32: movw {{.*}}, #99 |
116 ; ARM32: movw {{.*}}, #0 | 116 ; ARM32: movw {{.*}}, #0 |
117 ; ARM32: mul r | 117 ; ARM32: mul r |
118 ; ARM32: mla r | 118 ; ARM32: mla r |
119 ; ARM32: umull r | 119 ; ARM32: umull r |
120 ; ARM32: add r | 120 ; ARM32: add r |
121 | 121 |
122 define i32 @Sdiv(i32 %a, i32 %b) { | 122 define internal i32 @Sdiv(i32 %a, i32 %b) { |
123 entry: | 123 entry: |
124 %div = sdiv i32 %a, %b | 124 %div = sdiv i32 %a, %b |
125 ret i32 %div | 125 ret i32 %div |
126 } | 126 } |
127 ; CHECK-LABEL: Sdiv | 127 ; CHECK-LABEL: Sdiv |
128 ; CHECK: cdq | 128 ; CHECK: cdq |
129 ; CHECK: idiv e | 129 ; CHECK: idiv e |
130 ; | 130 ; |
131 ; ARM32-LABEL: Sdiv | 131 ; ARM32-LABEL: Sdiv |
132 ; ARM32: tst [[DENOM:r.*]], [[DENOM]] | 132 ; ARM32: tst [[DENOM:r.*]], [[DENOM]] |
133 ; ARM32: bne | 133 ; ARM32: bne |
134 ; ARM32: .word 0xe7fedef0 | 134 ; ARM32: .word 0xe7fedef0 |
135 ; ARM32: {{.*}} bl {{.*}} __divsi3 | 135 ; ARM32: {{.*}} bl {{.*}} __divsi3 |
136 ; ARM32HWDIV-LABEL: Sdiv | 136 ; ARM32HWDIV-LABEL: Sdiv |
137 ; ARM32HWDIV: tst | 137 ; ARM32HWDIV: tst |
138 ; ARM32HWDIV: bne | 138 ; ARM32HWDIV: bne |
139 ; ARM32HWDIV: sdiv | 139 ; ARM32HWDIV: sdiv |
140 | 140 |
141 define i32 @SdivConst(i32 %a) { | 141 define internal i32 @SdivConst(i32 %a) { |
142 entry: | 142 entry: |
143 %div = sdiv i32 %a, 219 | 143 %div = sdiv i32 %a, 219 |
144 ret i32 %div | 144 ret i32 %div |
145 } | 145 } |
146 ; CHECK-LABEL: SdivConst | 146 ; CHECK-LABEL: SdivConst |
147 ; CHECK: cdq | 147 ; CHECK: cdq |
148 ; CHECK: idiv e | 148 ; CHECK: idiv e |
149 ; | 149 ; |
150 ; ARM32-LABEL: SdivConst | 150 ; ARM32-LABEL: SdivConst |
151 ; ARM32-NOT: tst | 151 ; ARM32-NOT: tst |
152 ; ARM32: bl {{.*}} __divsi3 | 152 ; ARM32: bl {{.*}} __divsi3 |
153 ; ARM32HWDIV-LABEL: SdivConst | 153 ; ARM32HWDIV-LABEL: SdivConst |
154 ; ARM32HWDIV-NOT: tst | 154 ; ARM32HWDIV-NOT: tst |
155 ; ARM32HWDIV: sdiv | 155 ; ARM32HWDIV: sdiv |
156 | 156 |
157 define i32 @Srem(i32 %a, i32 %b) { | 157 define internal i32 @Srem(i32 %a, i32 %b) { |
158 entry: | 158 entry: |
159 %rem = srem i32 %a, %b | 159 %rem = srem i32 %a, %b |
160 ret i32 %rem | 160 ret i32 %rem |
161 } | 161 } |
162 ; CHECK-LABEL: Srem | 162 ; CHECK-LABEL: Srem |
163 ; CHECK: cdq | 163 ; CHECK: cdq |
164 ; CHECK: idiv e | 164 ; CHECK: idiv e |
165 ; | 165 ; |
166 ; ARM32-LABEL: Srem | 166 ; ARM32-LABEL: Srem |
167 ; ARM32: tst [[DENOM:r.*]], [[DENOM]] | 167 ; ARM32: tst [[DENOM:r.*]], [[DENOM]] |
168 ; ARM32: bne | 168 ; ARM32: bne |
169 ; ARM32: bl {{.*}} __modsi3 | 169 ; ARM32: bl {{.*}} __modsi3 |
170 ; ARM32HWDIV-LABEL: Srem | 170 ; ARM32HWDIV-LABEL: Srem |
171 ; ARM32HWDIV: tst | 171 ; ARM32HWDIV: tst |
172 ; ARM32HWDIV: bne | 172 ; ARM32HWDIV: bne |
173 ; ARM32HWDIV: sdiv | 173 ; ARM32HWDIV: sdiv |
174 ; ARM32HWDIV: mls | 174 ; ARM32HWDIV: mls |
175 | 175 |
176 define i32 @Udiv(i32 %a, i32 %b) { | 176 define internal i32 @Udiv(i32 %a, i32 %b) { |
177 entry: | 177 entry: |
178 %div = udiv i32 %a, %b | 178 %div = udiv i32 %a, %b |
179 ret i32 %div | 179 ret i32 %div |
180 } | 180 } |
181 ; CHECK-LABEL: Udiv | 181 ; CHECK-LABEL: Udiv |
182 ; CHECK: div e | 182 ; CHECK: div e |
183 ; | 183 ; |
184 ; ARM32-LABEL: Udiv | 184 ; ARM32-LABEL: Udiv |
185 ; ARM32: tst [[DENOM:r.*]], [[DENOM]] | 185 ; ARM32: tst [[DENOM:r.*]], [[DENOM]] |
186 ; ARM32: bne | 186 ; ARM32: bne |
187 ; ARM32: bl {{.*}} __udivsi3 | 187 ; ARM32: bl {{.*}} __udivsi3 |
188 ; ARM32HWDIV-LABEL: Udiv | 188 ; ARM32HWDIV-LABEL: Udiv |
189 ; ARM32HWDIV: tst | 189 ; ARM32HWDIV: tst |
190 ; ARM32HWDIV: bne | 190 ; ARM32HWDIV: bne |
191 ; ARM32HWDIV: udiv | 191 ; ARM32HWDIV: udiv |
192 | 192 |
193 define i32 @Urem(i32 %a, i32 %b) { | 193 define internal i32 @Urem(i32 %a, i32 %b) { |
194 entry: | 194 entry: |
195 %rem = urem i32 %a, %b | 195 %rem = urem i32 %a, %b |
196 ret i32 %rem | 196 ret i32 %rem |
197 } | 197 } |
198 ; CHECK-LABEL: Urem | 198 ; CHECK-LABEL: Urem |
199 ; CHECK: div e | 199 ; CHECK: div e |
200 ; | 200 ; |
201 ; ARM32-LABEL: Urem | 201 ; ARM32-LABEL: Urem |
202 ; ARM32: tst [[DENOM:r.*]], [[DENOM]] | 202 ; ARM32: tst [[DENOM:r.*]], [[DENOM]] |
203 ; ARM32: bne | 203 ; ARM32: bne |
204 ; ARM32: bl {{.*}} __umodsi3 | 204 ; ARM32: bl {{.*}} __umodsi3 |
205 ; ARM32HWDIV-LABEL: Urem | 205 ; ARM32HWDIV-LABEL: Urem |
206 ; ARM32HWDIV: tst | 206 ; ARM32HWDIV: tst |
207 ; ARM32HWDIV: bne | 207 ; ARM32HWDIV: bne |
208 ; ARM32HWDIV: udiv | 208 ; ARM32HWDIV: udiv |
209 ; ARM32HWDIV: mls | 209 ; ARM32HWDIV: mls |
210 | 210 |
211 ; The following tests check that shift instructions don't try to use a | 211 ; The following tests check that shift instructions don't try to use a |
212 ; ConstantRelocatable as an immediate operand. | 212 ; ConstantRelocatable as an immediate operand. |
213 | 213 |
214 @G = internal global [4 x i8] zeroinitializer, align 4 | 214 @G = internal global [4 x i8] zeroinitializer, align 4 |
215 | 215 |
216 define i32 @ShlReloc(i32 %a) { | 216 define internal i32 @ShlReloc(i32 %a) { |
217 entry: | 217 entry: |
218 %opnd = ptrtoint [4 x i8]* @G to i32 | 218 %opnd = ptrtoint [4 x i8]* @G to i32 |
219 %result = shl i32 %a, %opnd | 219 %result = shl i32 %a, %opnd |
220 ret i32 %result | 220 ret i32 %result |
221 } | 221 } |
222 ; CHECK-LABEL: ShlReloc | 222 ; CHECK-LABEL: ShlReloc |
223 ; CHECK: shl {{.*}},cl | 223 ; CHECK: shl {{.*}},cl |
224 | 224 |
225 define i32 @LshrReloc(i32 %a) { | 225 define internal i32 @LshrReloc(i32 %a) { |
226 entry: | 226 entry: |
227 %opnd = ptrtoint [4 x i8]* @G to i32 | 227 %opnd = ptrtoint [4 x i8]* @G to i32 |
228 %result = lshr i32 %a, %opnd | 228 %result = lshr i32 %a, %opnd |
229 ret i32 %result | 229 ret i32 %result |
230 } | 230 } |
231 ; CHECK-LABEL: LshrReloc | 231 ; CHECK-LABEL: LshrReloc |
232 ; CHECK: shr {{.*}},cl | 232 ; CHECK: shr {{.*}},cl |
233 | 233 |
234 define i32 @AshrReloc(i32 %a) { | 234 define internal i32 @AshrReloc(i32 %a) { |
235 entry: | 235 entry: |
236 %opnd = ptrtoint [4 x i8]* @G to i32 | 236 %opnd = ptrtoint [4 x i8]* @G to i32 |
237 %result = ashr i32 %a, %opnd | 237 %result = ashr i32 %a, %opnd |
238 ret i32 %result | 238 ret i32 %result |
239 } | 239 } |
240 ; CHECK-LABEL: AshrReloc | 240 ; CHECK-LABEL: AshrReloc |
241 ; CHECK: sar {{.*}},cl | 241 ; CHECK: sar {{.*}},cl |
OLD | NEW |