| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=-bmi2 | FileCheck %s |
| ; |
| ; For UMUL_LOHI lowering without BMI2, MUL/IMUL use RAX as an implicit source. |
| ; If one operand already lives in RAX (e.g. call result), avoid shuffling it out |
| ; and back before the multiply. |
| |
| declare i32 @foo32() |
| declare i64 @foo64() |
| |
| define i32 @mul32_no_implicit_copy(i32 %a0) nounwind { |
| ; CHECK-LABEL: mul32_no_implicit_copy: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: pushq %rbx |
| ; CHECK-NEXT: movl %edi, %ebx |
| ; CHECK-NEXT: callq foo32@PLT |
| ; CHECK-NEXT: mull %ebx |
| ; CHECK-NEXT: popq %rbx |
| ; CHECK-NEXT: retq |
| %a1 = call i32 @foo32() |
| %a2 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %a0, i32 %a1) |
| %a3 = extractvalue { i32, i1 } %a2, 0 |
| ret i32 %a3 |
| } |
| |
| define i64 @mul64_no_implicit_copy(i64 %a0) nounwind { |
| ; CHECK-LABEL: mul64_no_implicit_copy: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: pushq %rbx |
| ; CHECK-NEXT: movq %rdi, %rbx |
| ; CHECK-NEXT: callq foo64@PLT |
| ; CHECK-NEXT: mulq %rbx |
| ; CHECK-NEXT: popq %rbx |
| ; CHECK-NEXT: retq |
| %a1 = call i64 @foo64() |
| %a2 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a0, i64 %a1) |
| %a3 = extractvalue { i64, i1 } %a2, 0 |
| ret i64 %a3 |
| } |
| |
| define i64 @mul64_add_hi_order_a(ptr %x, i64 %y) { |
| ; CHECK-LABEL: mul64_add_hi_order_a: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq %rsi, %rax |
| ; CHECK-NEXT: imulq 8(%rdi), %rsi |
| ; CHECK-NEXT: mulq (%rdi) |
| ; CHECK-NEXT: leaq (%rdx,%rsi), %rax |
| ; CHECK-NEXT: retq |
| %p1 = getelementptr inbounds i64, ptr %x, i64 1 |
| %qv = load i64, ptr %p1, align 8 |
| %q = mul i64 %qv, %y |
| %pv = load i64, ptr %x, align 8 |
| %pv.zext = zext i64 %pv to i128 |
| %y.zext = zext i64 %y to i128 |
| %prod = mul nuw i128 %pv.zext, %y.zext |
| %prod.hi = lshr i128 %prod, 64 |
| %p = trunc i128 %prod.hi to i64 |
| %sum = add i64 %q, %p |
| ret i64 %sum |
| } |
| |
| define i64 @mul64_add_hi_order_b(ptr %x, i64 %y) { |
| ; CHECK-LABEL: mul64_add_hi_order_b: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq %rsi, %rax |
| ; CHECK-NEXT: mulq (%rdi) |
| ; CHECK-NEXT: imulq 8(%rdi), %rsi |
| ; CHECK-NEXT: leaq (%rsi,%rdx), %rax |
| ; CHECK-NEXT: retq |
| %pv = load i64, ptr %x, align 8 |
| %pv.zext = zext i64 %pv to i128 |
| %y.zext = zext i64 %y to i128 |
| %prod = mul nuw i128 %pv.zext, %y.zext |
| %prod.hi = lshr i128 %prod, 64 |
| %p = trunc i128 %prod.hi to i64 |
| %p1 = getelementptr inbounds i64, ptr %x, i64 1 |
| %qv = load i64, ptr %p1, align 8 |
| %q = mul i64 %qv, %y |
| %sum = add i64 %q, %p |
| ret i64 %sum |
| } |