|
1 | 1 | ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
2 | 2 | ; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s
|
3 | 3 |
|
4 |
| -declare { i64, i1 } @llvm.usub.with.overflow.i64(i64, i64) #1 |
| 4 | +declare { i8, i64 } @llvm.x86.subborrow.64(i8, i64, i64) |
| 5 | +declare { i64, i1 } @llvm.usub.with.overflow.i64(i64, i64) |
5 | 6 |
|
6 | 7 | define i128 @sub128(i128 %a, i128 %b) nounwind {
|
7 | 8 | ; CHECK-LABEL: sub128:
|
@@ -384,3 +385,62 @@ define i32 @sub_U320_usubo(%struct.U320* nocapture dereferenceable(40) %0, i64 %
|
384 | 385 | %52 = zext i1 %51 to i32
|
385 | 386 | ret i32 %52
|
386 | 387 | }
|
| 388 | + |
| 389 | +%struct.U192 = type { [3 x i64] } |
| 390 | + |
| 391 | +define void @PR39464(%struct.U192* noalias nocapture sret %0, %struct.U192* nocapture readonly dereferenceable(24) %1, %struct.U192* nocapture readonly dereferenceable(24) %2) { |
| 392 | +; CHECK-LABEL: PR39464: |
| 393 | +; CHECK: # %bb.0: |
| 394 | +; CHECK-NEXT: movq %rdi, %rax |
| 395 | +; CHECK-NEXT: movq (%rsi), %rcx |
| 396 | +; CHECK-NEXT: xorl %r9d, %r9d |
| 397 | +; CHECK-NEXT: subq (%rdx), %rcx |
| 398 | +; CHECK-NEXT: setb %r9b |
| 399 | +; CHECK-NEXT: movq %rcx, (%rdi) |
| 400 | +; CHECK-NEXT: movq 8(%rsi), %rdi |
| 401 | +; CHECK-NEXT: subq 8(%rdx), %rdi |
| 402 | +; CHECK-NEXT: setb %r8b |
| 403 | +; CHECK-NEXT: subq %r9, %rdi |
| 404 | +; CHECK-NEXT: setb %cl |
| 405 | +; CHECK-NEXT: orb %r8b, %cl |
| 406 | +; CHECK-NEXT: movzbl %cl, %ecx |
| 407 | +; CHECK-NEXT: movq %rdi, 8(%rax) |
| 408 | +; CHECK-NEXT: movq 16(%rsi), %rsi |
| 409 | +; CHECK-NEXT: subq 16(%rdx), %rsi |
| 410 | +; CHECK-NEXT: subq %rcx, %rsi |
| 411 | +; CHECK-NEXT: movq %rsi, 16(%rax) |
| 412 | +; CHECK-NEXT: retq |
| 413 | + %4 = getelementptr inbounds %struct.U192, %struct.U192* %1, i64 0, i32 0, i64 0 |
| 414 | + %5 = load i64, i64* %4, align 8 |
| 415 | + %6 = getelementptr inbounds %struct.U192, %struct.U192* %2, i64 0, i32 0, i64 0 |
| 416 | + %7 = load i64, i64* %6, align 8 |
| 417 | + %8 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %5, i64 %7) |
| 418 | + %9 = extractvalue { i64, i1 } %8, 1 |
| 419 | + %10 = extractvalue { i64, i1 } %8, 0 |
| 420 | + %11 = zext i1 %9 to i64 |
| 421 | + %12 = getelementptr inbounds %struct.U192, %struct.U192* %0, i64 0, i32 0, i64 0 |
| 422 | + store i64 %10, i64* %12, align 8 |
| 423 | + %13 = getelementptr inbounds %struct.U192, %struct.U192* %1, i64 0, i32 0, i64 1 |
| 424 | + %14 = load i64, i64* %13, align 8 |
| 425 | + %15 = getelementptr inbounds %struct.U192, %struct.U192* %2, i64 0, i32 0, i64 1 |
| 426 | + %16 = load i64, i64* %15, align 8 |
| 427 | + %17 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %14, i64 %16) |
| 428 | + %18 = extractvalue { i64, i1 } %17, 1 |
| 429 | + %19 = extractvalue { i64, i1 } %17, 0 |
| 430 | + %20 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %19, i64 %11) |
| 431 | + %21 = extractvalue { i64, i1 } %20, 1 |
| 432 | + %22 = extractvalue { i64, i1 } %20, 0 |
| 433 | + %23 = or i1 %18, %21 |
| 434 | + %24 = zext i1 %23 to i64 |
| 435 | + %25 = getelementptr inbounds %struct.U192, %struct.U192* %0, i64 0, i32 0, i64 1 |
| 436 | + store i64 %22, i64* %25, align 8 |
| 437 | + %26 = getelementptr inbounds %struct.U192, %struct.U192* %1, i64 0, i32 0, i64 2 |
| 438 | + %27 = load i64, i64* %26, align 8 |
| 439 | + %28 = getelementptr inbounds %struct.U192, %struct.U192* %2, i64 0, i32 0, i64 2 |
| 440 | + %29 = load i64, i64* %28, align 8 |
| 441 | + %30 = sub i64 %27, %29 |
| 442 | + %31 = sub i64 %30, %24 |
| 443 | + %32 = getelementptr inbounds %struct.U192, %struct.U192* %0, i64 0, i32 0, i64 2 |
| 444 | + store i64 %31, i64* %32, align 8 |
| 445 | + ret void |
| 446 | +} |
0 commit comments