[llvm] 770d5e8 - [tests] precommit tests for D136015

via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 23 06:41:04 PDT 2022


Author: zhongyunde
Date: 2022-10-23T21:36:43+08:00
New Revision: 770d5e89ba899d0306c35aa7f6f19a4736d8005b

URL: https://github.com/llvm/llvm-project/commit/770d5e89ba899d0306c35aa7f6f19a4736d8005b
DIFF: https://github.com/llvm/llvm-project/commit/770d5e89ba899d0306c35aa7f6f19a4736d8005b.diff

LOG: [tests] precommit tests for D136015

Address the commit https://reviews.llvm.org/D136015#inline-1313479

Reviewed By: spatel
Differential Revision: https://reviews.llvm.org/D136340

Added: 
    llvm/test/Transforms/InstCombine/mul_fold.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/InstCombine/mul_fold.ll b/llvm/test/Transforms/InstCombine/mul_fold.ll
new file mode 100644
index 0000000000000..013435a3c57dd
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/mul_fold.ll
@@ -0,0 +1,870 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+declare i8 @use8(i8)
+declare i16 @use16(i16)
+declare i32 @use32(i32)
+declare i64 @use64(i64)
+declare i128 @use128(i128)
+declare i130 @use130(i130)
+declare <2 x i8> @use_v2i8(<2 x i8>)
+
+; The following 16 cases are used for cover the commuted operand ADD and MUL
+; with extra uses to more of these tests to exercise those cases.
+;  The 
diff erent _Ax suffix hints the variety of combinations MUL
+;  The 
diff erent _Bx suffix hints the variety of combinations ADD
+;  4 tests that use in0/in1 with 
diff erent commutes
+define i8 @mul8_low_A0_B0(i8 %in0, i8 %in1) {
+; CHECK-LABEL: @mul8_low_A0_B0(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i8 [[IN0:%.*]], 15
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i8 [[IN0]], 4
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i8 [[IN1:%.*]], 15
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i8 [[IN1]], 4
+; CHECK-NEXT:    [[M10:%.*]] = mul i8 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i8 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i8 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i8 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[ADDC]], 4
+; CHECK-NEXT:    [[RETLO:%.*]] = add i8 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i8 [[RETLO]]
+;
+  %In0Lo = and i8 %in0, 15
+  %In0Hi = lshr i8 %in0, 4
+  %In1Lo = and i8 %in1, 15
+  %In1Hi = lshr i8 %in1, 4
+  %m10 = mul i8 %In1Hi, %In0Lo
+  %m01 = mul i8 %In1Lo, %In0Hi
+  %m00 = mul i8 %In1Lo, %In0Lo
+  %addc = add i8 %m10, %m01
+  %shl = shl i8 %addc, 4
+  %retLo = add i8 %shl, %m00
+  ret i8 %retLo
+}
+
+define i8 @mul8_low_A0_B1(i8 %in0, i8 %in1) {
+; CHECK-LABEL: @mul8_low_A0_B1(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i8 [[IN0:%.*]], 15
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i8 [[IN0]], 4
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i8 [[IN1:%.*]], 15
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i8 [[IN1]], 4
+; CHECK-NEXT:    [[M10:%.*]] = mul i8 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i8 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i8 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i8 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[ADDC]], 4
+; CHECK-NEXT:    [[RETLO:%.*]] = add i8 [[M00]], [[SHL]]
+; CHECK-NEXT:    ret i8 [[RETLO]]
+;
+  %In0Lo = and i8 %in0, 15
+  %In0Hi = lshr i8 %in0, 4
+  %In1Lo = and i8 %in1, 15
+  %In1Hi = lshr i8 %in1, 4
+  %m10 = mul i8 %In1Hi, %In0Lo
+  %m01 = mul i8 %In1Lo, %In0Hi
+  %m00 = mul i8 %In1Lo, %In0Lo
+  %addc = add i8 %m10, %m01
+  %shl = shl i8 %addc, 4
+  %retLo = add i8 %m00, %shl
+  ret i8 %retLo
+}
+
+define i8 @mul8_low_A0_B2(i8 %in0, i8 %in1) {
+; CHECK-LABEL: @mul8_low_A0_B2(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i8 [[IN0:%.*]], 15
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i8 [[IN0]], 4
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i8 [[IN1:%.*]], 15
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i8 [[IN1]], 4
+; CHECK-NEXT:    [[M10:%.*]] = mul i8 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i8 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i8 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i8 [[M01]], [[M10]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[ADDC]], 4
+; CHECK-NEXT:    [[RETLO:%.*]] = add i8 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i8 [[RETLO]]
+;
+  %In0Lo = and i8 %in0, 15
+  %In0Hi = lshr i8 %in0, 4
+  %In1Lo = and i8 %in1, 15
+  %In1Hi = lshr i8 %in1, 4
+  %m10 = mul i8 %In1Hi, %In0Lo
+  %m01 = mul i8 %In1Lo, %In0Hi
+  %m00 = mul i8 %In1Lo, %In0Lo
+  %addc = add i8 %m01, %m10
+  %shl = shl i8 %addc, 4
+  %retLo = add i8 %shl, %m00
+  ret i8 %retLo
+}
+
+define i8 @mul8_low_A0_B3(i8 %in0, i8 %in1) {
+; CHECK-LABEL: @mul8_low_A0_B3(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i8 [[IN0:%.*]], 15
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i8 [[IN0]], 4
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i8 [[IN1:%.*]], 15
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i8 [[IN1]], 4
+; CHECK-NEXT:    [[M10:%.*]] = mul i8 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i8 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i8 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i8 [[M01]], [[M10]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[ADDC]], 4
+; CHECK-NEXT:    [[RETLO:%.*]] = add i8 [[M00]], [[SHL]]
+; CHECK-NEXT:    ret i8 [[RETLO]]
+;
+  %In0Lo = and i8 %in0, 15
+  %In0Hi = lshr i8 %in0, 4
+  %In1Lo = and i8 %in1, 15
+  %In1Hi = lshr i8 %in1, 4
+  %m10 = mul i8 %In1Hi, %In0Lo
+  %m01 = mul i8 %In1Lo, %In0Hi
+  %m00 = mul i8 %In1Lo, %In0Lo
+  %addc = add i8 %m01, %m10
+  %shl = shl i8 %addc, 4
+  %retLo = add i8 %m00, %shl
+  ret i8 %retLo
+}
+
+; 4 tests that use In0Lo/In1Lo with 
diff erent commutes
+define i16 @mul16_low_A1_B0(i16 %in0, i16 %in1) {
+; CHECK-LABEL: @mul16_low_A1_B0(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i16 [[IN0]], 8
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i16 [[IN1]], 8
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i16 [[IN0LO]], [[IN1HI]]
+; CHECK-NEXT:    call void @use16(i16 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i16 [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    call void @use16(i16 [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i16 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i16 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ADDC]], 8
+; CHECK-NEXT:    [[RETLO:%.*]] = add i16 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i16 [[RETLO]]
+;
+  %In0Lo = and i16 %in0, 255
+  %In0Hi = lshr i16 %in0, 8
+  %In1Lo = and i16 %in1, 255
+  %In1Hi = lshr i16 %in1, 8
+  %m10 = mul i16 %In0Lo, %In1Hi
+  call void @use16(i16 %m10)
+  %m01 = mul i16 %In1Lo, %In0Hi
+  call void @use16(i16 %m01)
+  %m00 = mul i16 %In1Lo, %In0Lo
+  %addc = add i16 %m10, %m01
+  %shl = shl i16 %addc, 8
+  %retLo = add i16 %shl, %m00
+  ret i16 %retLo
+}
+
+define i16 @mul16_low_A1_B1(i16 %in0, i16 %in1) {
+; CHECK-LABEL: @mul16_low_A1_B1(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i16 [[IN0]], 8
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i16 [[IN1]], 8
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i16 [[IN0LO]], [[IN1HI]]
+; CHECK-NEXT:    call void @use16(i16 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i16 [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    call void @use16(i16 [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i16 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i16 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ADDC]], 8
+; CHECK-NEXT:    [[RETLO:%.*]] = add i16 [[M00]], [[SHL]]
+; CHECK-NEXT:    ret i16 [[RETLO]]
+;
+  %In0Lo = and i16 %in0, 255
+  %In0Hi = lshr i16 %in0, 8
+  %In1Lo = and i16 %in1, 255
+  %In1Hi = lshr i16 %in1, 8
+  %m10 = mul i16 %In0Lo, %In1Hi
+  call void @use16(i16 %m10)
+  %m01 = mul i16 %In1Lo, %In0Hi
+  call void @use16(i16 %m01)
+  %m00 = mul i16 %In1Lo, %In0Lo
+  %addc = add i16 %m10, %m01
+  %shl = shl i16 %addc, 8
+  %retLo = add i16 %m00, %shl
+  ret i16 %retLo
+}
+
+define i16 @mul16_low_A1_B2(i16 %in0, i16 %in1) {
+; CHECK-LABEL: @mul16_low_A1_B2(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i16 [[IN0]], 8
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i16 [[IN1]], 8
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i16 [[IN0LO]], [[IN1HI]]
+; CHECK-NEXT:    call void @use16(i16 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i16 [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    call void @use16(i16 [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i16 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i16 [[M01]], [[M10]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ADDC]], 8
+; CHECK-NEXT:    [[RETLO:%.*]] = add i16 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i16 [[RETLO]]
+;
+  %In0Lo = and i16 %in0, 255
+  %In0Hi = lshr i16 %in0, 8
+  %In1Lo = and i16 %in1, 255
+  %In1Hi = lshr i16 %in1, 8
+  %m10 = mul i16 %In0Lo, %In1Hi
+  call void @use16(i16 %m10)
+  %m01 = mul i16 %In1Lo, %In0Hi
+  call void @use16(i16 %m01)
+  %m00 = mul i16 %In1Lo, %In0Lo
+  %addc = add i16 %m01, %m10
+  %shl = shl i16 %addc, 8
+  %retLo = add i16 %shl, %m00
+  ret i16 %retLo
+}
+
+define i16 @mul16_low_A1_B3(i16 %in0, i16 %in1) {
+; CHECK-LABEL: @mul16_low_A1_B3(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i16 [[IN0]], 8
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i16 [[IN1]], 8
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i16 [[IN0LO]], [[IN1HI]]
+; CHECK-NEXT:    call void @use16(i16 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i16 [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    call void @use16(i16 [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i16 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i16 [[M01]], [[M10]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ADDC]], 8
+; CHECK-NEXT:    [[RETLO:%.*]] = add i16 [[M00]], [[SHL]]
+; CHECK-NEXT:    ret i16 [[RETLO]]
+;
+  %In0Lo = and i16 %in0, 255
+  %In0Hi = lshr i16 %in0, 8
+  %In1Lo = and i16 %in1, 255
+  %In1Hi = lshr i16 %in1, 8
+  %m10 = mul i16 %In0Lo, %In1Hi
+  call void @use16(i16 %m10)
+  %m01 = mul i16 %In1Lo, %In0Hi
+  call void @use16(i16 %m01)
+  %m00 = mul i16 %In1Lo, %In0Lo
+  %addc = add i16 %m01, %m10
+  %shl = shl i16 %addc, 8
+  %retLo = add i16 %m00, %shl
+  ret i16 %retLo
+}
+
+; 4 tests that use In0Lo/in1 with 
diff erent commutes
+define i32 @mul32_low_A2_B0(i32 %in0, i32 %in1) {
+; CHECK-LABEL: @mul32_low_A2_B0(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i32 [[IN0]], 16
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i32 [[IN1:%.*]], 65535
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i32 [[IN1]], 16
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    call void @use32(i32 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul i32 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i32 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i32 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[ADDC]], 16
+; CHECK-NEXT:    [[RETLO:%.*]] = add i32 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i32 [[RETLO]]
+;
+  %In0Lo = and i32 %in0, 65535
+  %In0Hi = lshr i32 %in0, 16
+  %In1Lo = and i32 %in1, 65535
+  %In1Hi = lshr i32 %in1, 16
+  %m10 = mul i32 %In1Hi, %In0Lo
+  call void @use32(i32 %m10)
+  %m01 = mul i32 %In0Hi, %In1Lo
+  %m00 = mul i32 %In1Lo, %In0Lo
+  %addc = add i32 %m10, %m01
+  %shl = shl i32 %addc, 16
+  %retLo = add i32 %shl, %m00
+  ret i32 %retLo
+}
+
+define i32 @mul32_low_A2_B1(i32 %in0, i32 %in1) {
+; CHECK-LABEL: @mul32_low_A2_B1(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i32 [[IN0]], 16
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i32 [[IN1:%.*]], 65535
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i32 [[IN1]], 16
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    call void @use32(i32 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul i32 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i32 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i32 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[ADDC]], 16
+; CHECK-NEXT:    [[RETLO:%.*]] = add i32 [[M00]], [[SHL]]
+; CHECK-NEXT:    ret i32 [[RETLO]]
+;
+  %In0Lo = and i32 %in0, 65535
+  %In0Hi = lshr i32 %in0, 16
+  %In1Lo = and i32 %in1, 65535
+  %In1Hi = lshr i32 %in1, 16
+  %m10 = mul i32 %In1Hi, %In0Lo
+  call void @use32(i32 %m10)
+  %m01 = mul i32 %In0Hi, %In1Lo
+  %m00 = mul i32 %In1Lo, %In0Lo
+  %addc = add i32 %m10, %m01
+  %shl = shl i32 %addc, 16
+  %retLo = add i32 %m00, %shl
+  ret i32 %retLo
+}
+
+define i32 @mul32_low_A2_B2(i32 %in0, i32 %in1) {
+; CHECK-LABEL: @mul32_low_A2_B2(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i32 [[IN0]], 16
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i32 [[IN1:%.*]], 65535
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i32 [[IN1]], 16
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    call void @use32(i32 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul i32 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i32 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i32 [[M01]], [[M10]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[ADDC]], 16
+; CHECK-NEXT:    [[RETLO:%.*]] = add i32 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i32 [[RETLO]]
+;
+  %In0Lo = and i32 %in0, 65535
+  %In0Hi = lshr i32 %in0, 16
+  %In1Lo = and i32 %in1, 65535
+  %In1Hi = lshr i32 %in1, 16
+  %m10 = mul i32 %In1Hi, %In0Lo
+  call void @use32(i32 %m10)
+  %m01 = mul i32 %In0Hi, %In1Lo
+  %m00 = mul i32 %In1Lo, %In0Lo
+  %addc = add i32 %m01, %m10
+  %shl = shl i32 %addc, 16
+  %retLo = add i32 %shl, %m00
+  ret i32 %retLo
+}
+
+define i32 @mul32_low_A2_B3(i32 %in0, i32 %in1) {
+; CHECK-LABEL: @mul32_low_A2_B3(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i32 [[IN0]], 16
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i32 [[IN1:%.*]], 65535
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i32 [[IN1]], 16
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    call void @use32(i32 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul i32 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i32 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i32 [[M01]], [[M10]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[ADDC]], 16
+; CHECK-NEXT:    [[RETLO:%.*]] = add i32 [[M00]], [[SHL]]
+; CHECK-NEXT:    ret i32 [[RETLO]]
+;
+  %In0Lo = and i32 %in0, 65535
+  %In0Hi = lshr i32 %in0, 16
+  %In1Lo = and i32 %in1, 65535
+  %In1Hi = lshr i32 %in1, 16
+  %m10 = mul i32 %In1Hi, %In0Lo
+  call void @use32(i32 %m10)
+  %m01 = mul i32 %In0Hi, %In1Lo
+  %m00 = mul i32 %In1Lo, %In0Lo
+  %addc = add i32 %m01, %m10
+  %shl = shl i32 %addc, 16
+  %retLo = add i32 %m00, %shl
+  ret i32 %retLo
+}
+
+; 4 tests that use in0/In1Lo with 
diff erent commutes
+define i64 @mul64_low_A3_B0(i64 %in0, i64 %in1) {
+; CHECK-LABEL: @mul64_low_A3_B0(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i64 [[IN0:%.*]], 4294967295
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i64 [[IN0]], 32
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i64 [[IN1]], 32
+; CHECK-NEXT:    [[M10:%.*]] = mul i64 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i64 [[IN0HI]], [[IN1LO]]
+; CHECK-NEXT:    call void @use64(i64 [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i64 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i64 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[ADDC]], 32
+; CHECK-NEXT:    [[RETLO:%.*]] = add i64 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i64 [[RETLO]]
+;
+  %In0Lo = and i64 %in0, 4294967295
+  %In0Hi = lshr i64 %in0, 32
+  %In1Lo = and i64 %in1, 4294967295
+  %In1Hi = lshr i64 %in1, 32
+  %m10 = mul i64 %In0Lo, %In1Hi
+  %m01 = mul i64 %In0Hi, %In1Lo
+  call void @use64(i64 %m01)
+  %m00 = mul i64 %In1Lo, %In0Lo
+  %addc = add i64 %m10, %m01
+  %shl = shl i64 %addc, 32
+  %retLo = add i64 %shl, %m00
+  ret i64 %retLo
+}
+
+define i64 @mul64_low_A3_B1(i64 %in0, i64 %in1) {
+; CHECK-LABEL: @mul64_low_A3_B1(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i64 [[IN0:%.*]], 4294967295
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i64 [[IN0]], 32
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i64 [[IN1]], 32
+; CHECK-NEXT:    [[M10:%.*]] = mul i64 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i64 [[IN0HI]], [[IN1LO]]
+; CHECK-NEXT:    call void @use64(i64 [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i64 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i64 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[ADDC]], 32
+; CHECK-NEXT:    [[RETLO:%.*]] = add i64 [[M00]], [[SHL]]
+; CHECK-NEXT:    ret i64 [[RETLO]]
+;
+  %In0Lo = and i64 %in0, 4294967295
+  %In0Hi = lshr i64 %in0, 32
+  %In1Lo = and i64 %in1, 4294967295
+  %In1Hi = lshr i64 %in1, 32
+  %m10 = mul i64 %In0Lo, %In1Hi
+  %m01 = mul i64 %In0Hi, %In1Lo
+  call void @use64(i64 %m01)
+  %m00 = mul i64 %In1Lo, %In0Lo
+  %addc = add i64 %m10, %m01
+  %shl = shl i64 %addc, 32
+  %retLo = add i64 %m00, %shl
+  ret i64 %retLo
+}
+
+define i64 @mul64_low_A3_B2(i64 %in0, i64 %in1) {
+; CHECK-LABEL: @mul64_low_A3_B2(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i64 [[IN0:%.*]], 4294967295
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i64 [[IN0]], 32
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i64 [[IN1]], 32
+; CHECK-NEXT:    [[M10:%.*]] = mul i64 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i64 [[IN0HI]], [[IN1LO]]
+; CHECK-NEXT:    call void @use64(i64 [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i64 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i64 [[M01]], [[M10]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[ADDC]], 32
+; CHECK-NEXT:    [[RETLO:%.*]] = add i64 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i64 [[RETLO]]
+;
+  %In0Lo = and i64 %in0, 4294967295
+  %In0Hi = lshr i64 %in0, 32
+  %In1Lo = and i64 %in1, 4294967295
+  %In1Hi = lshr i64 %in1, 32
+  %m10 = mul i64 %In0Lo, %In1Hi
+  %m01 = mul i64 %In0Hi, %In1Lo
+  call void @use64(i64 %m01)
+  %m00 = mul i64 %In1Lo, %In0Lo
+  %addc = add i64 %m01, %m10
+  %shl = shl i64 %addc, 32
+  %retLo = add i64 %shl, %m00
+  ret i64 %retLo
+}
+
+define i64 @mul64_low_A3_B3(i64 %in0, i64 %in1) {
+; CHECK-LABEL: @mul64_low_A3_B3(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i64 [[IN0:%.*]], 4294967295
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i64 [[IN0]], 32
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i64 [[IN1]], 32
+; CHECK-NEXT:    [[M10:%.*]] = mul i64 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i64 [[IN0HI]], [[IN1LO]]
+; CHECK-NEXT:    call void @use64(i64 [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i64 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i64 [[M01]], [[M10]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[ADDC]], 32
+; CHECK-NEXT:    [[RETLO:%.*]] = add i64 [[M00]], [[SHL]]
+; CHECK-NEXT:    ret i64 [[RETLO]]
+;
+  %In0Lo = and i64 %in0, 4294967295
+  %In0Hi = lshr i64 %in0, 32
+  %In1Lo = and i64 %in1, 4294967295
+  %In1Hi = lshr i64 %in1, 32
+  %m10 = mul i64 %In0Lo, %In1Hi
+  %m01 = mul i64 %In0Hi, %In1Lo
+  call void @use64(i64 %m01)
+  %m00 = mul i64 %In1Lo, %In0Lo
+  %addc = add i64 %m01, %m10
+  %shl = shl i64 %addc, 32
+  %retLo = add i64 %m00, %shl
+  ret i64 %retLo
+}
+
+define i32 @mul32_low_one_extra_user(i32 %in0, i32 %in1) {
+; CHECK-LABEL: @mul32_low_one_extra_user(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i32 [[IN0]], 16
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i32 [[IN1:%.*]], 65535
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i32 [[IN1]], 16
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i32 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i32 [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i32 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i32 [[M10]], [[M01]]
+; CHECK-NEXT:    call void @use32(i32 [[ADDC]])
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[ADDC]], 16
+; CHECK-NEXT:    [[RETLO:%.*]] = add i32 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i32 [[RETLO]]
+;
+  %In0Lo = and i32 %in0, 65535
+  %In0Hi = lshr i32 %in0, 16
+  %In1Lo = and i32 %in1, 65535
+  %In1Hi = lshr i32 %in1, 16
+  %m10 = mul i32 %In1Hi, %In0Lo
+  %m01 = mul i32 %In1Lo, %In0Hi
+  %m00 = mul i32 %In1Lo, %In0Lo
+  %addc = add i32 %m10, %m01
+  call void @use32(i32 %addc)
+  %shl = shl i32 %addc, 16
+  %retLo = add i32 %shl, %m00
+  ret i32 %retLo
+}
+
+; The following are variety types of target cases
+; https://alive2.llvm.org/ce/z/2BqKLt
+define i8 @mul8_low(i8 %in0, i8 %in1) {
+; CHECK-LABEL: @mul8_low(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i8 [[IN0:%.*]], 15
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i8 [[IN0]], 4
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i8 [[IN1:%.*]], 15
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i8 [[IN1]], 4
+; CHECK-NEXT:    [[M10:%.*]] = mul i8 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i8 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i8 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i8 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[ADDC]], 4
+; CHECK-NEXT:    [[RETLO:%.*]] = add i8 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i8 [[RETLO]]
+;
+  %In0Lo = and i8 %in0, 15
+  %In0Hi = lshr i8 %in0, 4
+  %In1Lo = and i8 %in1, 15
+  %In1Hi = lshr i8 %in1, 4
+  %m10 = mul i8 %In1Hi, %In0Lo
+  %m01 = mul i8 %In1Lo, %In0Hi
+  %m00 = mul i8 %In1Lo, %In0Lo
+  %addc = add i8 %m10, %m01
+  %shl = shl i8 %addc, 4
+  %retLo = add i8 %shl, %m00
+  ret i8 %retLo
+}
+
+define i16 @mul16_low(i16 %in0, i16 %in1) {
+; CHECK-LABEL: @mul16_low(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 255
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i16 [[IN0]], 8
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 255
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i16 [[IN1]], 8
+; CHECK-NEXT:    [[M10:%.*]] = mul i16 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i16 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i16 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i16 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ADDC]], 8
+; CHECK-NEXT:    [[RETLO:%.*]] = add i16 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i16 [[RETLO]]
+;
+  %In0Lo = and i16 %in0, 255
+  %In0Hi = lshr i16 %in0, 8
+  %In1Lo = and i16 %in1, 255
+  %In1Hi = lshr i16 %in1, 8
+  %m10 = mul i16 %In1Hi, %In0Lo
+  %m01 = mul i16 %In1Lo, %In0Hi
+  %m00 = mul i16 %In1Lo, %In0Lo
+  %addc = add i16 %m10, %m01
+  %shl = shl i16 %addc, 8
+  %retLo = add i16 %shl, %m00
+  ret i16 %retLo
+}
+
+define i32 @mul32_low(i32 %in0, i32 %in1) {
+; CHECK-LABEL: @mul32_low(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i32 [[IN0:%.*]], 65535
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i32 [[IN0]], 16
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i32 [[IN1:%.*]], 65535
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i32 [[IN1]], 16
+; CHECK-NEXT:    [[M10:%.*]] = mul i32 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i32 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i32 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i32 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[ADDC]], 16
+; CHECK-NEXT:    [[RETLO:%.*]] = add i32 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i32 [[RETLO]]
+;
+  %In0Lo = and i32 %in0, 65535
+  %In0Hi = lshr i32 %in0, 16
+  %In1Lo = and i32 %in1, 65535
+  %In1Hi = lshr i32 %in1, 16
+  %m10 = mul i32 %In1Hi, %In0Lo
+  %m01 = mul i32 %In1Lo, %In0Hi
+  %m00 = mul i32 %In1Lo, %In0Lo
+  %addc = add i32 %m10, %m01
+  %shl = shl i32 %addc, 16
+  %retLo = add i32 %shl, %m00
+  ret i32 %retLo
+}
+
+define i64 @mul64_low(i64 %in0, i64 %in1) {
+; CHECK-LABEL: @mul64_low(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i64 [[IN0:%.*]], 4294967295
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i64 [[IN0]], 32
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i64 [[IN1:%.*]], 4294967295
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i64 [[IN1]], 32
+; CHECK-NEXT:    [[M10:%.*]] = mul i64 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i64 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i64 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i64 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[ADDC]], 32
+; CHECK-NEXT:    [[RETLO:%.*]] = add i64 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i64 [[RETLO]]
+;
+  %In0Lo = and i64 %in0, 4294967295
+  %In0Hi = lshr i64 %in0, 32
+  %In1Lo = and i64 %in1, 4294967295
+  %In1Hi = lshr i64 %in1, 32
+  %m10 = mul i64 %In1Hi, %In0Lo
+  %m01 = mul i64 %In1Lo, %In0Hi
+  %m00 = mul i64 %In1Lo, %In0Lo
+  %addc = add i64 %m10, %m01
+  %shl = shl i64 %addc, 32
+  %retLo = add i64 %shl, %m00
+  ret i64 %retLo
+}
+
+define i128 @mul128_low(i128 %in0, i128 %in1) {
+; CHECK-LABEL: @mul128_low(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i128 [[IN0:%.*]], 18446744073709551615
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i128 [[IN0]], 64
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i128 [[IN1:%.*]], 18446744073709551615
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i128 [[IN1]], 64
+; CHECK-NEXT:    [[M10:%.*]] = mul i128 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i128 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i128 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i128 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i128 [[ADDC]], 64
+; CHECK-NEXT:    [[RETLO:%.*]] = add i128 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i128 [[RETLO]]
+;
+  %In0Lo = and i128 %in0, 18446744073709551615
+  %In0Hi = lshr i128 %in0, 64
+  %In1Lo = and i128 %in1, 18446744073709551615
+  %In1Hi = lshr i128 %in1, 64
+  %m10 = mul i128 %In1Hi, %In0Lo
+  %m01 = mul i128 %In1Lo, %In0Hi
+  %m00 = mul i128 %In1Lo, %In0Lo
+  %addc = add i128 %m10, %m01
+  %shl = shl i128 %addc, 64
+  %retLo = add i128 %shl, %m00
+  ret i128 %retLo
+}
+
+; TODO: Skip vector type
+define <2 x i8> @mul_v2i8_low(<2 x i8> %in0, <2 x i8> %in1) {
+; CHECK-LABEL: @mul_v2i8_low(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and <2 x i8> [[IN0:%.*]], <i8 15, i8 15>
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr <2 x i8> [[IN0]], <i8 4, i8 4>
+; CHECK-NEXT:    [[IN1LO:%.*]] = and <2 x i8> [[IN1:%.*]], <i8 15, i8 15>
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr <2 x i8> [[IN1]], <i8 4, i8 4>
+; CHECK-NEXT:    [[M10:%.*]] = mul <2 x i8> [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul <2 x i8> [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw <2 x i8> [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add <2 x i8> [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i8> [[ADDC]], <i8 4, i8 4>
+; CHECK-NEXT:    [[RETLO:%.*]] = add <2 x i8> [[SHL]], [[M00]]
+; CHECK-NEXT:    ret <2 x i8> [[RETLO]]
+;
+  %In0Lo = and <2 x i8> %in0, <i8 15, i8 15>
+  %In0Hi = lshr <2 x i8> %in0, <i8 4, i8 4>
+  %In1Lo = and <2 x i8> %in1, <i8 15, i8 15>
+  %In1Hi = lshr <2 x i8> %in1, <i8 4, i8 4>
+  %m10 = mul <2 x i8> %In1Hi, %In0Lo
+  %m01 = mul <2 x i8> %In1Lo, %In0Hi
+  %m00 = mul <2 x i8> %In1Lo, %In0Lo
+  %addc = add <2 x i8> %m10, %m01
+  %shl = shl <2 x i8> %addc, <i8 4, i8 4>
+  %retLo = add <2 x i8> %shl, %m00
+  ret <2 x i8> %retLo
+}
+
+define <2 x i8> @mul_v2i8_low_one_extra_user(<2 x i8> %in0, <2 x i8> %in1) {
+; CHECK-LABEL: @mul_v2i8_low_one_extra_user(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and <2 x i8> [[IN0:%.*]], <i8 15, i8 15>
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr <2 x i8> [[IN0]], <i8 4, i8 4>
+; CHECK-NEXT:    [[IN1LO:%.*]] = and <2 x i8> [[IN1:%.*]], <i8 15, i8 15>
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr <2 x i8> [[IN1]], <i8 4, i8 4>
+; CHECK-NEXT:    [[M10:%.*]] = mul <2 x i8> [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw <2 x i8> [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    call void @use_v2i8(<2 x i8> [[M01]])
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw <2 x i8> [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add <2 x i8> [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i8> [[ADDC]], <i8 4, i8 4>
+; CHECK-NEXT:    [[RETLO:%.*]] = add <2 x i8> [[SHL]], [[M00]]
+; CHECK-NEXT:    ret <2 x i8> [[RETLO]]
+;
+  %In0Lo = and <2 x i8> %in0, <i8 15, i8 15>
+  %In0Hi = lshr <2 x i8> %in0, <i8 4, i8 4>
+  %In1Lo = and <2 x i8> %in1, <i8 15, i8 15>
+  %In1Hi = lshr <2 x i8> %in1, <i8 4, i8 4>
+  %m10 = mul <2 x i8> %In1Hi, %In0Lo
+  %m01 = mul <2 x i8> %In1Lo, %In0Hi
+  call void @use_v2i8(<2 x i8> %m01)
+  %m00 = mul <2 x i8> %In1Lo, %In0Lo
+  %addc = add <2 x i8> %m10, %m01
+  %shl = shl <2 x i8> %addc, <i8 4, i8 4>
+  %retLo = add <2 x i8> %shl, %m00
+  ret <2 x i8> %retLo
+}
+
+; TODO: Support wide width
+define i130 @mul130_low(i130 %in0, i130 %in1) {
+; CHECK-LABEL: @mul130_low(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i130 [[IN0:%.*]], 36893488147419103231
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i130 [[IN0]], 65
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i130 [[IN1:%.*]], 36893488147419103231
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i130 [[IN1]], 65
+; CHECK-NEXT:    [[M10:%.*]] = mul i130 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i130 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i130 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i130 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i130 [[ADDC]], 65
+; CHECK-NEXT:    [[RETLO:%.*]] = add i130 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i130 [[RETLO]]
+;
+  %In0Lo = and i130 %in0, 36893488147419103231
+  %In0Hi = lshr i130 %in0, 65
+  %In1Lo = and i130 %in1, 36893488147419103231
+  %In1Hi = lshr i130 %in1, 65
+  %m10 = mul i130 %In1Hi, %In0Lo
+  %m01 = mul i130 %In1Lo, %In0Hi
+  %m00 = mul i130 %In1Lo, %In0Lo
+  %addc = add i130 %m10, %m01
+  %shl = shl i130 %addc, 65
+  %retLo = add i130 %shl, %m00
+  ret i130 %retLo
+}
+
+define i130 @mul130_low_one_extra_user(i130 %in0, i130 %in1) {
+; CHECK-LABEL: @mul130_low_one_extra_user(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i130 [[IN0:%.*]], 36893488147419103231
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i130 [[IN0]], 65
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i130 [[IN1:%.*]], 36893488147419103231
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i130 [[IN1]], 65
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i130 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    call void @use130(i130 [[M10]])
+; CHECK-NEXT:    [[M01:%.*]] = mul i130 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i130 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i130 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i130 [[ADDC]], 65
+; CHECK-NEXT:    [[RETLO:%.*]] = add i130 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i130 [[RETLO]]
+;
+  %In0Lo = and i130 %in0, 36893488147419103231
+  %In0Hi = lshr i130 %in0, 65
+  %In1Lo = and i130 %in1, 36893488147419103231
+  %In1Hi = lshr i130 %in1, 65
+  %m10 = mul i130 %In1Hi, %In0Lo
+  call void @use130(i130 %m10)
+  %m01 = mul i130 %In1Lo, %In0Hi
+  %m00 = mul i130 %In1Lo, %In0Lo
+  %addc = add i130 %m10, %m01
+  %shl = shl i130 %addc, 65
+  %retLo = add i130 %shl, %m00
+  ret i130 %retLo
+}
+
+; Negative case: Skip odd bitwidth type
+define i9 @mul9_low(i9 %in0, i9 %in1) {
+; CHECK-LABEL: @mul9_low(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i9 [[IN0:%.*]], 15
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i9 [[IN0]], 4
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i9 [[IN1:%.*]], 15
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i9 [[IN1]], 4
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw i9 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw i9 [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw nsw i9 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i9 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i9 [[ADDC]], 4
+; CHECK-NEXT:    [[RETLO:%.*]] = add i9 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i9 [[RETLO]]
+;
+  %In0Lo = and i9 %in0, 15
+  %In0Hi = lshr i9 %in0, 4
+  %In1Lo = and i9 %in1, 15
+  %In1Hi = lshr i9 %in1, 4
+  %m10 = mul i9 %In1Hi, %In0Lo
+  %m01 = mul i9 %In1Lo, %In0Hi
+  %m00 = mul i9 %In1Lo, %In0Lo
+  %addc = add i9 %m10, %m01
+  %shl = shl i9 %addc, 4
+  %retLo = add i9 %shl, %m00
+  ret i9 %retLo
+}
+
+; Negative test: Should not remote the "and", https://alive2.llvm.org/ce/z/JLmNU5
+define i64 @mul64_low_no_and(i64 %in0, i64 %in1) {
+; CHECK-LABEL: @mul64_low_no_and(
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i64 [[IN0:%.*]], 32
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i64 [[IN1:%.*]], 32
+; CHECK-NEXT:    [[M10:%.*]] = mul i64 [[IN1HI]], [[IN0]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i64 [[IN0HI]], [[IN1]]
+; CHECK-NEXT:    [[M00:%.*]] = mul i64 [[IN1]], [[IN0]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i64 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[ADDC]], 32
+; CHECK-NEXT:    [[RETLO:%.*]] = add i64 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i64 [[RETLO]]
+;
+  %In0Hi = lshr i64 %in0, 32
+  %In1Hi = lshr i64 %in1, 32
+  %m10 = mul i64 %In1Hi, %in0
+  %m01 = mul i64 %in1, %In0Hi
+  %m00 = mul i64 %in1, %in0
+  %addc = add i64 %m10, %m01
+  %shl = shl i64 %addc, 32
+  %retLo = add i64 %shl, %m00
+  ret i64 %retLo
+}
+
+; Negative test: Miss match the shift amount
+define i16 @mul16_low_miss_shift_amount(i16 %in0, i16 %in1) {
+; CHECK-LABEL: @mul16_low_miss_shift_amount(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i16 [[IN0:%.*]], 127
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i16 [[IN0]], 8
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i16 [[IN1:%.*]], 127
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i16 [[IN1]], 8
+; CHECK-NEXT:    [[M10:%.*]] = mul nuw nsw i16 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    [[M01:%.*]] = mul nuw nsw i16 [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw nsw i16 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add nuw i16 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i16 [[ADDC]], 8
+; CHECK-NEXT:    [[RETLO:%.*]] = add i16 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i16 [[RETLO]]
+;
+  %In0Lo = and i16 %in0, 127 ; Should be 255
+  %In0Hi = lshr i16 %in0, 8
+  %In1Lo = and i16 %in1, 127
+  %In1Hi = lshr i16 %in1, 8
+  %m10 = mul i16 %In1Hi, %In0Lo
+  %m01 = mul i16 %In1Lo, %In0Hi
+  %m00 = mul i16 %In1Lo, %In0Lo
+  %addc = add i16 %m10, %m01
+  %shl = shl i16 %addc, 8
+  %retLo = add i16 %shl, %m00
+  ret i16 %retLo
+}
+
+; Negative test: Miss match the half width
+define i8 @mul8_low_miss_half_width(i8 %in0, i8 %in1) {
+; CHECK-LABEL: @mul8_low_miss_half_width(
+; CHECK-NEXT:    [[IN0LO:%.*]] = and i8 [[IN0:%.*]], 15
+; CHECK-NEXT:    [[IN0HI:%.*]] = lshr i8 [[IN0]], 3
+; CHECK-NEXT:    [[IN1LO:%.*]] = and i8 [[IN1:%.*]], 15
+; CHECK-NEXT:    [[IN1HI:%.*]] = lshr i8 [[IN1]], 3
+; CHECK-NEXT:    [[M10:%.*]] = mul i8 [[IN1HI]], [[IN0LO]]
+; CHECK-NEXT:    [[M01:%.*]] = mul i8 [[IN1LO]], [[IN0HI]]
+; CHECK-NEXT:    [[M00:%.*]] = mul nuw i8 [[IN1LO]], [[IN0LO]]
+; CHECK-NEXT:    [[ADDC:%.*]] = add i8 [[M10]], [[M01]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[ADDC]], 3
+; CHECK-NEXT:    [[RETLO:%.*]] = add i8 [[SHL]], [[M00]]
+; CHECK-NEXT:    ret i8 [[RETLO]]
+;
+  %In0Lo = and i8 %in0, 15
+  %In0Hi = lshr i8 %in0, 3 ; Should be 4
+  %In1Lo = and i8 %in1, 15
+  %In1Hi = lshr i8 %in1, 3
+  %m10 = mul i8 %In1Hi, %In0Lo
+  %m01 = mul i8 %In1Lo, %In0Hi
+  %m00 = mul i8 %In1Lo, %In0Lo
+  %addc = add i8 %m10, %m01
+  %shl = shl i8 %addc, 3
+  %retLo = add i8 %shl, %m00
+  ret i8 %retLo
+}


        


More information about the llvm-commits mailing list