326 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s3 4; PR317545;6; #include <x86intrin.h>7; using u64 = unsigned long long;8;9; template<u64 K>10; void test(u64& alo, u64& ahi)11; {12; u64 blo = K;13; u64 bhi = 0;14; bool cf = (alo += blo) < blo;15; _addcarry_u64(cf, ahi, bhi, &ahi);16; }17;18; template void test<0ull>(u64&, u64&);19; template void test<1ull>(u64&, u64&);20; template void test<2ull>(u64&, u64&);21; template void test<3ull>(u64&, u64&);22; template void test<4ull>(u64&, u64&);23; template void test<0x7fffffffffffffffull>(u64&, u64&);24; template void test<0x8000000000000000ull>(u64&, u64&);25; template void test<0x8000000000000001ull>(u64&, u64&);26; template void test<0xffffffff80000000ull>(u64&, u64&);27; template void test<0xfffffffffffffffdull>(u64&, u64&);28; template void test<0xfffffffffffffffeull>(u64&, u64&);29; template void test<0xffffffffffffffffull>(u64&, u64&);30 31define void @test_0(ptr, ptr) {32; CHECK-LABEL: test_0:33; CHECK: # %bb.0:34; CHECK-NEXT: retq35 %3 = load i64, ptr %1, align 836 %4 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 0, i64 %3, i64 0)37 %5 = extractvalue { i8, i64 } %4, 138 store i64 %5, ptr %1, align 839 ret void40}41 42define void @test_1(ptr, ptr) {43; CHECK-LABEL: test_1:44; CHECK: # %bb.0:45; CHECK-NEXT: addq $1, (%rdi)46; CHECK-NEXT: adcq $0, (%rsi)47; CHECK-NEXT: retq48 %3 = load i64, ptr %0, align 849 %4 = add i64 %3, 150 store i64 %4, ptr %0, align 851 %5 = icmp eq i64 %4, 052 %6 = zext i1 %5 to i853 %7 = load i64, ptr %1, align 854 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)55 %9 = extractvalue { i8, i64 } %8, 156 store i64 %9, ptr %1, align 857 ret void58}59 60define void @test_2(ptr, ptr) {61; CHECK-LABEL: test_2:62; CHECK: # %bb.0:63; CHECK-NEXT: addq $2, (%rdi)64; CHECK-NEXT: adcq $0, (%rsi)65; CHECK-NEXT: retq66 %3 = load i64, ptr %0, align 867 %4 = add i64 %3, 268 store i64 %4, ptr %0, align 869 %5 = icmp ult i64 %4, 270 %6 = zext i1 %5 to i871 %7 = load i64, ptr %1, align 872 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)73 %9 = extractvalue { i8, i64 } %8, 174 store i64 %9, ptr %1, align 875 ret void76}77 78define void @test_3(ptr, ptr) {79; CHECK-LABEL: test_3:80; CHECK: # %bb.0:81; CHECK-NEXT: addq $3, (%rdi)82; CHECK-NEXT: adcq $0, (%rsi)83; CHECK-NEXT: retq84 %3 = load i64, ptr %0, align 885 %4 = add i64 %3, 386 store i64 %4, ptr %0, align 887 %5 = icmp ult i64 %4, 388 %6 = zext i1 %5 to i889 %7 = load i64, ptr %1, align 890 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)91 %9 = extractvalue { i8, i64 } %8, 192 store i64 %9, ptr %1, align 893 ret void94}95 96define void @test_4(ptr, ptr) {97; CHECK-LABEL: test_4:98; CHECK: # %bb.0:99; CHECK-NEXT: addq $4, (%rdi)100; CHECK-NEXT: adcq $0, (%rsi)101; CHECK-NEXT: retq102 %3 = load i64, ptr %0, align 8103 %4 = add i64 %3, 4104 store i64 %4, ptr %0, align 8105 %5 = icmp ult i64 %4, 4106 %6 = zext i1 %5 to i8107 %7 = load i64, ptr %1, align 8108 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)109 %9 = extractvalue { i8, i64 } %8, 1110 store i64 %9, ptr %1, align 8111 ret void112}113 114define void @test_9223372036854775807(ptr, ptr) {115; CHECK-LABEL: test_9223372036854775807:116; CHECK: # %bb.0:117; CHECK-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF118; CHECK-NEXT: addq %rax, (%rdi)119; CHECK-NEXT: adcq $0, (%rsi)120; CHECK-NEXT: retq121 %3 = load i64, ptr %0, align 8122 %4 = add i64 %3, 9223372036854775807123 store i64 %4, ptr %0, align 8124 %5 = icmp ult i64 %4, 9223372036854775807125 %6 = zext i1 %5 to i8126 %7 = load i64, ptr %1, align 8127 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)128 %9 = extractvalue { i8, i64 } %8, 1129 store i64 %9, ptr %1, align 8130 ret void131}132 133define void @test_9223372036854775808(ptr, ptr) {134; CHECK-LABEL: test_9223372036854775808:135; CHECK: # %bb.0:136; CHECK-NEXT: movq (%rdi), %rax137; CHECK-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000138; CHECK-NEXT: xorq %rax, %rcx139; CHECK-NEXT: movq %rcx, (%rdi)140; CHECK-NEXT: shrq $63, %rax141; CHECK-NEXT: addb $-1, %al142; CHECK-NEXT: adcq $0, (%rsi)143; CHECK-NEXT: retq144 %3 = load i64, ptr %0, align 8145 %4 = xor i64 %3, -9223372036854775808146 store i64 %4, ptr %0, align 8147 %5 = lshr i64 %3, 63148 %6 = trunc i64 %5 to i8149 %7 = load i64, ptr %1, align 8150 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)151 %9 = extractvalue { i8, i64 } %8, 1152 store i64 %9, ptr %1, align 8153 ret void154}155 156define void @test_9223372036854775809(ptr, ptr) {157; CHECK-LABEL: test_9223372036854775809:158; CHECK: # %bb.0:159; CHECK-NEXT: movabsq $-9223372036854775807, %rax # imm = 0x8000000000000001160; CHECK-NEXT: addq %rax, (%rdi)161; CHECK-NEXT: adcq $0, (%rsi)162; CHECK-NEXT: retq163 %3 = load i64, ptr %0, align 8164 %4 = add i64 %3, -9223372036854775807165 store i64 %4, ptr %0, align 8166 %5 = icmp ult i64 %4, -9223372036854775807167 %6 = zext i1 %5 to i8168 %7 = load i64, ptr %1, align 8169 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)170 %9 = extractvalue { i8, i64 } %8, 1171 store i64 %9, ptr %1, align 8172 ret void173}174 175define void @test_18446744071562067968(ptr, ptr) {176; CHECK-LABEL: test_18446744071562067968:177; CHECK: # %bb.0:178; CHECK-NEXT: addq $-2147483648, (%rdi) # imm = 0x80000000179; CHECK-NEXT: adcq $0, (%rsi)180; CHECK-NEXT: retq181 %3 = load i64, ptr %0, align 8182 %4 = add i64 %3, -2147483648183 store i64 %4, ptr %0, align 8184 %5 = icmp ult i64 %4, -2147483648185 %6 = zext i1 %5 to i8186 %7 = load i64, ptr %1, align 8187 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)188 %9 = extractvalue { i8, i64 } %8, 1189 store i64 %9, ptr %1, align 8190 ret void191}192 193define void @test_18446744073709551613(ptr, ptr) {194; CHECK-LABEL: test_18446744073709551613:195; CHECK: # %bb.0:196; CHECK-NEXT: addq $-3, (%rdi)197; CHECK-NEXT: adcq $0, (%rsi)198; CHECK-NEXT: retq199 %3 = load i64, ptr %0, align 8200 %4 = add i64 %3, -3201 store i64 %4, ptr %0, align 8202 %5 = icmp ult i64 %4, -3203 %6 = zext i1 %5 to i8204 %7 = load i64, ptr %1, align 8205 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)206 %9 = extractvalue { i8, i64 } %8, 1207 store i64 %9, ptr %1, align 8208 ret void209}210 211define void @test_18446744073709551614(ptr, ptr) {212; CHECK-LABEL: test_18446744073709551614:213; CHECK: # %bb.0:214; CHECK-NEXT: addq $-2, (%rdi)215; CHECK-NEXT: adcq $0, (%rsi)216; CHECK-NEXT: retq217 %3 = load i64, ptr %0, align 8218 %4 = add i64 %3, -2219 store i64 %4, ptr %0, align 8220 %5 = icmp ult i64 %4, -2221 %6 = zext i1 %5 to i8222 %7 = load i64, ptr %1, align 8223 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)224 %9 = extractvalue { i8, i64 } %8, 1225 store i64 %9, ptr %1, align 8226 ret void227}228 229define void @test_18446744073709551615(ptr, ptr) {230; CHECK-LABEL: test_18446744073709551615:231; CHECK: # %bb.0:232; CHECK-NEXT: addq $-1, (%rdi)233; CHECK-NEXT: adcq $0, (%rsi)234; CHECK-NEXT: retq235 %3 = load i64, ptr %0, align 8236 %4 = add i64 %3, -1237 store i64 %4, ptr %0, align 8238 %5 = icmp ne i64 %3, 0239 %6 = zext i1 %5 to i8240 %7 = load i64, ptr %1, align 8241 %8 = tail call { i8, i64 } @llvm.x86.addcarry.64(i8 %6, i64 %7, i64 0)242 %9 = extractvalue { i8, i64 } %8, 1243 store i64 %9, ptr %1, align 8244 ret void245}246 247define i1 @illegal_type(i17 %x, ptr %p) {248; CHECK-LABEL: illegal_type:249; CHECK: # %bb.0:250; CHECK-NEXT: addl $29, %edi251; CHECK-NEXT: movw %di, (%rsi)252; CHECK-NEXT: andl $131071, %edi # imm = 0x1FFFF253; CHECK-NEXT: movl %edi, %eax254; CHECK-NEXT: shrl $16, %eax255; CHECK-NEXT: movb %al, 2(%rsi)256; CHECK-NEXT: cmpl $29, %edi257; CHECK-NEXT: setb %al258; CHECK-NEXT: retq259 %a = add i17 %x, 29260 store i17 %a, ptr %p261 %ov = icmp ult i17 %a, 29262 ret i1 %ov263}264 265; The overflow check may be against the input rather than the sum.266 267define i1 @uaddo_i64_increment_alt(i64 %x, ptr %p) {268; CHECK-LABEL: uaddo_i64_increment_alt:269; CHECK: # %bb.0:270; CHECK-NEXT: incq %rdi271; CHECK-NEXT: sete %al272; CHECK-NEXT: movq %rdi, (%rsi)273; CHECK-NEXT: retq274 %a = add i64 %x, 1275 store i64 %a, ptr %p276 %ov = icmp eq i64 %x, -1277 ret i1 %ov278}279 280; Make sure insertion is done correctly based on dominance.281 282define i1 @uaddo_i64_increment_alt_dom(i64 %x, ptr %p) {283; CHECK-LABEL: uaddo_i64_increment_alt_dom:284; CHECK: # %bb.0:285; CHECK-NEXT: incq %rdi286; CHECK-NEXT: sete %al287; CHECK-NEXT: movq %rdi, (%rsi)288; CHECK-NEXT: retq289 %ov = icmp eq i64 %x, -1290 %a = add i64 %x, 1291 store i64 %a, ptr %p292 ret i1 %ov293}294 295; The overflow check may be against the input rather than the sum.296 297define i1 @uaddo_i64_decrement_alt(i64 %x, ptr %p) {298; CHECK-LABEL: uaddo_i64_decrement_alt:299; CHECK: # %bb.0:300; CHECK-NEXT: addq $-1, %rdi301; CHECK-NEXT: setb %al302; CHECK-NEXT: movq %rdi, (%rsi)303; CHECK-NEXT: retq304 %a = add i64 %x, -1305 store i64 %a, ptr %p306 %ov = icmp ne i64 %x, 0307 ret i1 %ov308}309 310; Make sure insertion is done correctly based on dominance.311 312define i1 @uaddo_i64_decrement_alt_dom(i64 %x, ptr %p) {313; CHECK-LABEL: uaddo_i64_decrement_alt_dom:314; CHECK: # %bb.0:315; CHECK-NEXT: addq $-1, %rdi316; CHECK-NEXT: setb %al317; CHECK-NEXT: movq %rdi, (%rsi)318; CHECK-NEXT: retq319 %ov = icmp ne i64 %x, 0320 %a = add i64 %x, -1321 store i64 %a, ptr %p322 ret i1 %ov323}324 325declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64)326