; 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 }