CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
859 lines
31 KiB
LLVM
859 lines
31 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: opt < %s -passes=aggressive-instcombine,instcombine -S | FileCheck %s
|
|
|
|
; https://alive2.llvm.org/ce/z/MSo5S_
|
|
define i64 @umulh_variant(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i64 [[Y]] to i128
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i64 [[X]] to i128
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw i128 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i128 [[TMP3]], 64
|
|
; CHECK-NEXT: [[TMP5:%.*]] = trunc nuw i128 [[TMP4]] to i64
|
|
; CHECK-NEXT: ret i64 [[TMP5]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
define i32 @umulh_variant_i32(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: define i32 @umulh_variant_i32(
|
|
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[Y]] to i64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[X]] to i64
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw i64 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i64 [[TMP3]], 32
|
|
; CHECK-NEXT: [[HW64:%.*]] = trunc nuw i64 [[TMP4]] to i32
|
|
; CHECK-NEXT: ret i32 [[HW64]]
|
|
;
|
|
%x_lo = and i32 %x, u0xffff
|
|
%y_lo = and i32 %y, u0xffff
|
|
%x_hi = lshr i32 %x, 16
|
|
%y_hi = lshr i32 %y, 16
|
|
|
|
%t0 = mul nuw i32 %y_lo, %x_lo
|
|
%t1 = mul nuw i32 %y_lo, %x_hi
|
|
%t2 = mul nuw i32 %y_hi, %x_lo
|
|
%t3 = mul nuw i32 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i32 %t0, 16
|
|
|
|
%u0 = add nuw i32 %t0_hi, %t1
|
|
%u0_lo = and i32 %u0, u0xffff
|
|
%u0_hi = lshr i32 %u0, 16
|
|
%u1 = add nuw i32 %u0_lo, %t2
|
|
%u1_hi = lshr i32 %u1, 16
|
|
%u2 = add nuw i32 %u0_hi, %t3
|
|
%hw64 = add nuw i32 %u2, %u1_hi
|
|
ret i32 %hw64
|
|
}
|
|
|
|
define <2 x i32> @umulh_variant_v2i32(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: define <2 x i32> @umulh_variant_v2i32(
|
|
; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i32> [[Y]] to <2 x i64>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[X]] to <2 x i64>
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw <2 x i64> [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr <2 x i64> [[TMP3]], splat (i64 32)
|
|
; CHECK-NEXT: [[HW64:%.*]] = trunc nuw <2 x i64> [[TMP4]] to <2 x i32>
|
|
; CHECK-NEXT: ret <2 x i32> [[HW64]]
|
|
;
|
|
%x_lo = and <2 x i32> %x, <i32 u0xffff, i32 u0xffff>
|
|
%y_lo = and <2 x i32> %y, <i32 u0xffff, i32 u0xffff>
|
|
%x_hi = lshr <2 x i32> %x, <i32 16, i32 16>
|
|
%y_hi = lshr <2 x i32> %y, <i32 16, i32 16>
|
|
|
|
%t0 = mul nuw <2 x i32> %y_lo, %x_lo
|
|
%t1 = mul nuw <2 x i32> %y_lo, %x_hi
|
|
%t2 = mul nuw <2 x i32> %y_hi, %x_lo
|
|
%t3 = mul nuw <2 x i32> %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr <2 x i32> %t0, <i32 16, i32 16>
|
|
|
|
%u0 = add nuw <2 x i32> %t0_hi, %t1
|
|
%u0_lo = and <2 x i32> %u0, <i32 u0xffff, i32 u0xffff>
|
|
%u0_hi = lshr <2 x i32> %u0, <i32 16, i32 16>
|
|
%u1 = add nuw <2 x i32> %u0_lo, %t2
|
|
%u1_hi = lshr <2 x i32> %u1, <i32 16, i32 16>
|
|
%u2 = add nuw <2 x i32> %u0_hi, %t3
|
|
%hw64 = add nuw <2 x i32> %u2, %u1_hi
|
|
ret <2 x i32> %hw64
|
|
}
|
|
|
|
define i128 @umulh_variant_i128(i128 %x, i128 %y) {
|
|
; CHECK-LABEL: define i128 @umulh_variant_i128(
|
|
; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i128 [[Y]] to i256
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i128 [[X]] to i256
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw i256 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i256 [[TMP3]], 128
|
|
; CHECK-NEXT: [[HW64:%.*]] = trunc nuw i256 [[TMP4]] to i128
|
|
; CHECK-NEXT: ret i128 [[HW64]]
|
|
;
|
|
%x_lo = and i128 %x, u0xffffffffffffffff
|
|
%y_lo = and i128 %y, u0xffffffffffffffff
|
|
%x_hi = lshr i128 %x, 64
|
|
%y_hi = lshr i128 %y, 64
|
|
|
|
%t0 = mul nuw i128 %y_lo, %x_lo
|
|
%t1 = mul nuw i128 %y_lo, %x_hi
|
|
%t2 = mul nuw i128 %y_hi, %x_lo
|
|
%t3 = mul nuw i128 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i128 %t0, 64
|
|
|
|
%u0 = add nuw i128 %t0_hi, %t1
|
|
%u0_lo = and i128 %u0, u0xffffffffffffffff
|
|
%u0_hi = lshr i128 %u0, 64
|
|
%u1 = add nuw i128 %u0_lo, %t2
|
|
%u1_hi = lshr i128 %u1, 64
|
|
%u2 = add nuw i128 %u0_hi, %t3
|
|
%hw64 = add nuw i128 %u2, %u1_hi
|
|
ret i128 %hw64
|
|
}
|
|
|
|
define i64 @umulh_variant_commuted(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant_commuted(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i64 [[X]] to i128
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i64 [[Y]] to i128
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw i128 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i128 [[TMP3]], 64
|
|
; CHECK-NEXT: [[HW64:%.*]] = trunc nuw i128 [[TMP4]] to i64
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %x_lo, %y_lo
|
|
%t1 = mul nuw i64 %x_lo, %y_hi
|
|
%t2 = mul nuw i64 %x_hi, %y_lo
|
|
%t3 = mul nuw i64 %x_hi, %y_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t1, %t0_hi
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %t2, %u0_lo
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u1_hi, %u0_hi
|
|
%hw64 = add nuw i64 %t3, %u2
|
|
ret i64 %hw64
|
|
}
|
|
|
|
|
|
|
|
; Negative tests
|
|
|
|
define i64 @umulh_variant_notlox(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant_notlox(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967294
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967294
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967294 ; wrong imm
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
define i64 @umulh_variant_nothiy(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant_nothiy(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 16
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967295
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 16 ; wrong imm
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
define i64 @umulh_variant_notlowacc(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant_notlowacc(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967294
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967294 ; wrong imm
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
define i64 @umulh_variant_notll(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant_notll(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967295
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t3 = mul nuw i64 %y_lo, %x_lo ; swapped lolo and hihi
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t0 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
|
|
|
|
; Use checks
|
|
|
|
; 't0' can have more than one use.
|
|
define i64 @umulh_variant__mul_use__t0(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__t0(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[T0]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i64 [[Y]] to i128
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i64 [[X]] to i128
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw i128 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i128 [[TMP3]], 64
|
|
; CHECK-NEXT: [[HW64:%.*]] = trunc nuw i128 [[TMP4]] to i64
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
call void (...) @llvm.fake.use(i64 %t0)
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 't1' can have more than one use.
|
|
define i64 @umulh_variant__mul_use__t1(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__t1(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[T1]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i64 [[Y]] to i128
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i64 [[X]] to i128
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw i128 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i128 [[TMP3]], 64
|
|
; CHECK-NEXT: [[HW64:%.*]] = trunc nuw i128 [[TMP4]] to i64
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
call void (...) @llvm.fake.use(i64 %t1)
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 't2' can have more than one use.
|
|
define i64 @umulh_variant__mul_use__t2(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__t2(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[T2]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i64 [[Y]] to i128
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i64 [[X]] to i128
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw i128 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i128 [[TMP3]], 64
|
|
; CHECK-NEXT: [[HW64:%.*]] = trunc nuw i128 [[TMP4]] to i64
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
call void (...) @llvm.fake.use(i64 %t2)
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 't3' must have single use.
|
|
define i64 @umulh_variant__mul_use__t3(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__t3(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[T3]])
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967295
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
call void (...) @llvm.fake.use(i64 %t3)
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 't0_hi' must have single use.
|
|
define i64 @umulh_variant__mul_use__t0_hi(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__t0_hi(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[T0_HI]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i64 [[Y]] to i128
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i64 [[X]] to i128
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul nuw i128 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i128 [[TMP3]], 64
|
|
; CHECK-NEXT: [[HW64:%.*]] = trunc nuw i128 [[TMP4]] to i64
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
call void (...) @llvm.fake.use(i64 %t0_hi)
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 'u0' must have single use.
|
|
define i64 @umulh_variant__mul_use__u0(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__u0(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[U0]])
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967295
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
call void (...) @llvm.fake.use(i64 %u0)
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 'u0_lo' must have single use.
|
|
define i64 @umulh_variant__mul_use__u0_lo(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__u0_lo(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967295
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[U0_LO]])
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
call void (...) @llvm.fake.use(i64 %u0_lo)
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 'u0_hi' must have single use.
|
|
define i64 @umulh_variant__mul_use__u0_hi(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__u0_hi(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967295
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[U0_HI]])
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
call void (...) @llvm.fake.use(i64 %u0_hi)
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 'u1' must have single use.
|
|
define i64 @umulh_variant__mul_use__u1(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__u1(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967295
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[U1]])
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
call void (...) @llvm.fake.use(i64 %u1)
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 'u1_hi' must have single use.
|
|
define i64 @umulh_variant__mul_use__u1_hi(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__u1_hi(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[T0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[T0_HI:%.*]] = lshr i64 [[T0]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = add nuw i64 [[T0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U0]], 4294967295
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[U1_HI]])
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U0_HI]], [[T3]]
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
call void (...) @llvm.fake.use(i64 %u1_hi)
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
; 'u2' must have single use.
|
|
define i64 @umulh_variant__mul_use__u2(i64 %x, i64 %y) {
|
|
; CHECK-LABEL: define i64 @umulh_variant__mul_use__u2(
|
|
; CHECK-SAME: i64 [[X:%.*]], i64 [[Y:%.*]]) {
|
|
; CHECK-NEXT: [[X_LO:%.*]] = and i64 [[X]], 4294967295
|
|
; CHECK-NEXT: [[Y_LO:%.*]] = and i64 [[Y]], 4294967295
|
|
; CHECK-NEXT: [[X_HI:%.*]] = lshr i64 [[X]], 32
|
|
; CHECK-NEXT: [[Y_HI:%.*]] = lshr i64 [[Y]], 32
|
|
; CHECK-NEXT: [[U0:%.*]] = mul nuw i64 [[Y_LO]], [[X_LO]]
|
|
; CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[Y_LO]], [[X_HI]]
|
|
; CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[Y_HI]], [[X_LO]]
|
|
; CHECK-NEXT: [[T3:%.*]] = mul nuw i64 [[Y_HI]], [[X_HI]]
|
|
; CHECK-NEXT: [[U0_HI:%.*]] = lshr i64 [[U0]], 32
|
|
; CHECK-NEXT: [[U1:%.*]] = add nuw i64 [[U0_HI]], [[T1]]
|
|
; CHECK-NEXT: [[U0_LO:%.*]] = and i64 [[U1]], 4294967295
|
|
; CHECK-NEXT: [[U1_HI:%.*]] = lshr i64 [[U1]], 32
|
|
; CHECK-NEXT: [[U3:%.*]] = add nuw i64 [[U0_LO]], [[T2]]
|
|
; CHECK-NEXT: [[U1_HI1:%.*]] = lshr i64 [[U3]], 32
|
|
; CHECK-NEXT: [[U2:%.*]] = add nuw i64 [[U1_HI]], [[T3]]
|
|
; CHECK-NEXT: call void (...) @llvm.fake.use(i64 [[U2]])
|
|
; CHECK-NEXT: [[HW64:%.*]] = add nuw i64 [[U2]], [[U1_HI1]]
|
|
; CHECK-NEXT: ret i64 [[HW64]]
|
|
;
|
|
%x_lo = and i64 %x, 4294967295
|
|
%y_lo = and i64 %y, 4294967295
|
|
%x_hi = lshr i64 %x, 32
|
|
%y_hi = lshr i64 %y, 32
|
|
|
|
%t0 = mul nuw i64 %y_lo, %x_lo
|
|
%t1 = mul nuw i64 %y_lo, %x_hi
|
|
%t2 = mul nuw i64 %y_hi, %x_lo
|
|
%t3 = mul nuw i64 %y_hi, %x_hi
|
|
|
|
%t0_hi = lshr i64 %t0, 32
|
|
|
|
%u0 = add nuw i64 %t0_hi, %t1
|
|
%u0_lo = and i64 %u0, 4294967295
|
|
%u0_hi = lshr i64 %u0, 32
|
|
%u1 = add nuw i64 %u0_lo, %t2
|
|
%u1_hi = lshr i64 %u1, 32
|
|
%u2 = add nuw i64 %u0_hi, %t3
|
|
call void (...) @llvm.fake.use(i64 %u2)
|
|
%hw64 = add nuw i64 %u2, %u1_hi
|
|
ret i64 %hw64
|
|
}
|
|
|
|
define [2 x i64] @XXH_mult64to128(i64 noundef %lhs, i64 noundef %rhs) {
|
|
; CHECK-LABEL: define [2 x i64] @XXH_mult64to128(
|
|
; CHECK-SAME: i64 noundef [[LHS:%.*]], i64 noundef [[RHS:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*:]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = zext i64 [[RHS]] to i128
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i64 [[LHS]] to i128
|
|
; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i128 [[TMP0]], [[TMP1]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = lshr i128 [[TMP2]], 64
|
|
; CHECK-NEXT: [[ADD16:%.*]] = trunc nuw i128 [[TMP3]] to i64
|
|
; CHECK-NEXT: [[SHR102:%.*]] = mul i64 [[LHS]], [[RHS]]
|
|
; CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue [2 x i64] poison, i64 [[SHR102]], 0
|
|
; CHECK-NEXT: [[DOTFCA_1_INSERT:%.*]] = insertvalue [2 x i64] [[DOTFCA_0_INSERT]], i64 [[ADD16]], 1
|
|
; CHECK-NEXT: ret [2 x i64] [[DOTFCA_1_INSERT]]
|
|
;
|
|
entry:
|
|
%and = and i64 %lhs, 4294967295
|
|
%and1 = and i64 %rhs, 4294967295
|
|
%mul.i = mul nuw i64 %and1, %and
|
|
%shr = lshr i64 %lhs, 32
|
|
%mul.i27 = mul nuw i64 %and1, %shr
|
|
%shr5 = lshr i64 %rhs, 32
|
|
%mul.i28 = mul nuw i64 %shr5, %and
|
|
%mul.i29 = mul nuw i64 %shr5, %shr
|
|
%shr10 = lshr i64 %mul.i, 32
|
|
%and11 = and i64 %mul.i27, 4294967295
|
|
%add = add nuw i64 %and11, %mul.i28
|
|
%add12 = add nuw i64 %add, %shr10
|
|
%shr13 = lshr i64 %mul.i27, 32
|
|
%shr14 = lshr i64 %add12, 32
|
|
%add15 = add nuw i64 %shr13, %mul.i29
|
|
%add16 = add nuw i64 %add15, %shr14
|
|
%shl = shl i64 %add12, 32
|
|
%and17 = and i64 %mul.i, 4294967295
|
|
%or = or disjoint i64 %shl, %and17
|
|
%.fca.0.insert = insertvalue [2 x i64] poison, i64 %or, 0
|
|
%.fca.1.insert = insertvalue [2 x i64] %.fca.0.insert, i64 %add16, 1
|
|
ret [2 x i64] %.fca.1.insert
|
|
}
|
|
|