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 6declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) 7declare {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. 11define 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 28entry: 29 %b = add i32 %a, 128 30 ret i32 %b 31} 32define 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 50entry: 51 %b = add i64 %a, 2147483648 52 ret i64 %b 53} 54define 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 72entry: 73 %b = add i64 %a, 128 74 ret i64 %b 75} 76 77define 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 109entry: 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 115normal: 116 store i32 0, i32* %X 117 br label %overflow 118 119overflow: 120 ret i1 false 121} 122 123define 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 155entry: 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 161normal: 162 store i32 0, i32* %X 163 br label %carry 164 165carry: 166 ret i1 false 167} 168 169define 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 190entry: 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 197define {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 218entry: 219 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 220 ret {i32, i1} %t 221} 222 223; PR5443 224define {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 247entry: 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 259define 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 286entry: 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 293define 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 312entry: 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 318define 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 333entry: 334 %aa = load i32, i32* %a 335 %b = add i32 %aa, 128 336 store i32 %b, i32* %a 337 ret void 338} 339 340define 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 356entry: 357 %aa = load i64, i64* %a 358 %b = add i64 %aa, 2147483648 359 store i64 %b, i64* %a 360 ret void 361} 362 363define 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 379entry: 380 %aa = load i64, i64* %a 381 %b = add i64 %aa, 128 382 store i64 %b, i64* %a 383 ret void 384} 385 386define 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 409define 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