blob: 6815a4d178f22a1b07285195c84141e40ec35a43 [file]
; 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
}