1545 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s3 4declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64)5declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) #16declare { i64, i1 } @llvm.usub.with.overflow.i64(i64, i64) #17declare { i128, i1 } @llvm.sadd.with.overflow.i128(i128, i128)8 9define i128 @add128(i128 %a, i128 %b) nounwind {10; CHECK-LABEL: add128:11; CHECK: # %bb.0: # %entry12; CHECK-NEXT: movq %rdi, %rax13; CHECK-NEXT: addq %rdx, %rax14; CHECK-NEXT: adcq %rcx, %rsi15; CHECK-NEXT: movq %rsi, %rdx16; CHECK-NEXT: retq17entry:18 %0 = add i128 %a, %b19 ret i128 %020}21 22define void @add128_rmw(ptr %a, i128 %b) nounwind {23; CHECK-LABEL: add128_rmw:24; CHECK: # %bb.0: # %entry25; CHECK-NEXT: addq %rsi, (%rdi)26; CHECK-NEXT: adcq %rdx, 8(%rdi)27; CHECK-NEXT: retq28entry:29 %0 = load i128, ptr %a30 %1 = add i128 %0, %b31 store i128 %1, ptr %a32 ret void33}34 35define void @add128_rmw2(i128 %a, ptr %b) nounwind {36; CHECK-LABEL: add128_rmw2:37; CHECK: # %bb.0: # %entry38; CHECK-NEXT: addq %rdi, (%rdx)39; CHECK-NEXT: adcq %rsi, 8(%rdx)40; CHECK-NEXT: retq41entry:42 %0 = load i128, ptr %b43 %1 = add i128 %a, %044 store i128 %1, ptr %b45 ret void46}47 48define i256 @add256(i256 %a, i256 %b) nounwind {49; CHECK-LABEL: add256:50; CHECK: # %bb.0: # %entry51; CHECK-NEXT: movq %rdi, %rax52; CHECK-NEXT: addq %r9, %rsi53; CHECK-NEXT: adcq {{[0-9]+}}(%rsp), %rdx54; CHECK-NEXT: adcq {{[0-9]+}}(%rsp), %rcx55; CHECK-NEXT: adcq {{[0-9]+}}(%rsp), %r856; CHECK-NEXT: movq %rcx, 16(%rdi)57; CHECK-NEXT: movq %rdx, 8(%rdi)58; CHECK-NEXT: movq %rsi, (%rdi)59; CHECK-NEXT: movq %r8, 24(%rdi)60; CHECK-NEXT: retq61entry:62 %0 = add i256 %a, %b63 ret i256 %064}65 66define void @add256_rmw(ptr %a, i256 %b) nounwind {67; CHECK-LABEL: add256_rmw:68; CHECK: # %bb.0: # %entry69; CHECK-NEXT: addq %rsi, (%rdi)70; CHECK-NEXT: adcq %rdx, 8(%rdi)71; CHECK-NEXT: adcq %rcx, 16(%rdi)72; CHECK-NEXT: adcq %r8, 24(%rdi)73; CHECK-NEXT: retq74entry:75 %0 = load i256, ptr %a76 %1 = add i256 %0, %b77 store i256 %1, ptr %a78 ret void79}80 81define void @add256_rmw2(i256 %a, ptr %b) nounwind {82; CHECK-LABEL: add256_rmw2:83; CHECK: # %bb.0: # %entry84; CHECK-NEXT: addq %rdi, (%r8)85; CHECK-NEXT: adcq %rsi, 8(%r8)86; CHECK-NEXT: adcq %rdx, 16(%r8)87; CHECK-NEXT: adcq %rcx, 24(%r8)88; CHECK-NEXT: retq89entry:90 %0 = load i256, ptr %b91 %1 = add i256 %a, %092 store i256 %1, ptr %b93 ret void94}95 96define void @a(ptr nocapture %s, ptr nocapture %t, i64 %a, i64 %b, i64 %c) nounwind {97; CHECK-LABEL: a:98; CHECK: # %bb.0: # %entry99; CHECK-NEXT: addq %rcx, %rdx100; CHECK-NEXT: adcq $0, %r8101; CHECK-NEXT: movq %r8, (%rdi)102; CHECK-NEXT: movq %rdx, (%rsi)103; CHECK-NEXT: retq104entry:105 %0 = zext i64 %a to i128106 %1 = zext i64 %b to i128107 %2 = add i128 %1, %0108 %3 = zext i64 %c to i128109 %4 = shl i128 %3, 64110 %5 = add i128 %4, %2111 %6 = lshr i128 %5, 64112 %7 = trunc i128 %6 to i64113 store i64 %7, ptr %s, align 8114 %8 = trunc i128 %2 to i64115 store i64 %8, ptr %t, align 8116 ret void117}118 119define void @b(ptr nocapture %r, i64 %a, i64 %b, i32 %c) nounwind {120; CHECK-LABEL: b:121; CHECK: # %bb.0: # %entry122; CHECK-NEXT: addq %rdx, %rsi123; CHECK-NEXT: adcl $0, %ecx124; CHECK-NEXT: movl %ecx, (%rdi)125; CHECK-NEXT: retq126entry:127 %0 = zext i64 %a to i128128 %1 = zext i64 %b to i128129 %2 = zext i32 %c to i128130 %3 = add i128 %1, %0131 %4 = lshr i128 %3, 64132 %5 = add i128 %4, %2133 %6 = trunc i128 %5 to i32134 store i32 %6, ptr %r, align 4135 ret void136}137 138define void @c(ptr nocapture %r, i64 %a, i64 %b, i16 %c) nounwind {139; CHECK-LABEL: c:140; CHECK: # %bb.0: # %entry141; CHECK-NEXT: addq %rdx, %rsi142; CHECK-NEXT: adcw $0, %cx143; CHECK-NEXT: movw %cx, (%rdi)144; CHECK-NEXT: retq145entry:146 %0 = zext i64 %a to i128147 %1 = zext i64 %b to i128148 %2 = zext i16 %c to i128149 %3 = add i128 %1, %0150 %4 = lshr i128 %3, 64151 %5 = add i128 %4, %2152 %6 = trunc i128 %5 to i16153 store i16 %6, ptr %r, align 4154 ret void155}156 157define void @d(ptr nocapture %r, i64 %a, i64 %b, i8 %c) nounwind {158; CHECK-LABEL: d:159; CHECK: # %bb.0: # %entry160; CHECK-NEXT: addq %rdx, %rsi161; CHECK-NEXT: adcb $0, %cl162; CHECK-NEXT: movb %cl, (%rdi)163; CHECK-NEXT: retq164entry:165 %0 = zext i64 %a to i128166 %1 = zext i64 %b to i128167 %2 = zext i8 %c to i128168 %3 = add i128 %1, %0169 %4 = lshr i128 %3, 64170 %5 = add i128 %4, %2171 %6 = trunc i128 %5 to i8172 store i8 %6, ptr %r, align 4173 ret void174}175 176define i8 @e(ptr nocapture %a, i32 %b) nounwind {177; CHECK-LABEL: e:178; CHECK: # %bb.0:179; CHECK-NEXT: # kill: def $esi killed $esi def $rsi180; CHECK-NEXT: movl (%rdi), %ecx181; CHECK-NEXT: leal (%rsi,%rcx), %edx182; CHECK-NEXT: addl %esi, %edx183; CHECK-NEXT: setb %al184; CHECK-NEXT: addl %ecx, %esi185; CHECK-NEXT: movl %edx, (%rdi)186; CHECK-NEXT: adcb $0, %al187; CHECK-NEXT: retq188 %1 = load i32, ptr %a, align 4189 %2 = add i32 %1, %b190 %3 = icmp ult i32 %2, %b191 %4 = zext i1 %3 to i8192 %5 = add i32 %2, %b193 store i32 %5, ptr %a, align 4194 %6 = icmp ult i32 %5, %b195 %7 = zext i1 %6 to i8196 %8 = add nuw nsw i8 %7, %4197 ret i8 %8198}199 200%scalar = type { [4 x i64] }201 202define %scalar @pr31719(ptr nocapture readonly %this, %scalar %arg.b) nounwind {203; CHECK-LABEL: pr31719:204; CHECK: # %bb.0: # %entry205; CHECK-NEXT: movq %rdi, %rax206; CHECK-NEXT: addq (%rsi), %rdx207; CHECK-NEXT: adcq 8(%rsi), %rcx208; CHECK-NEXT: adcq 16(%rsi), %r8209; CHECK-NEXT: adcq 24(%rsi), %r9210; CHECK-NEXT: movq %rdx, (%rdi)211; CHECK-NEXT: movq %rcx, 8(%rdi)212; CHECK-NEXT: movq %r8, 16(%rdi)213; CHECK-NEXT: movq %r9, 24(%rdi)214; CHECK-NEXT: retq215entry:216 %0 = extractvalue %scalar %arg.b, 0217 %.elt = extractvalue [4 x i64] %0, 0218 %.elt24 = extractvalue [4 x i64] %0, 1219 %.elt26 = extractvalue [4 x i64] %0, 2220 %.elt28 = extractvalue [4 x i64] %0, 3221 %1 = load i64, ptr %this, align 8222 %2 = zext i64 %1 to i128223 %3 = zext i64 %.elt to i128224 %4 = add nuw nsw i128 %2, %3225 %5 = trunc i128 %4 to i64226 %6 = lshr i128 %4, 64227 %7 = getelementptr inbounds %scalar , ptr %this, i64 0, i32 0, i64 1228 %8 = load i64, ptr %7, align 8229 %9 = zext i64 %8 to i128230 %10 = zext i64 %.elt24 to i128231 %11 = add nuw nsw i128 %9, %10232 %12 = add nuw nsw i128 %11, %6233 %13 = trunc i128 %12 to i64234 %14 = lshr i128 %12, 64235 %15 = getelementptr inbounds %scalar , ptr %this, i64 0, i32 0, i64 2236 %16 = load i64, ptr %15, align 8237 %17 = zext i64 %16 to i128238 %18 = zext i64 %.elt26 to i128239 %19 = add nuw nsw i128 %17, %18240 %20 = add nuw nsw i128 %19, %14241 %21 = trunc i128 %20 to i64242 %22 = lshr i128 %20, 64243 %23 = getelementptr inbounds %scalar , ptr %this, i64 0, i32 0, i64 3244 %24 = load i64, ptr %23, align 8245 %25 = zext i64 %24 to i128246 %26 = zext i64 %.elt28 to i128247 %27 = add nuw nsw i128 %25, %26248 %28 = add nuw nsw i128 %27, %22249 %29 = trunc i128 %28 to i64250 %30 = insertvalue [4 x i64] undef, i64 %5, 0251 %31 = insertvalue [4 x i64] %30, i64 %13, 1252 %32 = insertvalue [4 x i64] %31, i64 %21, 2253 %33 = insertvalue [4 x i64] %32, i64 %29, 3254 %34 = insertvalue %scalar undef, [4 x i64] %33, 0255 ret %scalar %34256}257 258%accumulator= type { i64, i64, i32 }259 260define void @muladd(ptr nocapture %this, i64 %arg.a, i64 %arg.b) nounwind {261; CHECK-LABEL: muladd:262; CHECK: # %bb.0: # %entry263; CHECK-NEXT: movq %rdx, %rax264; CHECK-NEXT: mulq %rsi265; CHECK-NEXT: addq %rax, (%rdi)266; CHECK-NEXT: adcq %rdx, 8(%rdi)267; CHECK-NEXT: adcl $0, 16(%rdi)268; CHECK-NEXT: retq269entry:270 %0 = zext i64 %arg.a to i128271 %1 = zext i64 %arg.b to i128272 %2 = mul nuw i128 %1, %0273 %3 = load i64, ptr %this, align 8274 %4 = zext i64 %3 to i128275 %5 = add i128 %4, %2276 %6 = trunc i128 %5 to i64277 store i64 %6, ptr %this, align 8278 %7 = lshr i128 %5, 64279 %8 = getelementptr inbounds %accumulator, ptr %this, i64 0, i32 1280 %9 = load i64, ptr %8, align 8281 %10 = zext i64 %9 to i128282 %11 = add nuw nsw i128 %7, %10283 %12 = trunc i128 %11 to i64284 store i64 %12, ptr %8, align 8285 %13 = lshr i128 %11, 64286 %14 = getelementptr inbounds %accumulator, ptr %this, i64 0, i32 2287 %15 = load i32, ptr %14, align 4288 %16 = zext i32 %15 to i128289 %17 = add nuw nsw i128 %13, %16290 %18 = trunc i128 %17 to i32291 store i32 %18, ptr %14, align 4292 ret void293}294 295define i64 @shiftadd(i64 %a, i64 %b, i64 %c, i64 %d) nounwind {296; CHECK-LABEL: shiftadd:297; CHECK: # %bb.0: # %entry298; CHECK-NEXT: movq %rdx, %rax299; CHECK-NEXT: addq %rsi, %rdi300; CHECK-NEXT: adcq %rcx, %rax301; CHECK-NEXT: retq302entry:303 %0 = zext i64 %a to i128304 %1 = zext i64 %b to i128305 %2 = add i128 %0, %1306 %3 = lshr i128 %2, 64307 %4 = trunc i128 %3 to i64308 %5 = add i64 %c, %d309 %6 = add i64 %4, %5310 ret i64 %6311}312 313%S = type { [4 x i64] }314 315define %S @readd(ptr nocapture readonly %this, %S %arg.b) nounwind {316; CHECK-LABEL: readd:317; CHECK: # %bb.0: # %entry318; CHECK-NEXT: movq %rdi, %rax319; CHECK-NEXT: addq (%rsi), %rdx320; CHECK-NEXT: movq 8(%rsi), %rdi321; CHECK-NEXT: adcq $0, %rdi322; CHECK-NEXT: setb %r10b323; CHECK-NEXT: movzbl %r10b, %r10d324; CHECK-NEXT: addq %rcx, %rdi325; CHECK-NEXT: adcq 16(%rsi), %r10326; CHECK-NEXT: setb %cl327; CHECK-NEXT: movzbl %cl, %ecx328; CHECK-NEXT: addq %r8, %r10329; CHECK-NEXT: adcq 24(%rsi), %rcx330; CHECK-NEXT: addq %r9, %rcx331; CHECK-NEXT: movq %rdx, (%rax)332; CHECK-NEXT: movq %rdi, 8(%rax)333; CHECK-NEXT: movq %r10, 16(%rax)334; CHECK-NEXT: movq %rcx, 24(%rax)335; CHECK-NEXT: retq336entry:337 %0 = extractvalue %S %arg.b, 0338 %.elt6 = extractvalue [4 x i64] %0, 1339 %.elt8 = extractvalue [4 x i64] %0, 2340 %.elt10 = extractvalue [4 x i64] %0, 3341 %.elt = extractvalue [4 x i64] %0, 0342 %1 = load i64, ptr %this, align 8343 %2 = zext i64 %1 to i128344 %3 = zext i64 %.elt to i128345 %4 = add nuw nsw i128 %2, %3346 %5 = trunc i128 %4 to i64347 %6 = lshr i128 %4, 64348 %7 = getelementptr inbounds %S, ptr %this, i64 0, i32 0, i64 1349 %8 = load i64, ptr %7, align 8350 %9 = zext i64 %8 to i128351 %10 = add nuw nsw i128 %6, %9352 %11 = zext i64 %.elt6 to i128353 %12 = add nuw nsw i128 %10, %11354 %13 = trunc i128 %12 to i64355 %14 = lshr i128 %12, 64356 %15 = getelementptr inbounds %S, ptr %this, i64 0, i32 0, i64 2357 %16 = load i64, ptr %15, align 8358 %17 = zext i64 %16 to i128359 %18 = add nuw nsw i128 %14, %17360 %19 = zext i64 %.elt8 to i128361 %20 = add nuw nsw i128 %18, %19362 %21 = lshr i128 %20, 64363 %22 = trunc i128 %20 to i64364 %23 = getelementptr inbounds %S, ptr %this, i64 0,i32 0, i64 3365 %24 = load i64, ptr %23, align 8366 %25 = zext i64 %24 to i128367 %26 = add nuw nsw i128 %21, %25368 %27 = zext i64 %.elt10 to i128369 %28 = add nuw nsw i128 %26, %27370 %29 = trunc i128 %28 to i64371 %30 = insertvalue [4 x i64] undef, i64 %5, 0372 %31 = insertvalue [4 x i64] %30, i64 %13, 1373 %32 = insertvalue [4 x i64] %31, i64 %22, 2374 %33 = insertvalue [4 x i64] %32, i64 %29, 3375 %34 = insertvalue %S undef, [4 x i64] %33, 0376 ret %S %34377}378 379define i128 @addcarry1_not(i128 %n) nounwind {380; CHECK-LABEL: addcarry1_not:381; CHECK: # %bb.0:382; CHECK-NEXT: movq %rdi, %rax383; CHECK-NEXT: xorl %edx, %edx384; CHECK-NEXT: negq %rax385; CHECK-NEXT: sbbq %rsi, %rdx386; CHECK-NEXT: retq387 %1 = xor i128 %n, -1388 %2 = add i128 %1, 1389 ret i128 %2390}391 392define { i128, i1 } @saddo_not_1(i128 %x) nounwind {393; CHECK-LABEL: saddo_not_1:394; CHECK: # %bb.0:395; CHECK-NEXT: movq %rdi, %rax396; CHECK-NEXT: xorl %edx, %edx397; CHECK-NEXT: negq %rax398; CHECK-NEXT: sbbq %rsi, %rdx399; CHECK-NEXT: seto %cl400; CHECK-NEXT: retq401 %not = xor i128 %x, -1402 %r = call { i128, i1 } @llvm.sadd.with.overflow.i128(i128 %not, i128 1)403 ret { i128, i1 } %r404}405 406define { i128, i1 } @saddo_carry_not_1(i128 %x) nounwind {407; CHECK-LABEL: saddo_carry_not_1:408; CHECK: # %bb.0:409; CHECK-NEXT: movq %rdi, %rax410; CHECK-NEXT: negq %rax411; CHECK-NEXT: movl $1, %edx412; CHECK-NEXT: sbbq %rsi, %rdx413; CHECK-NEXT: seto %cl414; CHECK-NEXT: retq415 %not = xor i128 %x, -1416 %r = call { i128, i1 } @llvm.sadd.with.overflow.i128(i128 %not, i128 u0x10000000000000001)417 ret { i128, i1 } %r418}419 420define i128 @addcarry_to_subcarry(i64 %a, i64 %b) nounwind {421; CHECK-LABEL: addcarry_to_subcarry:422; CHECK: # %bb.0:423; CHECK-NEXT: movq %rdi, %rax424; CHECK-NEXT: cmpq %rsi, %rdi425; CHECK-NEXT: notq %rsi426; CHECK-NEXT: setae %cl427; CHECK-NEXT: addb $-1, %cl428; CHECK-NEXT: adcq $0, %rax429; CHECK-NEXT: setb %cl430; CHECK-NEXT: movzbl %cl, %edx431; CHECK-NEXT: addq %rsi, %rax432; CHECK-NEXT: adcq $0, %rdx433; CHECK-NEXT: retq434 %notb = xor i64 %b, -1435 %notb128 = zext i64 %notb to i128436 %a128 = zext i64 %a to i128437 %sum1 = add i128 %a128, 1438 %sub1 = add i128 %sum1, %notb128439 %hi = lshr i128 %sub1, 64440 %sum2 = add i128 %hi, %a128441 %sub2 = add i128 %sum2, %notb128442 ret i128 %sub2443}444 445; basic test for combineCarryDiamond()446define { i64, i64, i1 } @addcarry_2x64(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {447; CHECK-LABEL: addcarry_2x64:448; CHECK: # %bb.0:449; CHECK-NEXT: movq %rdi, %rax450; CHECK-NEXT: addq %rdx, %rax451; CHECK-NEXT: adcq %rcx, %rsi452; CHECK-NEXT: setb %cl453; CHECK-NEXT: movq %rsi, %rdx454; CHECK-NEXT: retq455 %t0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)456 %s0 = extractvalue { i64, i1 } %t0, 0457 %k0 = extractvalue { i64, i1 } %t0, 1458 459 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)460 %s1 = extractvalue { i64, i1 } %t1, 0461 %k1 = extractvalue { i64, i1 } %t1, 1462 463 %zk0 = zext i1 %k0 to i64464 %t2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %s1, i64 %zk0)465 %s2 = extractvalue { i64, i1 } %t2, 0466 %k2 = extractvalue { i64, i1 } %t2, 1467 %k = or i1 %k1, %k2468 469 %r0 = insertvalue { i64, i64, i1 } poison, i64 %s0, 0470 %r1 = insertvalue { i64, i64, i1 } %r0, i64 %s2, 1471 %r = insertvalue { i64, i64, i1 } %r1, i1 %k, 2472 ret { i64, i64, i1 } %r473}474 475; basic test for combineCarryDiamond() with carries behind zext/and/trunc476define { i64, i64, i1 } @addcarry_hidden_2x64(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {477; CHECK-LABEL: addcarry_hidden_2x64:478; CHECK: # %bb.0:479; CHECK-NEXT: movq %rdi, %rax480; CHECK-NEXT: addq %rdx, %rax481; CHECK-NEXT: adcq %rcx, %rsi482; CHECK-NEXT: setb %cl483; CHECK-NEXT: movq %rsi, %rdx484; CHECK-NEXT: retq485 %t0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)486 %s0 = extractvalue { i64, i1 } %t0, 0487 %k0 = extractvalue { i64, i1 } %t0, 1488 489 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)490 %s1 = extractvalue { i64, i1 } %t1, 0491 %k1 = extractvalue { i64, i1 } %t1, 1492 %k1i8 = zext i1 %k1 to i8493 %k1and = and i8 %k1i8, 1494 %k1hidden = trunc i8 %k1and to i1495 496 %zk0 = zext i1 %k0 to i64497 %t2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %s1, i64 %zk0)498 %s2 = extractvalue { i64, i1 } %t2, 0499 %k2 = extractvalue { i64, i1 } %t2, 1500 501 %k = or i1 %k1hidden, %k2502 503 %r0 = insertvalue { i64, i64, i1 } poison, i64 %s0, 0504 %r1 = insertvalue { i64, i64, i1 } %r0, i64 %s2, 1505 %r = insertvalue { i64, i64, i1 } %r1, i1 %k, 2506 ret { i64, i64, i1 } %r507}508 509; basic test for combineCarryDiamond() with carries behind zext/and/trunc510define { i64, i64, i1 } @addcarry_hidden2_2x64(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {511; CHECK-LABEL: addcarry_hidden2_2x64:512; CHECK: # %bb.0:513; CHECK-NEXT: movq %rdi, %rax514; CHECK-NEXT: addq %rdx, %rax515; CHECK-NEXT: adcq %rcx, %rsi516; CHECK-NEXT: setb %cl517; CHECK-NEXT: movq %rsi, %rdx518; CHECK-NEXT: retq519 %t0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)520 %s0 = extractvalue { i64, i1 } %t0, 0521 %k0 = extractvalue { i64, i1 } %t0, 1522 523 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)524 %s1 = extractvalue { i64, i1 } %t1, 0525 %k1 = extractvalue { i64, i1 } %t1, 1526 527 %zk0 = zext i1 %k0 to i64528 %t2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %s1, i64 %zk0)529 %s2 = extractvalue { i64, i1 } %t2, 0530 %k2 = extractvalue { i64, i1 } %t2, 1531 %k2i8 = zext i1 %k2 to i8532 %k2and = and i8 %k2i8, 1533 %k2hidden = trunc i8 %k2and to i1534 535 %k = or i1 %k1, %k2hidden536 537 %r0 = insertvalue { i64, i64, i1 } poison, i64 %s0, 0538 %r1 = insertvalue { i64, i64, i1 } %r0, i64 %s2, 1539 %r = insertvalue { i64, i64, i1 } %r1, i1 %k, 2540 ret { i64, i64, i1 } %r541}542 543; basic test for combineCarryDiamond() with or operands reversed544define { i64, i64, i1 } @addcarry_2x64_or_reversed(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {545; CHECK-LABEL: addcarry_2x64_or_reversed:546; CHECK: # %bb.0:547; CHECK-NEXT: movq %rdi, %rax548; CHECK-NEXT: addq %rdx, %rax549; CHECK-NEXT: adcq %rcx, %rsi550; CHECK-NEXT: setb %cl551; CHECK-NEXT: movq %rsi, %rdx552; CHECK-NEXT: retq553 %t0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)554 %s0 = extractvalue { i64, i1 } %t0, 0555 %k0 = extractvalue { i64, i1 } %t0, 1556 557 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)558 %s1 = extractvalue { i64, i1 } %t1, 0559 %k1 = extractvalue { i64, i1 } %t1, 1560 561 %zk0 = zext i1 %k0 to i64562 %t2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %zk0, i64 %s1) ; reversed563 %s2 = extractvalue { i64, i1 } %t2, 0564 %k2 = extractvalue { i64, i1 } %t2, 1565 %k = or i1 %k2, %k1 ; reverse natural order of operands566 567 %r0 = insertvalue { i64, i64, i1 } poison, i64 %s0, 0568 %r1 = insertvalue { i64, i64, i1 } %r0, i64 %s2, 1569 %r = insertvalue { i64, i64, i1 } %r1, i1 %k, 2570 ret { i64, i64, i1 } %r571}572 573; basic test for combineCarryDiamond() with xor operands reversed574define { i64, i64, i1 } @addcarry_2x64_xor_reversed(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {575; CHECK-LABEL: addcarry_2x64_xor_reversed:576; CHECK: # %bb.0:577; CHECK-NEXT: movq %rdi, %rax578; CHECK-NEXT: addq %rdx, %rax579; CHECK-NEXT: adcq %rcx, %rsi580; CHECK-NEXT: setb %cl581; CHECK-NEXT: movq %rsi, %rdx582; CHECK-NEXT: retq583 %t0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)584 %s0 = extractvalue { i64, i1 } %t0, 0585 %k0 = extractvalue { i64, i1 } %t0, 1586 587 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)588 %s1 = extractvalue { i64, i1 } %t1, 0589 %k1 = extractvalue { i64, i1 } %t1, 1590 591 %zk0 = zext i1 %k0 to i64592 %t2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %s1, i64 %zk0)593 %s2 = extractvalue { i64, i1 } %t2, 0594 %k2 = extractvalue { i64, i1 } %t2, 1595 %k = xor i1 %k2, %k1 ; reverse natural order of operands596 597 %r0 = insertvalue { i64, i64, i1 } poison, i64 %s0, 0598 %r1 = insertvalue { i64, i64, i1 } %r0, i64 %s2, 1599 %r = insertvalue { i64, i64, i1 } %r1, i1 %k, 2600 ret { i64, i64, i1 } %r601}602 603; basic test for combineCarryDiamond() with and operands reversed604define { i64, i64, i1 } @addcarry_2x64_and_reversed(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {605; CHECK-LABEL: addcarry_2x64_and_reversed:606; CHECK: # %bb.0:607; CHECK-NEXT: movq %rdi, %rax608; CHECK-NEXT: addq %rdx, %rax609; CHECK-NEXT: adcq %rcx, %rsi610; CHECK-NEXT: movq %rsi, %rdx611; CHECK-NEXT: xorl %ecx, %ecx612; CHECK-NEXT: retq613 %t0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)614 %s0 = extractvalue { i64, i1 } %t0, 0615 %k0 = extractvalue { i64, i1 } %t0, 1616 617 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)618 %s1 = extractvalue { i64, i1 } %t1, 0619 %k1 = extractvalue { i64, i1 } %t1, 1620 621 %zk0 = zext i1 %k0 to i64622 %t2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %s1, i64 %zk0)623 %s2 = extractvalue { i64, i1 } %t2, 0624 %k2 = extractvalue { i64, i1 } %t2, 1625 %k = and i1 %k2, %k1 ; reverse natural order of operands626 627 %r0 = insertvalue { i64, i64, i1 } poison, i64 %s0, 0628 %r1 = insertvalue { i64, i64, i1 } %r0, i64 %s2, 1629 %r = insertvalue { i64, i64, i1 } %r1, i1 %k, 2630 ret { i64, i64, i1 } %r631}632 633; basic test for combineCarryDiamond() with add operands reversed634define { i64, i64, i1 } @addcarry_2x64_add_reversed(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {635; CHECK-LABEL: addcarry_2x64_add_reversed:636; CHECK: # %bb.0:637; CHECK-NEXT: movq %rdi, %rax638; CHECK-NEXT: addq %rdx, %rax639; CHECK-NEXT: adcq %rcx, %rsi640; CHECK-NEXT: setb %cl641; CHECK-NEXT: movq %rsi, %rdx642; CHECK-NEXT: retq643 %t0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)644 %s0 = extractvalue { i64, i1 } %t0, 0645 %k0 = extractvalue { i64, i1 } %t0, 1646 647 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)648 %s1 = extractvalue { i64, i1 } %t1, 0649 %k1 = extractvalue { i64, i1 } %t1, 1650 651 %zk0 = zext i1 %k0 to i64652 %t2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %s1, i64 %zk0)653 %s2 = extractvalue { i64, i1 } %t2, 0654 %k2 = extractvalue { i64, i1 } %t2, 1655 %k = add i1 %k2, %k1 ; reverse natural order of operands656 657 %r0 = insertvalue { i64, i64, i1 } poison, i64 %s0, 0658 %r1 = insertvalue { i64, i64, i1 } %r0, i64 %s2, 1659 %r = insertvalue { i64, i64, i1 } %r1, i1 %k, 2660 ret { i64, i64, i1 } %r661}662 663; Here %carryin is considered as valid carry flag for combining into ADDCARRY664; although %carryin does not come from any carry-producing instruction.665define { i64, i1 } @addcarry_fake_carry(i64 %a, i64 %b, i1 %carryin) nounwind {666; CHECK-LABEL: addcarry_fake_carry:667; CHECK: # %bb.0:668; CHECK-NEXT: movq %rdi, %rax669; CHECK-NEXT: btl $0, %edx670; CHECK-NEXT: adcq %rsi, %rax671; CHECK-NEXT: setb %dl672; CHECK-NEXT: retq673 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)674 %partial = extractvalue { i64, i1 } %t1, 0675 %k1 = extractvalue { i64, i1 } %t1, 1676 677 %zcarryin = zext i1 %carryin to i64678 %sum = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %partial, i64 %zcarryin)679 %k2 = extractvalue { i64, i1 } %sum, 1680 681 %carryout = or i1 %k1, %k2682 683 %ret = insertvalue { i64, i1 } %sum, i1 %carryout, 1684 ret { i64, i1 } %ret685}686 687; negative test: %carryin does not look like carry688define { i64, i1 } @addcarry_carry_not_zext(i64 %a, i64 %b, i64 %carryin) nounwind {689; CHECK-LABEL: addcarry_carry_not_zext:690; CHECK: # %bb.0:691; CHECK-NEXT: movq %rdi, %rax692; CHECK-NEXT: addq %rsi, %rax693; CHECK-NEXT: setb %cl694; CHECK-NEXT: addq %rdx, %rax695; CHECK-NEXT: setb %dl696; CHECK-NEXT: orb %cl, %dl697; CHECK-NEXT: retq698 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)699 %partial = extractvalue { i64, i1 } %t1, 0700 %k1 = extractvalue { i64, i1 } %t1, 1701 702 %sum = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %partial, i64 %carryin)703 %k2 = extractvalue { i64, i1 } %sum, 1704 705 %carryout = or i1 %k1, %k2706 707 %ret = insertvalue { i64, i1 } %sum, i1 %carryout, 1708 ret { i64, i1 } %ret709}710 711; negative test: %carryin does not look like carry712define { i64, i1 } @addcarry_carry_not_i1(i64 %a, i64 %b, i8 %carryin) nounwind {713; CHECK-LABEL: addcarry_carry_not_i1:714; CHECK: # %bb.0:715; CHECK-NEXT: addq %rsi, %rdi716; CHECK-NEXT: setb %cl717; CHECK-NEXT: movzbl %dl, %eax718; CHECK-NEXT: addq %rdi, %rax719; CHECK-NEXT: setb %dl720; CHECK-NEXT: orb %cl, %dl721; CHECK-NEXT: retq722 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)723 %partial = extractvalue { i64, i1 } %t1, 0724 %k1 = extractvalue { i64, i1 } %t1, 1725 726 %zcarryin = zext i8 %carryin to i64727 %sum = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %partial, i64 %zcarryin)728 %k2 = extractvalue { i64, i1 } %sum, 1729 730 %carryout = or i1 %k1, %k2731 732 %ret = insertvalue { i64, i1 } %sum, i1 %carryout, 1733 ret { i64, i1 } %ret734}735 736; Check that we can reconstruct a carry if it is masked.737define { i64, i1 } @addcarry_carry_and_1(i64 %a, i64 %b, i64 %carryin) nounwind {738; CHECK-LABEL: addcarry_carry_and_1:739; CHECK: # %bb.0:740; CHECK-NEXT: movq %rdi, %rax741; CHECK-NEXT: btl $0, %edx742; CHECK-NEXT: adcq %rsi, %rax743; CHECK-NEXT: setb %dl744; CHECK-NEXT: retq745 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)746 %partial = extractvalue { i64, i1 } %t1, 0747 %k1 = extractvalue { i64, i1 } %t1, 1748 749 %mcarryin = and i64 %carryin, 1750 %sum = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %partial, i64 %mcarryin)751 %k2 = extractvalue { i64, i1 } %sum, 1752 753 %carryout = or i1 %k1, %k2754 755 %ret = insertvalue { i64, i1 } %sum, i1 %carryout, 1756 ret { i64, i1 } %ret757}758 759; negative test for combineCarryDiamond(): uaddo mixed with usubo760define { i64, i64, i1 } @addcarry_mixed_2x64(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {761; CHECK-LABEL: addcarry_mixed_2x64:762; CHECK: # %bb.0:763; CHECK-NEXT: movq %rdi, %rax764; CHECK-NEXT: addq %rcx, %rsi765; CHECK-NEXT: setb %dil766; CHECK-NEXT: addq %rdx, %rax767; CHECK-NEXT: sbbq $0, %rsi768; CHECK-NEXT: setb %cl769; CHECK-NEXT: orb %dil, %cl770; CHECK-NEXT: movq %rsi, %rdx771; CHECK-NEXT: retq772 %t0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)773 %s0 = extractvalue { i64, i1 } %t0, 0774 %k0 = extractvalue { i64, i1 } %t0, 1775 776 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)777 %s1 = extractvalue { i64, i1 } %t1, 0778 %k1 = extractvalue { i64, i1 } %t1, 1779 780 %zk0 = zext i1 %k0 to i64781 %t2 = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %s1, i64 %zk0)782 %s2 = extractvalue { i64, i1 } %t2, 0783 %k2 = extractvalue { i64, i1 } %t2, 1784 %k = or i1 %k1, %k2785 786 %r0 = insertvalue { i64, i64, i1 } poison, i64 %s0, 0787 %r1 = insertvalue { i64, i64, i1 } %r0, i64 %s2, 1788 %r = insertvalue { i64, i64, i1 } %r1, i1 %k, 2789 ret { i64, i64, i1 } %r790}791 792%struct.U320 = type { [5 x i64] }793 794define i32 @add_U320_without_i128_add(ptr nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) nounwind {795; CHECK-LABEL: add_U320_without_i128_add:796; CHECK: # %bb.0:797; CHECK-NEXT: movq 16(%rdi), %rax798; CHECK-NEXT: movq 24(%rdi), %r10799; CHECK-NEXT: movq 32(%rdi), %r11800; CHECK-NEXT: addq %rsi, (%rdi)801; CHECK-NEXT: adcq %rdx, 8(%rdi)802; CHECK-NEXT: movq %rax, %rdx803; CHECK-NEXT: adcq %rcx, %rdx804; CHECK-NEXT: addq %rcx, %rax805; CHECK-NEXT: movq %r10, %rcx806; CHECK-NEXT: adcq %r8, %rcx807; CHECK-NEXT: cmpq %rax, %rdx808; CHECK-NEXT: adcq $0, %rcx809; CHECK-NEXT: leaq (%r11,%r9), %rsi810; CHECK-NEXT: addq %r8, %r10811; CHECK-NEXT: movq %r11, %r8812; CHECK-NEXT: adcq %r9, %r8813; CHECK-NEXT: cmpq %r10, %rcx814; CHECK-NEXT: adcq $0, %r8815; CHECK-NEXT: xorl %eax, %eax816; CHECK-NEXT: cmpq %rsi, %r8817; CHECK-NEXT: setb %al818; CHECK-NEXT: addq %r9, %r11819; CHECK-NEXT: movq %rdx, 16(%rdi)820; CHECK-NEXT: movq %rcx, 24(%rdi)821; CHECK-NEXT: movq %r8, 32(%rdi)822; CHECK-NEXT: adcl $0, %eax823; CHECK-NEXT: retq824 %7 = load i64, ptr %0, align 8825 %8 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 1826 %9 = load i64, ptr %8, align 8827 %10 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 2828 %11 = load i64, ptr %10, align 8829 %12 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 3830 %13 = load i64, ptr %12, align 8831 %14 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 4832 %15 = load i64, ptr %14, align 8833 %16 = add i64 %7, %1834 %17 = add i64 %9, %2835 %18 = icmp ult i64 %16, %1836 %19 = zext i1 %18 to i64837 %20 = add i64 %17, %19838 %21 = add i64 %11, %3839 %22 = icmp ult i64 %17, %9840 %23 = zext i1 %22 to i64841 %24 = icmp ult i64 %20, %17842 %25 = zext i1 %24 to i64843 %26 = add i64 %21, %23844 %27 = add i64 %26, %25845 %28 = add i64 %13, %4846 %29 = icmp ult i64 %21, %11847 %30 = zext i1 %29 to i64848 %31 = icmp ult i64 %27, %21849 %32 = zext i1 %31 to i64850 %33 = add i64 %28, %30851 %34 = add i64 %33, %32852 %35 = add i64 %15, %5853 %36 = icmp ult i64 %28, %13854 %37 = zext i1 %36 to i64855 %38 = icmp ult i64 %34, %28856 %39 = zext i1 %38 to i64857 %40 = add i64 %35, %37858 %41 = add i64 %40, %39859 store i64 %16, ptr %0, align 8860 store i64 %20, ptr %8, align 8861 store i64 %27, ptr %10, align 8862 store i64 %34, ptr %12, align 8863 store i64 %41, ptr %14, align 8864 %42 = icmp ult i64 %35, %15865 %43 = zext i1 %42 to i32866 %44 = icmp ult i64 %41, %35867 %45 = zext i1 %44 to i32868 %46 = add nuw nsw i32 %45, %43869 ret i32 %46870}871 872define i32 @add_U320_without_i128_or(ptr nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) nounwind {873; CHECK-LABEL: add_U320_without_i128_or:874; CHECK: # %bb.0:875; CHECK-NEXT: addq %rsi, (%rdi)876; CHECK-NEXT: adcq %rdx, 8(%rdi)877; CHECK-NEXT: adcq %rcx, 16(%rdi)878; CHECK-NEXT: adcq %r8, 24(%rdi)879; CHECK-NEXT: adcq %r9, 32(%rdi)880; CHECK-NEXT: setb %al881; CHECK-NEXT: movzbl %al, %eax882; CHECK-NEXT: retq883 %7 = load i64, ptr %0, align 8884 %8 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 1885 %9 = load i64, ptr %8, align 8886 %10 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 2887 %11 = load i64, ptr %10, align 8888 %12 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 3889 %13 = load i64, ptr %12, align 8890 %14 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 4891 %15 = load i64, ptr %14, align 8892 %16 = add i64 %7, %1893 %17 = add i64 %9, %2894 %18 = icmp ult i64 %16, %1895 %19 = zext i1 %18 to i64896 %20 = add i64 %17, %19897 %21 = add i64 %11, %3898 %22 = icmp ult i64 %17, %9899 %23 = icmp ult i64 %20, %17900 %24 = or i1 %22, %23901 %25 = zext i1 %24 to i64902 %26 = add i64 %21, %25903 %27 = add i64 %13, %4904 %28 = icmp ult i64 %21, %11905 %29 = icmp ult i64 %26, %21906 %30 = or i1 %28, %29907 %31 = zext i1 %30 to i64908 %32 = add i64 %27, %31909 %33 = add i64 %15, %5910 %34 = icmp ult i64 %27, %13911 %35 = icmp ult i64 %32, %27912 %36 = or i1 %34, %35913 %37 = zext i1 %36 to i64914 %38 = add i64 %33, %37915 store i64 %16, ptr %0, align 8916 store i64 %20, ptr %8, align 8917 store i64 %26, ptr %10, align 8918 store i64 %32, ptr %12, align 8919 store i64 %38, ptr %14, align 8920 %39 = icmp ult i64 %33, %15921 %40 = icmp ult i64 %38, %33922 %41 = or i1 %39, %40923 %42 = zext i1 %41 to i32924 ret i32 %42925}926 927define i32 @add_U320_without_i128_xor(ptr nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) nounwind {928; CHECK-LABEL: add_U320_without_i128_xor:929; CHECK: # %bb.0:930; CHECK-NEXT: addq %rsi, (%rdi)931; CHECK-NEXT: adcq %rdx, 8(%rdi)932; CHECK-NEXT: adcq %rcx, 16(%rdi)933; CHECK-NEXT: adcq %r8, 24(%rdi)934; CHECK-NEXT: adcq %r9, 32(%rdi)935; CHECK-NEXT: setb %al936; CHECK-NEXT: movzbl %al, %eax937; CHECK-NEXT: retq938 %7 = load i64, ptr %0, align 8939 %8 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 1940 %9 = load i64, ptr %8, align 8941 %10 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 2942 %11 = load i64, ptr %10, align 8943 %12 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 3944 %13 = load i64, ptr %12, align 8945 %14 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 4946 %15 = load i64, ptr %14, align 8947 %16 = add i64 %7, %1948 %17 = add i64 %9, %2949 %18 = icmp ult i64 %16, %1950 %19 = zext i1 %18 to i64951 %20 = add i64 %17, %19952 %21 = add i64 %11, %3953 %22 = icmp ult i64 %17, %9954 %23 = icmp ult i64 %20, %17955 %24 = xor i1 %22, %23956 %25 = zext i1 %24 to i64957 %26 = add i64 %21, %25958 %27 = add i64 %13, %4959 %28 = icmp ult i64 %21, %11960 %29 = icmp ult i64 %26, %21961 %30 = xor i1 %28, %29962 %31 = zext i1 %30 to i64963 %32 = add i64 %27, %31964 %33 = add i64 %15, %5965 %34 = icmp ult i64 %27, %13966 %35 = icmp ult i64 %32, %27967 %36 = xor i1 %34, %35968 %37 = zext i1 %36 to i64969 %38 = add i64 %33, %37970 store i64 %16, ptr %0, align 8971 store i64 %20, ptr %8, align 8972 store i64 %26, ptr %10, align 8973 store i64 %32, ptr %12, align 8974 store i64 %38, ptr %14, align 8975 %39 = icmp ult i64 %33, %15976 %40 = icmp ult i64 %38, %33977 %41 = xor i1 %39, %40978 %42 = zext i1 %41 to i32979 ret i32 %42980}981 982; Either the primary addition can overflow or the addition of the carry, but983; they cannot both overflow.984define i32 @bogus_add_U320_without_i128_and(ptr nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) nounwind {985; CHECK-LABEL: bogus_add_U320_without_i128_and:986; CHECK: # %bb.0:987; CHECK-NEXT: addq %rsi, (%rdi)988; CHECK-NEXT: adcq %rdx, 8(%rdi)989; CHECK-NEXT: addq %rcx, 16(%rdi)990; CHECK-NEXT: addq %r8, 24(%rdi)991; CHECK-NEXT: addq %r9, 32(%rdi)992; CHECK-NEXT: xorl %eax, %eax993; CHECK-NEXT: retq994 %7 = load i64, ptr %0, align 8995 %8 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 1996 %9 = load i64, ptr %8, align 8997 %10 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 2998 %11 = load i64, ptr %10, align 8999 %12 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 31000 %13 = load i64, ptr %12, align 81001 %14 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 41002 %15 = load i64, ptr %14, align 81003 %16 = add i64 %7, %11004 %17 = add i64 %9, %21005 %18 = icmp ult i64 %16, %11006 %19 = zext i1 %18 to i641007 %20 = add i64 %17, %191008 %21 = add i64 %11, %31009 %22 = icmp ult i64 %17, %91010 %23 = icmp ult i64 %20, %171011 %24 = and i1 %22, %231012 %25 = zext i1 %24 to i641013 %26 = add i64 %21, %251014 %27 = add i64 %13, %41015 %28 = icmp ult i64 %21, %111016 %29 = icmp ult i64 %26, %211017 %30 = and i1 %28, %291018 %31 = zext i1 %30 to i641019 %32 = add i64 %27, %311020 %33 = add i64 %15, %51021 %34 = icmp ult i64 %27, %131022 %35 = icmp ult i64 %32, %271023 %36 = and i1 %34, %351024 %37 = zext i1 %36 to i641025 %38 = add i64 %33, %371026 store i64 %16, ptr %0, align 81027 store i64 %20, ptr %8, align 81028 store i64 %26, ptr %10, align 81029 store i64 %32, ptr %12, align 81030 store i64 %38, ptr %14, align 81031 %39 = icmp ult i64 %33, %151032 %40 = icmp ult i64 %38, %331033 %41 = and i1 %39, %401034 %42 = zext i1 %41 to i321035 ret i32 %421036}1037 1038define void @add_U320_without_i128_or_no_ret(ptr nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) nounwind {1039; CHECK-LABEL: add_U320_without_i128_or_no_ret:1040; CHECK: # %bb.0:1041; CHECK-NEXT: addq %rsi, (%rdi)1042; CHECK-NEXT: adcq %rdx, 8(%rdi)1043; CHECK-NEXT: adcq %rcx, 16(%rdi)1044; CHECK-NEXT: adcq %r8, 24(%rdi)1045; CHECK-NEXT: adcq %r9, 32(%rdi)1046; CHECK-NEXT: retq1047 %7 = load i64, ptr %0, align 81048 %8 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 11049 %9 = load i64, ptr %8, align 81050 %10 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 21051 %11 = load i64, ptr %10, align 81052 %12 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 31053 %13 = load i64, ptr %12, align 81054 %14 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 41055 %15 = load i64, ptr %14, align 81056 %16 = add i64 %7, %11057 %17 = add i64 %9, %21058 %18 = icmp ult i64 %16, %11059 %19 = zext i1 %18 to i641060 %20 = add i64 %17, %191061 %21 = add i64 %11, %31062 %22 = icmp ult i64 %17, %91063 %23 = icmp ult i64 %20, %171064 %24 = or i1 %22, %231065 %25 = zext i1 %24 to i641066 %26 = add i64 %21, %251067 %27 = add i64 %13, %41068 %28 = icmp ult i64 %21, %111069 %29 = icmp ult i64 %26, %211070 %30 = or i1 %28, %291071 %31 = zext i1 %30 to i641072 %32 = add i64 %27, %311073 %33 = add i64 %15, %51074 %34 = icmp ult i64 %27, %131075 %35 = icmp ult i64 %32, %271076 %36 = or i1 %34, %351077 %37 = zext i1 %36 to i641078 %38 = add i64 %33, %371079 store i64 %16, ptr %0, align 81080 store i64 %20, ptr %8, align 81081 store i64 %26, ptr %10, align 81082 store i64 %32, ptr %12, align 81083 store i64 %38, ptr %14, align 81084 ret void1085}1086 1087define i32 @add_U320_uaddo(ptr nocapture dereferenceable(40) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) nounwind {1088; CHECK-LABEL: add_U320_uaddo:1089; CHECK: # %bb.0:1090; CHECK-NEXT: addq %rsi, (%rdi)1091; CHECK-NEXT: adcq %rdx, 8(%rdi)1092; CHECK-NEXT: adcq %rcx, 16(%rdi)1093; CHECK-NEXT: adcq %r8, 24(%rdi)1094; CHECK-NEXT: adcq %r9, 32(%rdi)1095; CHECK-NEXT: setb %al1096; CHECK-NEXT: movzbl %al, %eax1097; CHECK-NEXT: retq1098 %7 = load i64, ptr %0, align 81099 %8 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 11100 %9 = load i64, ptr %8, align 81101 %10 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 21102 %11 = load i64, ptr %10, align 81103 %12 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 31104 %13 = load i64, ptr %12, align 81105 %14 = getelementptr inbounds %struct.U320, ptr %0, i64 0, i32 0, i64 41106 %15 = load i64, ptr %14, align 81107 %16 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %7, i64 %1)1108 %17 = extractvalue { i64, i1 } %16, 11109 %18 = extractvalue { i64, i1 } %16, 01110 %19 = zext i1 %17 to i641111 %20 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %9, i64 %2)1112 %21 = extractvalue { i64, i1 } %20, 11113 %22 = extractvalue { i64, i1 } %20, 01114 %23 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %22, i64 %19)1115 %24 = extractvalue { i64, i1 } %23, 11116 %25 = extractvalue { i64, i1 } %23, 01117 %26 = or i1 %21, %241118 %27 = zext i1 %26 to i641119 %28 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %11, i64 %3)1120 %29 = extractvalue { i64, i1 } %28, 11121 %30 = extractvalue { i64, i1 } %28, 01122 %31 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %30, i64 %27)1123 %32 = extractvalue { i64, i1 } %31, 11124 %33 = extractvalue { i64, i1 } %31, 01125 %34 = or i1 %29, %321126 %35 = zext i1 %34 to i641127 %36 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %13, i64 %4)1128 %37 = extractvalue { i64, i1 } %36, 11129 %38 = extractvalue { i64, i1 } %36, 01130 %39 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %38, i64 %35)1131 %40 = extractvalue { i64, i1 } %39, 11132 %41 = extractvalue { i64, i1 } %39, 01133 %42 = or i1 %37, %401134 %43 = zext i1 %42 to i641135 %44 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %15, i64 %5)1136 %45 = extractvalue { i64, i1 } %44, 11137 %46 = extractvalue { i64, i1 } %44, 01138 %47 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %46, i64 %43)1139 %48 = extractvalue { i64, i1 } %47, 11140 %49 = extractvalue { i64, i1 } %47, 01141 %50 = or i1 %45, %481142 store i64 %18, ptr %0, align 81143 store i64 %25, ptr %8, align 81144 store i64 %33, ptr %10, align 81145 store i64 %41, ptr %12, align 81146 store i64 %49, ptr %14, align 81147 %51 = zext i1 %50 to i321148 ret i32 %511149}1150 1151%struct.U192 = type { [3 x i64] }1152 1153define void @PR39464(ptr noalias nocapture sret(%struct.U192) %0, ptr nocapture readonly dereferenceable(24) %1, ptr nocapture readonly dereferenceable(24) %2) nounwind {1154; CHECK-LABEL: PR39464:1155; CHECK: # %bb.0:1156; CHECK-NEXT: movq %rdi, %rax1157; CHECK-NEXT: movq (%rsi), %rcx1158; CHECK-NEXT: addq (%rdx), %rcx1159; CHECK-NEXT: movq %rcx, (%rdi)1160; CHECK-NEXT: movq 8(%rsi), %rcx1161; CHECK-NEXT: adcq 8(%rdx), %rcx1162; CHECK-NEXT: movq %rcx, 8(%rdi)1163; CHECK-NEXT: movq 16(%rsi), %rcx1164; CHECK-NEXT: adcq 16(%rdx), %rcx1165; CHECK-NEXT: movq %rcx, 16(%rdi)1166; CHECK-NEXT: retq1167 %4 = load i64, ptr %1, align 81168 %5 = load i64, ptr %2, align 81169 %6 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %4, i64 %5)1170 %7 = extractvalue { i64, i1 } %6, 11171 %8 = extractvalue { i64, i1 } %6, 01172 %9 = zext i1 %7 to i641173 store i64 %8, ptr %0, align 81174 %10 = getelementptr inbounds %struct.U192, ptr %1, i64 0, i32 0, i64 11175 %11 = load i64, ptr %10, align 81176 %12 = getelementptr inbounds %struct.U192, ptr %2, i64 0, i32 0, i64 11177 %13 = load i64, ptr %12, align 81178 %14 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %11, i64 %13)1179 %15 = extractvalue { i64, i1 } %14, 11180 %16 = extractvalue { i64, i1 } %14, 01181 %17 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %16, i64 %9)1182 %18 = extractvalue { i64, i1 } %17, 11183 %19 = extractvalue { i64, i1 } %17, 01184 %20 = or i1 %15, %181185 %21 = zext i1 %20 to i641186 %22 = getelementptr inbounds %struct.U192, ptr %0, i64 0, i32 0, i64 11187 store i64 %19, ptr %22, align 81188 %23 = getelementptr inbounds %struct.U192, ptr %1, i64 0, i32 0, i64 21189 %24 = load i64, ptr %23, align 81190 %25 = getelementptr inbounds %struct.U192, ptr %2, i64 0, i32 0, i64 21191 %26 = load i64, ptr %25, align 81192 %27 = add i64 %24, %261193 %28 = add i64 %27, %211194 %29 = getelementptr inbounds %struct.U192, ptr %0, i64 0, i32 0, i64 21195 store i64 %28, ptr %29, align 81196 ret void1197}1198 1199 1200%uint128 = type { i64, i64 }1201 1202define zeroext i1 @uaddo_U128_without_i128_or(i64 %0, i64 %1, i64 %2, i64 %3, ptr nocapture %4) nounwind {1203; CHECK-LABEL: uaddo_U128_without_i128_or:1204; CHECK: # %bb.0:1205; CHECK-NEXT: addq %rdx, %rdi1206; CHECK-NEXT: adcq %rcx, %rsi1207; CHECK-NEXT: setb %al1208; CHECK-NEXT: movq %rsi, (%r8)1209; CHECK-NEXT: movq %rdi, 8(%r8)1210; CHECK-NEXT: retq1211 %6 = add i64 %2, %01212 %7 = icmp ult i64 %6, %01213 %8 = add i64 %3, %11214 %9 = icmp ult i64 %8, %11215 %10 = zext i1 %7 to i641216 %11 = add i64 %8, %101217 %12 = icmp ult i64 %11, %81218 %13 = or i1 %9, %121219 store i64 %11, ptr %4, align 81220 %14 = getelementptr inbounds %uint128, ptr %4, i64 0, i32 11221 store i64 %6, ptr %14, align 81222 ret i1 %131223}1224 1225 1226%uint192 = type { i64, i64, i64 }1227 1228define void @add_U192_without_i128_or(ptr sret(%uint192) %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6) nounwind {1229; CHECK-LABEL: add_U192_without_i128_or:1230; CHECK: # %bb.0:1231; CHECK-NEXT: movq %rdi, %rax1232; CHECK-NEXT: addq %r8, %rsi1233; CHECK-NEXT: adcq %r9, %rdx1234; CHECK-NEXT: adcq {{[0-9]+}}(%rsp), %rcx1235; CHECK-NEXT: movq %rcx, (%rdi)1236; CHECK-NEXT: movq %rdx, 8(%rdi)1237; CHECK-NEXT: movq %rsi, 16(%rdi)1238; CHECK-NEXT: retq1239 %8 = add i64 %4, %11240 %9 = icmp ult i64 %8, %11241 %10 = add i64 %5, %21242 %11 = icmp ult i64 %10, %21243 %12 = zext i1 %9 to i641244 %13 = add i64 %10, %121245 %14 = icmp ult i64 %13, %101246 %15 = or i1 %11, %141247 %16 = add i64 %6, %31248 %17 = zext i1 %15 to i641249 %18 = add i64 %16, %171250 store i64 %18, ptr %0, align 81251 %19 = getelementptr inbounds %uint192, ptr %0, i64 0, i32 11252 store i64 %13, ptr %19, align 81253 %20 = getelementptr inbounds %uint192, ptr %0, i64 0, i32 21254 store i64 %8, ptr %20, align 81255 ret void1256}1257 1258 1259%uint256 = type { %uint128, %uint128 }1260 1261; Classic unrolled 256-bit addition implementation using i64 as the word type.1262; It starts by adding least significant words and propagates carry to additions of the higher words.1263define void @add_U256_without_i128_or_by_i64_words(ptr sret(%uint256) %0, ptr %1, ptr %2) nounwind {1264; CHECK-LABEL: add_U256_without_i128_or_by_i64_words:1265; CHECK: # %bb.0:1266; CHECK-NEXT: movq %rdi, %rax1267; CHECK-NEXT: movq (%rdx), %rcx1268; CHECK-NEXT: movq 8(%rdx), %rdi1269; CHECK-NEXT: addq (%rsi), %rcx1270; CHECK-NEXT: adcq 8(%rsi), %rdi1271; CHECK-NEXT: movq 16(%rdx), %r81272; CHECK-NEXT: adcq 16(%rsi), %r81273; CHECK-NEXT: movq 24(%rdx), %rdx1274; CHECK-NEXT: adcq 24(%rsi), %rdx1275; CHECK-NEXT: movq %rdx, (%rax)1276; CHECK-NEXT: movq %r8, 8(%rax)1277; CHECK-NEXT: movq %rdi, 16(%rax)1278; CHECK-NEXT: movq %rcx, 24(%rax)1279; CHECK-NEXT: retq1280 %4 = load i64, ptr %1, align 81281 %5 = load i64, ptr %2, align 81282 %6 = add i64 %5, %41283 %7 = icmp ult i64 %6, %41284 %8 = getelementptr inbounds %uint256, ptr %1, i64 0, i32 0, i32 11285 %9 = load i64, ptr %8, align 81286 %10 = getelementptr inbounds %uint256, ptr %2, i64 0, i32 0, i32 11287 %11 = load i64, ptr %10, align 81288 %12 = add i64 %11, %91289 %13 = icmp ult i64 %12, %91290 %14 = zext i1 %7 to i641291 %15 = add i64 %12, %141292 %16 = icmp ult i64 %15, %141293 %17 = or i1 %13, %161294 %18 = getelementptr inbounds %uint256, ptr %1, i64 0, i32 1, i32 01295 %19 = load i64, ptr %18, align 81296 %20 = getelementptr inbounds %uint256, ptr %2, i64 0, i32 1, i32 01297 %21 = load i64, ptr %20, align 81298 %22 = add i64 %21, %191299 %23 = icmp ult i64 %22, %191300 %24 = zext i1 %17 to i641301 %25 = add i64 %22, %241302 %26 = icmp ult i64 %25, %241303 %27 = or i1 %23, %261304 %28 = getelementptr inbounds %uint256, ptr %1, i64 0, i32 1, i32 11305 %29 = load i64, ptr %28, align 81306 %30 = getelementptr inbounds %uint256, ptr %2, i64 0, i32 1, i32 11307 %31 = load i64, ptr %30, align 81308 %32 = add i64 %31, %291309 %33 = zext i1 %27 to i641310 %34 = add i64 %32, %331311 store i64 %34, ptr %0, align 81312 %35 = getelementptr inbounds %uint256, ptr %0, i64 0, i32 0, i32 11313 store i64 %25, ptr %35, align 81314 %36 = getelementptr inbounds %uint256, ptr %0, i64 0, i32 1, i32 01315 store i64 %15, ptr %36, align 81316 %37 = getelementptr inbounds %uint256, ptr %0, i64 0, i32 1, i32 11317 store i64 %6, ptr %37, align 81318 ret void1319}1320 1321; The 256-bit addition implementation using two inlined uaddo procedures for U128 type { i64, i64 }.1322; This is similar to how LLVM legalize types in CodeGen.1323define void @add_U256_without_i128_or_recursive(ptr sret(%uint256) %0, ptr %1, ptr %2) nounwind {1324; CHECK-LABEL: add_U256_without_i128_or_recursive:1325; CHECK: # %bb.0:1326; CHECK-NEXT: movq %rdi, %rax1327; CHECK-NEXT: movq (%rdx), %rcx1328; CHECK-NEXT: movq 8(%rdx), %rdi1329; CHECK-NEXT: addq (%rsi), %rcx1330; CHECK-NEXT: adcq 8(%rsi), %rdi1331; CHECK-NEXT: movq 16(%rdx), %r81332; CHECK-NEXT: movq 24(%rdx), %rdx1333; CHECK-NEXT: adcq 16(%rsi), %r81334; CHECK-NEXT: adcq 24(%rsi), %rdx1335; CHECK-NEXT: movq %rcx, (%rax)1336; CHECK-NEXT: movq %rdi, 8(%rax)1337; CHECK-NEXT: movq %r8, 16(%rax)1338; CHECK-NEXT: movq %rdx, 24(%rax)1339; CHECK-NEXT: retq1340 %4 = load i64, ptr %1, align 81341 %5 = getelementptr inbounds %uint256, ptr %1, i64 0, i32 0, i32 11342 %6 = load i64, ptr %5, align 81343 %7 = load i64, ptr %2, align 81344 %8 = getelementptr inbounds %uint256, ptr %2, i64 0, i32 0, i32 11345 %9 = load i64, ptr %8, align 81346 %10 = add i64 %7, %41347 %11 = icmp ult i64 %10, %41348 %12 = add i64 %9, %61349 %13 = icmp ult i64 %12, %61350 %14 = zext i1 %11 to i641351 %15 = add i64 %12, %141352 %16 = icmp ult i64 %15, %121353 %17 = or i1 %13, %161354 %18 = getelementptr inbounds %uint256, ptr %1, i64 0, i32 1, i32 01355 %19 = load i64, ptr %18, align 81356 %20 = getelementptr inbounds %uint256, ptr %1, i64 0, i32 1, i32 11357 %21 = load i64, ptr %20, align 81358 %22 = getelementptr inbounds %uint256, ptr %2, i64 0, i32 1, i32 01359 %23 = load i64, ptr %22, align 81360 %24 = getelementptr inbounds %uint256, ptr %2, i64 0, i32 1, i32 11361 %25 = load i64, ptr %24, align 81362 %26 = add i64 %23, %191363 %27 = icmp ult i64 %26, %191364 %28 = add i64 %25, %211365 %29 = zext i1 %27 to i641366 %30 = add i64 %28, %291367 %31 = zext i1 %17 to i641368 %32 = add i64 %26, %311369 %33 = icmp ult i64 %32, %261370 %34 = zext i1 %33 to i641371 %35 = add i64 %30, %341372 store i64 %10, ptr %0, align 81373 %36 = getelementptr inbounds %uint256, ptr %0, i64 0, i32 0, i32 11374 store i64 %15, ptr %36, align 81375 %37 = getelementptr inbounds %uint256, ptr %0, i64 0, i32 1, i32 01376 store i64 %32, ptr %37, align 81377 %38 = getelementptr inbounds %uint256, ptr %0, i64 0, i32 1, i32 11378 store i64 %35, ptr %38, align 81379 ret void1380}1381 1382define i32 @addcarry_ult(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {1383; CHECK-LABEL: addcarry_ult:1384; CHECK: # %bb.0:1385; CHECK-NEXT: movl %edi, %eax1386; CHECK-NEXT: cmpl %ecx, %edx1387; CHECK-NEXT: adcl %esi, %eax1388; CHECK-NEXT: retq1389 %s = add i32 %a, %b1390 %k = icmp ult i32 %x, %y1391 %z = zext i1 %k to i321392 %r = add i32 %s, %z1393 ret i32 %r1394}1395 1396define i32 @addcarry_ugt(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {1397; CHECK-LABEL: addcarry_ugt:1398; CHECK: # %bb.0:1399; CHECK-NEXT: movl %edi, %eax1400; CHECK-NEXT: cmpl %edx, %ecx1401; CHECK-NEXT: adcl %esi, %eax1402; CHECK-NEXT: retq1403 %s = add i32 %a, %b1404 %k = icmp ugt i32 %x, %y1405 %z = zext i1 %k to i321406 %r = add i32 %s, %z1407 ret i32 %r1408}1409 1410define i32 @addcarry_ule(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {1411; CHECK-LABEL: addcarry_ule:1412; CHECK: # %bb.0:1413; CHECK-NEXT: # kill: def $esi killed $esi def $rsi1414; CHECK-NEXT: # kill: def $edi killed $edi def $rdi1415; CHECK-NEXT: leal (%rdi,%rsi), %eax1416; CHECK-NEXT: cmpl %edx, %ecx1417; CHECK-NEXT: sbbl $-1, %eax1418; CHECK-NEXT: retq1419 %s = add i32 %a, %b1420 %k = icmp ule i32 %x, %y1421 %z = zext i1 %k to i321422 %r = add i32 %s, %z1423 ret i32 %r1424}1425 1426define i32 @addcarry_uge(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {1427; CHECK-LABEL: addcarry_uge:1428; CHECK: # %bb.0:1429; CHECK-NEXT: # kill: def $esi killed $esi def $rsi1430; CHECK-NEXT: # kill: def $edi killed $edi def $rdi1431; CHECK-NEXT: leal (%rdi,%rsi), %eax1432; CHECK-NEXT: cmpl %ecx, %edx1433; CHECK-NEXT: sbbl $-1, %eax1434; CHECK-NEXT: retq1435 %s = add i32 %a, %b1436 %k = icmp uge i32 %x, %y1437 %z = zext i1 %k to i321438 %r = add i32 %s, %z1439 ret i32 %r1440}1441 1442define { i64, i64 } @addcarry_commutative_1(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {1443; CHECK-LABEL: addcarry_commutative_1:1444; CHECK: # %bb.0:1445; CHECK-NEXT: movq %rsi, %rax1446; CHECK-NEXT: addq %rdx, %rdi1447; CHECK-NEXT: adcq %rcx, %rax1448; CHECK-NEXT: movq %rax, %rdx1449; CHECK-NEXT: retq1450 %z0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)1451 %k0 = extractvalue { i64, i1 } %z0, 11452 %k0z = zext i1 %k0 to i641453 1454 %t1s = add i64 %x1, %y11455 %z1s = add i64 %t1s, %k0z1456 1457 ; same as the above, but args swapped1458 %a1s = add i64 %y1, %x11459 %b1s = add i64 %a1s, %k0z1460 1461 %r0 = insertvalue { i64, i64 } poison, i64 %z1s, 01462 %r1 = insertvalue { i64, i64 } %r0, i64 %b1s, 11463 ret { i64, i64 } %r11464}1465 1466define { i64, i64 } @addcarry_commutative_2(i64 %x0, i64 %x1, i64 %y0, i64 %y1) nounwind {1467; CHECK-LABEL: addcarry_commutative_2:1468; CHECK: # %bb.0:1469; CHECK-NEXT: movq %rsi, %rax1470; CHECK-NEXT: addq %rdx, %rdi1471; CHECK-NEXT: adcq %rcx, %rax1472; CHECK-NEXT: movq %rax, %rdx1473; CHECK-NEXT: retq1474 %z0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x0, i64 %y0)1475 %k0 = extractvalue { i64, i1 } %z0, 11476 %k0z = zext i1 %k0 to i641477 1478 %t1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x1, i64 %y1)1479 %t1s = extractvalue { i64, i1 } %t1, 01480 %z1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %t1s, i64 %k0z)1481 %z1s = extractvalue { i64, i1 } %z1, 01482 1483 ; same as the above, but args swapped1484 %a1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %y1, i64 %x1)1485 %a1s = extractvalue { i64, i1 } %a1, 01486 %b1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a1s, i64 %k0z)1487 %b1s = extractvalue { i64, i1 } %b1, 01488 1489 %r0 = insertvalue { i64, i64 } poison, i64 %z1s, 01490 %r1 = insertvalue { i64, i64 } %r0, i64 %b1s, 11491 ret { i64, i64 } %r11492}1493 1494define i1 @pr84831(i64 %arg) {1495; CHECK-LABEL: pr84831:1496; CHECK: # %bb.0:1497; CHECK-NEXT: testq %rdi, %rdi1498; CHECK-NEXT: setne %al1499; CHECK-NEXT: xorl %ecx, %ecx1500; CHECK-NEXT: addb $-1, %al1501; CHECK-NEXT: adcq $1, %rcx1502; CHECK-NEXT: setb %al1503; CHECK-NEXT: retq1504 %a = icmp ult i64 0, %arg1505 %add1 = add i64 0, 11506 %carryout1 = icmp ult i64 %add1, 01507 %b = zext i1 %a to i641508 %add2 = add i64 %add1, %b1509 %carryout2 = icmp ult i64 %add2, %add11510 %zc1 = zext i1 %carryout1 to i631511 %zc2 = zext i1 %carryout2 to i631512 %or = or i63 %zc1, %zc21513 %trunc = trunc i63 %or to i11514 ret i1 %trunc1515}1516 1517define void @pr169691(ptr %p0, i64 %implicit, i1 zeroext %carry) {1518; CHECK-LABEL: pr169691:1519; CHECK: # %bb.0:1520; CHECK-NEXT: addb $-1, %dl1521; CHECK-NEXT: adcq %rsi, (%rdi)1522; CHECK-NEXT: adcq %rsi, 8(%rdi)1523; CHECK-NEXT: retq1524 %a0 = load i64, ptr %p0, align 81525 %uaddo0 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a0, i64 %implicit)1526 %uaddo0.1 = extractvalue { i64, i1 } %uaddo0, 11527 %uaddo0.0 = extractvalue { i64, i1 } %uaddo0, 01528 %zextc = zext i1 %carry to i641529 %uaddo0b = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %uaddo0.0, i64 %zextc)1530 %uaddo0b.1 = extractvalue { i64, i1 } %uaddo0b, 11531 %uaddo0b.0 = extractvalue { i64, i1 } %uaddo0b, 01532 %carry0 = or i1 %uaddo0.1, %uaddo0b.11533 store i64 %uaddo0b.0, ptr %p0, align 81534 1535 %p1 = getelementptr inbounds nuw i8, ptr %p0, i64 81536 %a1 = load i64, ptr %p1, align 81537 %uaddo1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a1, i64 %implicit)1538 %uaddo1.0 = extractvalue { i64, i1 } %uaddo1, 01539 %zext0 = zext i1 %carry0 to i641540 %uaddo1b = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %uaddo1.0, i64 %zext0)1541 %uaddo1b.0 = extractvalue { i64, i1 } %uaddo1b, 01542 store i64 %uaddo1b.0, ptr %p1, align 81543 ret void1544}1545