1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mcpu=generic -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X32 3 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux | FileCheck %s --check-prefixes=X64,X64-LINUX 4 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-win32 | FileCheck %s --check-prefixes=X64,X64-WIN32 5 6 declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) 7 declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) 8 9 ; The immediate can be encoded in a smaller way if the 10 ; instruction is a sub instead of an add. 11 define i32 @test1(i32 inreg %a) nounwind { 12 ; X32-LABEL: test1: 13 ; X32: # %bb.0: # %entry 14 ; X32-NEXT: subl $-128, %eax 15 ; X32-NEXT: retl 16 ; 17 ; X64-LINUX-LABEL: test1: 18 ; X64-LINUX: # %bb.0: # %entry 19 ; X64-LINUX-NEXT: subl $-128, %edi 20 ; X64-LINUX-NEXT: movl %edi, %eax 21 ; X64-LINUX-NEXT: retq 22 ; 23 ; X64-WIN32-LABEL: test1: 24 ; X64-WIN32: # %bb.0: # %entry 25 ; X64-WIN32-NEXT: subl $-128, %ecx 26 ; X64-WIN32-NEXT: movl %ecx, %eax 27 ; X64-WIN32-NEXT: retq 28 entry: 29 %b = add i32 %a, 128 30 ret i32 %b 31 } 32 define i64 @test2(i64 inreg %a) nounwind { 33 ; X32-LABEL: test2: 34 ; X32: # %bb.0: # %entry 35 ; X32-NEXT: addl $-2147483648, %eax # imm = 0x80000000 36 ; X32-NEXT: adcl $0, %edx 37 ; X32-NEXT: retl 38 ; 39 ; X64-LINUX-LABEL: test2: 40 ; X64-LINUX: # %bb.0: # %entry 41 ; X64-LINUX-NEXT: subq $-2147483648, %rdi # imm = 0x80000000 42 ; X64-LINUX-NEXT: movq %rdi, %rax 43 ; X64-LINUX-NEXT: retq 44 ; 45 ; X64-WIN32-LABEL: test2: 46 ; X64-WIN32: # %bb.0: # %entry 47 ; X64-WIN32-NEXT: subq $-2147483648, %rcx # imm = 0x80000000 48 ; X64-WIN32-NEXT: movq %rcx, %rax 49 ; X64-WIN32-NEXT: retq 50 entry: 51 %b = add i64 %a, 2147483648 52 ret i64 %b 53 } 54 define i64 @test3(i64 inreg %a) nounwind { 55 ; X32-LABEL: test3: 56 ; X32: # %bb.0: # %entry 57 ; X32-NEXT: addl $128, %eax 58 ; X32-NEXT: adcl $0, %edx 59 ; X32-NEXT: retl 60 ; 61 ; X64-LINUX-LABEL: test3: 62 ; X64-LINUX: # %bb.0: # %entry 63 ; X64-LINUX-NEXT: subq $-128, %rdi 64 ; X64-LINUX-NEXT: movq %rdi, %rax 65 ; X64-LINUX-NEXT: retq 66 ; 67 ; X64-WIN32-LABEL: test3: 68 ; X64-WIN32: # %bb.0: # %entry 69 ; X64-WIN32-NEXT: subq $-128, %rcx 70 ; X64-WIN32-NEXT: movq %rcx, %rax 71 ; X64-WIN32-NEXT: retq 72 entry: 73 %b = add i64 %a, 128 74 ret i64 %b 75 } 76 77 define i1 @test4(i32 %v1, i32 %v2, i32* %X) nounwind { 78 ; X32-LABEL: test4: 79 ; X32: # %bb.0: # %entry 80 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 81 ; X32-NEXT: addl {{[0-9]+}}(%esp), %eax 82 ; X32-NEXT: jo .LBB3_2 83 ; X32-NEXT: # %bb.1: # %normal 84 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 85 ; X32-NEXT: movl $0, (%eax) 86 ; X32-NEXT: .LBB3_2: # %overflow 87 ; X32-NEXT: xorl %eax, %eax 88 ; X32-NEXT: retl 89 ; 90 ; X64-LINUX-LABEL: test4: 91 ; X64-LINUX: # %bb.0: # %entry 92 ; X64-LINUX-NEXT: addl %esi, %edi 93 ; X64-LINUX-NEXT: jo .LBB3_2 94 ; X64-LINUX-NEXT: # %bb.1: # %normal 95 ; X64-LINUX-NEXT: movl $0, (%rdx) 96 ; X64-LINUX-NEXT: .LBB3_2: # %overflow 97 ; X64-LINUX-NEXT: xorl %eax, %eax 98 ; X64-LINUX-NEXT: retq 99 ; 100 ; X64-WIN32-LABEL: test4: 101 ; X64-WIN32: # %bb.0: # %entry 102 ; X64-WIN32-NEXT: addl %edx, %ecx 103 ; X64-WIN32-NEXT: jo .LBB3_2 104 ; X64-WIN32-NEXT: # %bb.1: # %normal 105 ; X64-WIN32-NEXT: movl $0, (%r8) 106 ; X64-WIN32-NEXT: .LBB3_2: # %overflow 107 ; X64-WIN32-NEXT: xorl %eax, %eax 108 ; X64-WIN32-NEXT: retq 109 entry: 110 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) 111 %sum = extractvalue {i32, i1} %t, 0 112 %obit = extractvalue {i32, i1} %t, 1 113 br i1 %obit, label %overflow, label %normal 114 115 normal: 116 store i32 0, i32* %X 117 br label %overflow 118 119 overflow: 120 ret i1 false 121 } 122 123 define i1 @test5(i32 %v1, i32 %v2, i32* %X) nounwind { 124 ; X32-LABEL: test5: 125 ; X32: # %bb.0: # %entry 126 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 127 ; X32-NEXT: addl {{[0-9]+}}(%esp), %eax 128 ; X32-NEXT: jb .LBB4_2 129 ; X32-NEXT: # %bb.1: # %normal 130 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 131 ; X32-NEXT: movl $0, (%eax) 132 ; X32-NEXT: .LBB4_2: # %carry 133 ; X32-NEXT: xorl %eax, %eax 134 ; X32-NEXT: retl 135 ; 136 ; X64-LINUX-LABEL: test5: 137 ; X64-LINUX: # %bb.0: # %entry 138 ; X64-LINUX-NEXT: addl %esi, %edi 139 ; X64-LINUX-NEXT: jb .LBB4_2 140 ; X64-LINUX-NEXT: # %bb.1: # %normal 141 ; X64-LINUX-NEXT: movl $0, (%rdx) 142 ; X64-LINUX-NEXT: .LBB4_2: # %carry 143 ; X64-LINUX-NEXT: xorl %eax, %eax 144 ; X64-LINUX-NEXT: retq 145 ; 146 ; X64-WIN32-LABEL: test5: 147 ; X64-WIN32: # %bb.0: # %entry 148 ; X64-WIN32-NEXT: addl %edx, %ecx 149 ; X64-WIN32-NEXT: jb .LBB4_2 150 ; X64-WIN32-NEXT: # %bb.1: # %normal 151 ; X64-WIN32-NEXT: movl $0, (%r8) 152 ; X64-WIN32-NEXT: .LBB4_2: # %carry 153 ; X64-WIN32-NEXT: xorl %eax, %eax 154 ; X64-WIN32-NEXT: retq 155 entry: 156 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 157 %sum = extractvalue {i32, i1} %t, 0 158 %obit = extractvalue {i32, i1} %t, 1 159 br i1 %obit, label %carry, label %normal 160 161 normal: 162 store i32 0, i32* %X 163 br label %carry 164 165 carry: 166 ret i1 false 167 } 168 169 define i64 @test6(i64 %A, i32 %B) nounwind { 170 ; X32-LABEL: test6: 171 ; X32: # %bb.0: # %entry 172 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 173 ; X32-NEXT: movl {{[0-9]+}}(%esp), %edx 174 ; X32-NEXT: addl {{[0-9]+}}(%esp), %edx 175 ; X32-NEXT: retl 176 ; 177 ; X64-LINUX-LABEL: test6: 178 ; X64-LINUX: # %bb.0: # %entry 179 ; X64-LINUX-NEXT: # kill: def $esi killed $esi def $rsi 180 ; X64-LINUX-NEXT: shlq $32, %rsi 181 ; X64-LINUX-NEXT: leaq (%rsi,%rdi), %rax 182 ; X64-LINUX-NEXT: retq 183 ; 184 ; X64-WIN32-LABEL: test6: 185 ; X64-WIN32: # %bb.0: # %entry 186 ; X64-WIN32-NEXT: # kill: def $edx killed $edx def $rdx 187 ; X64-WIN32-NEXT: shlq $32, %rdx 188 ; X64-WIN32-NEXT: leaq (%rdx,%rcx), %rax 189 ; X64-WIN32-NEXT: retq 190 entry: 191 %tmp12 = zext i32 %B to i64 192 %tmp3 = shl i64 %tmp12, 32 193 %tmp5 = add i64 %tmp3, %A 194 ret i64 %tmp5 195 } 196 197 define {i32, i1} @test7(i32 %v1, i32 %v2) nounwind { 198 ; X32-LABEL: test7: 199 ; X32: # %bb.0: # %entry 200 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 201 ; X32-NEXT: addl {{[0-9]+}}(%esp), %eax 202 ; X32-NEXT: setb %dl 203 ; X32-NEXT: retl 204 ; 205 ; X64-LINUX-LABEL: test7: 206 ; X64-LINUX: # %bb.0: # %entry 207 ; X64-LINUX-NEXT: addl %esi, %edi 208 ; X64-LINUX-NEXT: setb %dl 209 ; X64-LINUX-NEXT: movl %edi, %eax 210 ; X64-LINUX-NEXT: retq 211 ; 212 ; X64-WIN32-LABEL: test7: 213 ; X64-WIN32: # %bb.0: # %entry 214 ; X64-WIN32-NEXT: addl %edx, %ecx 215 ; X64-WIN32-NEXT: setb %dl 216 ; X64-WIN32-NEXT: movl %ecx, %eax 217 ; X64-WIN32-NEXT: retq 218 entry: 219 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 220 ret {i32, i1} %t 221 } 222 223 ; PR5443 224 define {i64, i1} @test8(i64 %left, i64 %right) nounwind { 225 ; X32-LABEL: test8: 226 ; X32: # %bb.0: # %entry 227 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 228 ; X32-NEXT: movl {{[0-9]+}}(%esp), %edx 229 ; X32-NEXT: addl {{[0-9]+}}(%esp), %eax 230 ; X32-NEXT: adcl {{[0-9]+}}(%esp), %edx 231 ; X32-NEXT: setb %cl 232 ; X32-NEXT: retl 233 ; 234 ; X64-LINUX-LABEL: test8: 235 ; X64-LINUX: # %bb.0: # %entry 236 ; X64-LINUX-NEXT: addq %rsi, %rdi 237 ; X64-LINUX-NEXT: setb %dl 238 ; X64-LINUX-NEXT: movq %rdi, %rax 239 ; X64-LINUX-NEXT: retq 240 ; 241 ; X64-WIN32-LABEL: test8: 242 ; X64-WIN32: # %bb.0: # %entry 243 ; X64-WIN32-NEXT: addq %rdx, %rcx 244 ; X64-WIN32-NEXT: setb %dl 245 ; X64-WIN32-NEXT: movq %rcx, %rax 246 ; X64-WIN32-NEXT: retq 247 entry: 248 %extleft = zext i64 %left to i65 249 %extright = zext i64 %right to i65 250 %sum = add i65 %extleft, %extright 251 %res.0 = trunc i65 %sum to i64 252 %overflow = and i65 %sum, -18446744073709551616 253 %res.1 = icmp ne i65 %overflow, 0 254 %final0 = insertvalue {i64, i1} undef, i64 %res.0, 0 255 %final1 = insertvalue {i64, i1} %final0, i1 %res.1, 1 256 ret {i64, i1} %final1 257 } 258 259 define i32 @test9(i32 %x, i32 %y) nounwind readnone { 260 ; X32-LABEL: test9: 261 ; X32: # %bb.0: # %entry 262 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 263 ; X32-NEXT: xorl %ecx, %ecx 264 ; X32-NEXT: cmpl $10, {{[0-9]+}}(%esp) 265 ; X32-NEXT: sete %cl 266 ; X32-NEXT: subl %ecx, %eax 267 ; X32-NEXT: retl 268 ; 269 ; X64-LINUX-LABEL: test9: 270 ; X64-LINUX: # %bb.0: # %entry 271 ; X64-LINUX-NEXT: xorl %eax, %eax 272 ; X64-LINUX-NEXT: cmpl $10, %edi 273 ; X64-LINUX-NEXT: sete %al 274 ; X64-LINUX-NEXT: subl %eax, %esi 275 ; X64-LINUX-NEXT: movl %esi, %eax 276 ; X64-LINUX-NEXT: retq 277 ; 278 ; X64-WIN32-LABEL: test9: 279 ; X64-WIN32: # %bb.0: # %entry 280 ; X64-WIN32-NEXT: xorl %eax, %eax 281 ; X64-WIN32-NEXT: cmpl $10, %ecx 282 ; X64-WIN32-NEXT: sete %al 283 ; X64-WIN32-NEXT: subl %eax, %edx 284 ; X64-WIN32-NEXT: movl %edx, %eax 285 ; X64-WIN32-NEXT: retq 286 entry: 287 %cmp = icmp eq i32 %x, 10 288 %sub = sext i1 %cmp to i32 289 %cond = add i32 %sub, %y 290 ret i32 %cond 291 } 292 293 define i1 @test10(i32 %x) nounwind { 294 ; X32-LABEL: test10: 295 ; X32: # %bb.0: # %entry 296 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 297 ; X32-NEXT: incl %eax 298 ; X32-NEXT: seto %al 299 ; X32-NEXT: retl 300 ; 301 ; X64-LINUX-LABEL: test10: 302 ; X64-LINUX: # %bb.0: # %entry 303 ; X64-LINUX-NEXT: incl %edi 304 ; X64-LINUX-NEXT: seto %al 305 ; X64-LINUX-NEXT: retq 306 ; 307 ; X64-WIN32-LABEL: test10: 308 ; X64-WIN32: # %bb.0: # %entry 309 ; X64-WIN32-NEXT: incl %ecx 310 ; X64-WIN32-NEXT: seto %al 311 ; X64-WIN32-NEXT: retq 312 entry: 313 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %x, i32 1) 314 %obit = extractvalue {i32, i1} %t, 1 315 ret i1 %obit 316 } 317 318 define void @test11(i32* inreg %a) nounwind { 319 ; X32-LABEL: test11: 320 ; X32: # %bb.0: # %entry 321 ; X32-NEXT: subl $-128, (%eax) 322 ; X32-NEXT: retl 323 ; 324 ; X64-LINUX-LABEL: test11: 325 ; X64-LINUX: # %bb.0: # %entry 326 ; X64-LINUX-NEXT: subl $-128, (%rdi) 327 ; X64-LINUX-NEXT: retq 328 ; 329 ; X64-WIN32-LABEL: test11: 330 ; X64-WIN32: # %bb.0: # %entry 331 ; X64-WIN32-NEXT: subl $-128, (%rcx) 332 ; X64-WIN32-NEXT: retq 333 entry: 334 %aa = load i32, i32* %a 335 %b = add i32 %aa, 128 336 store i32 %b, i32* %a 337 ret void 338 } 339 340 define void @test12(i64* inreg %a) nounwind { 341 ; X32-LABEL: test12: 342 ; X32: # %bb.0: # %entry 343 ; X32-NEXT: addl $-2147483648, (%eax) # imm = 0x80000000 344 ; X32-NEXT: adcl $0, 4(%eax) 345 ; X32-NEXT: retl 346 ; 347 ; X64-LINUX-LABEL: test12: 348 ; X64-LINUX: # %bb.0: # %entry 349 ; X64-LINUX-NEXT: subq $-2147483648, (%rdi) # imm = 0x80000000 350 ; X64-LINUX-NEXT: retq 351 ; 352 ; X64-WIN32-LABEL: test12: 353 ; X64-WIN32: # %bb.0: # %entry 354 ; X64-WIN32-NEXT: subq $-2147483648, (%rcx) # imm = 0x80000000 355 ; X64-WIN32-NEXT: retq 356 entry: 357 %aa = load i64, i64* %a 358 %b = add i64 %aa, 2147483648 359 store i64 %b, i64* %a 360 ret void 361 } 362 363 define void @test13(i64* inreg %a) nounwind { 364 ; X32-LABEL: test13: 365 ; X32: # %bb.0: # %entry 366 ; X32-NEXT: addl $128, (%eax) 367 ; X32-NEXT: adcl $0, 4(%eax) 368 ; X32-NEXT: retl 369 ; 370 ; X64-LINUX-LABEL: test13: 371 ; X64-LINUX: # %bb.0: # %entry 372 ; X64-LINUX-NEXT: subq $-128, (%rdi) 373 ; X64-LINUX-NEXT: retq 374 ; 375 ; X64-WIN32-LABEL: test13: 376 ; X64-WIN32: # %bb.0: # %entry 377 ; X64-WIN32-NEXT: subq $-128, (%rcx) 378 ; X64-WIN32-NEXT: retq 379 entry: 380 %aa = load i64, i64* %a 381 %b = add i64 %aa, 128 382 store i64 %b, i64* %a 383 ret void 384 } 385 386 define i32 @inc_not(i32 %a) { 387 ; X32-LABEL: inc_not: 388 ; X32: # %bb.0: 389 ; X32-NEXT: xorl %eax, %eax 390 ; X32-NEXT: subl {{[0-9]+}}(%esp), %eax 391 ; X32-NEXT: retl 392 ; 393 ; X64-LINUX-LABEL: inc_not: 394 ; X64-LINUX: # %bb.0: 395 ; X64-LINUX-NEXT: negl %edi 396 ; X64-LINUX-NEXT: movl %edi, %eax 397 ; X64-LINUX-NEXT: retq 398 ; 399 ; X64-WIN32-LABEL: inc_not: 400 ; X64-WIN32: # %bb.0: 401 ; X64-WIN32-NEXT: negl %ecx 402 ; X64-WIN32-NEXT: movl %ecx, %eax 403 ; X64-WIN32-NEXT: retq 404 %nota = xor i32 %a, -1 405 %r = add i32 %nota, 1 406 ret i32 %r 407 } 408 409 define void @uaddo1_not(i32 %a, i32* %p0, i1* %p1) { 410 ; X32-LABEL: uaddo1_not: 411 ; X32: # %bb.0: 412 ; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 413 ; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 414 ; X32-NEXT: xorl %edx, %edx 415 ; X32-NEXT: subl {{[0-9]+}}(%esp), %edx 416 ; X32-NEXT: movl %edx, (%ecx) 417 ; X32-NEXT: setae (%eax) 418 ; X32-NEXT: retl 419 ; 420 ; X64-LINUX-LABEL: uaddo1_not: 421 ; X64-LINUX: # %bb.0: 422 ; X64-LINUX-NEXT: negl %edi 423 ; X64-LINUX-NEXT: movl %edi, (%rsi) 424 ; X64-LINUX-NEXT: setae (%rdx) 425 ; X64-LINUX-NEXT: retq 426 ; 427 ; X64-WIN32-LABEL: uaddo1_not: 428 ; X64-WIN32: # %bb.0: 429 ; X64-WIN32-NEXT: negl %ecx 430 ; X64-WIN32-NEXT: movl %ecx, (%rdx) 431 ; X64-WIN32-NEXT: setae (%r8) 432 ; X64-WIN32-NEXT: retq 433 %nota = xor i32 %a, -1 434 %uaddo = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %nota, i32 1) 435 %r0 = extractvalue {i32, i1} %uaddo, 0 436 %r1 = extractvalue {i32, i1} %uaddo, 1 437 store i32 %r0, i32* %p0 438 store i1 %r1, i1* %p1 439 ret void 440 } 441