Skip to content

Commit

Permalink
[InstCombine][NFC] Add Tests for Minimum over Trailing/Leading Bits C…
Browse files Browse the repository at this point in the history
…ounts
  • Loading branch information
mskamp committed Apr 28, 2024
1 parent 256d76f commit 9fdd0b1
Showing 1 changed file with 355 additions and 0 deletions.
355 changes: 355 additions & 0 deletions llvm/test/Transforms/InstCombine/umin_cttz_ctlz.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

declare i1 @llvm.umin.i1(i1 %a, i1 %b)
declare i8 @llvm.umin.i8(i8 %a, i8 %b)
declare i16 @llvm.umin.i16(i16 %a, i16 %b)
declare i32 @llvm.umin.i32(i32 %a, i32 %b)
declare i64 @llvm.umin.i64(i64 %a, i64 %b)
declare <2 x i32> @llvm.umin.v2i32(<2 x i32> %a, <2 x i32> %b)

declare i1 @llvm.cttz.i1(i1, i1)
declare i8 @llvm.cttz.i8(i8, i1)
declare i16 @llvm.cttz.i16(i16, i1)
declare i32 @llvm.cttz.i32(i32, i1)
declare i64 @llvm.cttz.i64(i64, i1)
declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1)

declare i1 @llvm.ctlz.i1(i1, i1)
declare i8 @llvm.ctlz.i8(i8, i1)
declare i16 @llvm.ctlz.i16(i16, i1)
declare i32 @llvm.ctlz.i32(i32, i1)
declare i64 @llvm.ctlz.i64(i64, i1)
declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1)

define i8 @umin_cttz_i8_zero_undefined(i8 %X) {
; CHECK-LABEL: define i8 @umin_cttz_i8_zero_undefined(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i8 0, 9) i8 @llvm.cttz.i8(i8 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.umin.i8(i8 [[CTTZ]], i8 6)
; CHECK-NEXT: ret i8 [[RET]]
;
%cttz = call i8 @llvm.cttz.i8(i8 %X, i1 true)
%ret = call i8 @llvm.umin.i8(i8 %cttz, i8 6)
ret i8 %ret
}

define i8 @umin_cttz_i8_zero_defined(i8 %X) {
; CHECK-LABEL: define i8 @umin_cttz_i8_zero_defined(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i8 0, 9) i8 @llvm.cttz.i8(i8 [[X]], i1 false)
; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.umin.i8(i8 [[CTTZ]], i8 6)
; CHECK-NEXT: ret i8 [[RET]]
;
%cttz = call i8 @llvm.cttz.i8(i8 %X, i1 false)
%ret = call i8 @llvm.umin.i8(i8 %cttz, i8 6)
ret i8 %ret
}

define i8 @umin_cttz_i8_commuted_zero_undefined(i8 %X) {
; CHECK-LABEL: define i8 @umin_cttz_i8_commuted_zero_undefined(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i8 0, 9) i8 @llvm.cttz.i8(i8 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.umin.i8(i8 [[CTTZ]], i8 6)
; CHECK-NEXT: ret i8 [[RET]]
;
%cttz = call i8 @llvm.cttz.i8(i8 %X, i1 true)
%ret = call i8 @llvm.umin.i8(i8 6, i8 %cttz)
ret i8 %ret
}

define i8 @umin_cttz_i8_ge_bitwidth_zero_undefined(i8 %X) {
; CHECK-LABEL: define i8 @umin_cttz_i8_ge_bitwidth_zero_undefined(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i8 0, 9) i8 @llvm.cttz.i8(i8 [[X]], i1 true)
; CHECK-NEXT: ret i8 [[CTTZ]]
;
%cttz = call i8 @llvm.cttz.i8(i8 %X, i1 true)
%ret = call i8 @llvm.umin.i8(i8 %cttz, i8 10)
ret i8 %ret
}

define i16 @umin_cttz_i16_zero_undefined(i16 %X) {
; CHECK-LABEL: define i16 @umin_cttz_i16_zero_undefined(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.umin.i16(i16 [[CTTZ]], i16 6)
; CHECK-NEXT: ret i16 [[RET]]
;
%cttz = call i16 @llvm.cttz.i16(i16 %X, i1 true)
%ret = call i16 @llvm.umin.i16(i16 %cttz, i16 6)
ret i16 %ret
}

define i32 @umin_cttz_i32_zero_undefined(i32 %X) {
; CHECK-LABEL: define i32 @umin_cttz_i32_zero_undefined(
; CHECK-SAME: i32 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.umin.i32(i32 [[CTTZ]], i32 6)
; CHECK-NEXT: ret i32 [[RET]]
;
%cttz = call i32 @llvm.cttz.i32(i32 %X, i1 true)
%ret = call i32 @llvm.umin.i32(i32 %cttz, i32 6)
ret i32 %ret
}

define i64 @umin_cttz_i64_zero_undefined(i64 %X) {
; CHECK-LABEL: define i64 @umin_cttz_i64_zero_undefined(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i64 @llvm.umin.i64(i64 [[CTTZ]], i64 6)
; CHECK-NEXT: ret i64 [[RET]]
;
%cttz = call i64 @llvm.cttz.i64(i64 %X, i1 true)
%ret = call i64 @llvm.umin.i64(i64 %cttz, i64 6)
ret i64 %ret
}

define i1 @umin_cttz_i1_zero_undefined(i1 %X) {
; CHECK-LABEL: define i1 @umin_cttz_i1_zero_undefined(
; CHECK-SAME: i1 [[X:%.*]]) {
; CHECK-NEXT: ret i1 false
;
%cttz = call i1 @llvm.cttz.i1(i1 %X, i1 true)
%ret = call i1 @llvm.umin.i1(i1 %cttz, i1 1)
ret i1 %ret
}

define i1 @umin_cttz_i1_zero_defined(i1 %X) {
; CHECK-LABEL: define i1 @umin_cttz_i1_zero_defined(
; CHECK-SAME: i1 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = xor i1 [[X]], true
; CHECK-NEXT: ret i1 [[CTTZ]]
;
%cttz = call i1 @llvm.cttz.i1(i1 %X, i1 false)
%ret = call i1 @llvm.umin.i1(i1 %cttz, i1 1)
ret i1 %ret
}

define <2 x i32> @umin_cttz_2xi32_splat_zero_undefined(<2 x i32> %X) {
; CHECK-LABEL: define <2 x i32> @umin_cttz_2xi32_splat_zero_undefined(
; CHECK-SAME: <2 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[CTTZ]], <2 x i32> <i32 6, i32 6>)
; CHECK-NEXT: ret <2 x i32> [[RET]]
;
%cttz = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %X, i1 true)
%ret = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %cttz, <2 x i32> <i32 6, i32 6>)
ret <2 x i32> %ret
}

define <2 x i32> @umin_cttz_2xi32_splat_poison_zero_undefined(<2 x i32> %X) {
; CHECK-LABEL: define <2 x i32> @umin_cttz_2xi32_splat_poison_zero_undefined(
; CHECK-SAME: <2 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[CTTZ]], <2 x i32> <i32 6, i32 poison>)
; CHECK-NEXT: ret <2 x i32> [[RET]]
;
%cttz = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %X, i1 true)
%ret = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %cttz, <2 x i32> <i32 6, i32 poison>)
ret <2 x i32> %ret
}

define <2 x i32> @umin_cttz_2xi32_no_splat_negative_zero_undefined(<2 x i32> %X) {
; CHECK-LABEL: define <2 x i32> @umin_cttz_2xi32_no_splat_negative_zero_undefined(
; CHECK-SAME: <2 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[CTTZ]], <2 x i32> <i32 6, i32 0>)
; CHECK-NEXT: ret <2 x i32> [[RET]]
;
%cttz = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %X, i1 true)
%ret = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %cttz, <2 x i32> <i32 6, i32 0>)
ret <2 x i32> %ret
}

define i16 @umin_cttz_i16_negative_non_constant(i16 %X, i16 %Y) {
; CHECK-LABEL: define i16 @umin_cttz_i16_negative_non_constant(
; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.umin.i16(i16 [[CTTZ]], i16 [[Y]])
; CHECK-NEXT: ret i16 [[RET]]
;
%cttz = call i16 @llvm.cttz.i16(i16 %X, i1 true)
%ret = call i16 @llvm.umin.i16(i16 %cttz, i16 %Y)
ret i16 %ret
}

define i16 @umin_cttz_i16_negative_two_uses(i16 %X) {
; CHECK-LABEL: define i16 @umin_cttz_i16_negative_two_uses(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X]], i1 true)
; CHECK-NEXT: [[OP0:%.*]] = call i16 @llvm.umin.i16(i16 [[CTTZ]], i16 6)
; CHECK-NEXT: [[RET:%.*]] = add nuw nsw i16 [[CTTZ]], [[OP0]]
; CHECK-NEXT: ret i16 [[RET]]
;
%cttz = call i16 @llvm.cttz.i16(i16 %X, i1 true)
%op0 = call i16 @llvm.umin.i16(i16 %cttz, i16 6)
%ret = add i16 %cttz, %op0
ret i16 %ret
}

define i8 @umin_ctlz_i8_zero_undefined(i8 %X) {
; CHECK-LABEL: define i8 @umin_ctlz_i8_zero_undefined(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i8 0, 9) i8 @llvm.ctlz.i8(i8 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.umin.i8(i8 [[CTLZ]], i8 6)
; CHECK-NEXT: ret i8 [[RET]]
;
%ctlz = call i8 @llvm.ctlz.i8(i8 %X, i1 true)
%ret = call i8 @llvm.umin.i8(i8 %ctlz, i8 6)
ret i8 %ret
}

define i8 @umin_ctlz_i8_zero_defined(i8 %X) {
; CHECK-LABEL: define i8 @umin_ctlz_i8_zero_defined(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i8 0, 9) i8 @llvm.ctlz.i8(i8 [[X]], i1 false)
; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.umin.i8(i8 [[CTLZ]], i8 6)
; CHECK-NEXT: ret i8 [[RET]]
;
%ctlz = call i8 @llvm.ctlz.i8(i8 %X, i1 false)
%ret = call i8 @llvm.umin.i8(i8 %ctlz, i8 6)
ret i8 %ret
}

define i8 @umin_ctlz_i8_commuted_zero_undefined(i8 %X) {
; CHECK-LABEL: define i8 @umin_ctlz_i8_commuted_zero_undefined(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i8 0, 9) i8 @llvm.ctlz.i8(i8 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.umin.i8(i8 [[CTLZ]], i8 6)
; CHECK-NEXT: ret i8 [[RET]]
;
%ctlz = call i8 @llvm.ctlz.i8(i8 %X, i1 true)
%ret = call i8 @llvm.umin.i8(i8 6, i8 %ctlz)
ret i8 %ret
}

define i8 @umin_ctlz_i8_ge_bitwidth_zero_undefined(i8 %X) {
; CHECK-LABEL: define i8 @umin_ctlz_i8_ge_bitwidth_zero_undefined(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i8 0, 9) i8 @llvm.ctlz.i8(i8 [[X]], i1 true)
; CHECK-NEXT: ret i8 [[CTLZ]]
;
%ctlz = call i8 @llvm.ctlz.i8(i8 %X, i1 true)
%ret = call i8 @llvm.umin.i8(i8 %ctlz, i8 10)
ret i8 %ret
}

define i16 @umin_ctlz_i16_zero_undefined(i16 %X) {
; CHECK-LABEL: define i16 @umin_ctlz_i16_zero_undefined(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.umin.i16(i16 [[CTLZ]], i16 6)
; CHECK-NEXT: ret i16 [[RET]]
;
%ctlz = call i16 @llvm.ctlz.i16(i16 %X, i1 true)
%ret = call i16 @llvm.umin.i16(i16 %ctlz, i16 6)
ret i16 %ret
}

define i32 @umin_ctlz_i32_zero_undefined(i32 %X) {
; CHECK-LABEL: define i32 @umin_ctlz_i32_zero_undefined(
; CHECK-SAME: i32 [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.umin.i32(i32 [[CTLZ]], i32 6)
; CHECK-NEXT: ret i32 [[RET]]
;
%ctlz = call i32 @llvm.ctlz.i32(i32 %X, i1 true)
%ret = call i32 @llvm.umin.i32(i32 %ctlz, i32 6)
ret i32 %ret
}

define i64 @umin_ctlz_i64_zero_undefined(i64 %X) {
; CHECK-LABEL: define i64 @umin_ctlz_i64_zero_undefined(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i64 @llvm.umin.i64(i64 [[CTLZ]], i64 6)
; CHECK-NEXT: ret i64 [[RET]]
;
%ctlz = call i64 @llvm.ctlz.i64(i64 %X, i1 true)
%ret = call i64 @llvm.umin.i64(i64 %ctlz, i64 6)
ret i64 %ret
}

define i1 @umin_ctlz_i1_zero_undefined(i1 %X) {
; CHECK-LABEL: define i1 @umin_ctlz_i1_zero_undefined(
; CHECK-SAME: i1 [[X:%.*]]) {
; CHECK-NEXT: ret i1 false
;
%ctlz = call i1 @llvm.ctlz.i1(i1 %X, i1 true)
%ret = call i1 @llvm.umin.i1(i1 %ctlz, i1 1)
ret i1 %ret
}

define i1 @umin_ctlz_i1_zero_defined(i1 %X) {
; CHECK-LABEL: define i1 @umin_ctlz_i1_zero_defined(
; CHECK-SAME: i1 [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = xor i1 [[X]], true
; CHECK-NEXT: ret i1 [[CTLZ]]
;
%ctlz = call i1 @llvm.ctlz.i1(i1 %X, i1 false)
%ret = call i1 @llvm.umin.i1(i1 %ctlz, i1 1)
ret i1 %ret
}

define <2 x i32> @umin_ctlz_2xi32_splat_zero_undefined(<2 x i32> %X) {
; CHECK-LABEL: define <2 x i32> @umin_ctlz_2xi32_splat_zero_undefined(
; CHECK-SAME: <2 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[CTLZ]], <2 x i32> <i32 6, i32 6>)
; CHECK-NEXT: ret <2 x i32> [[RET]]
;
%ctlz = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %X, i1 true)
%ret = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %ctlz, <2 x i32> <i32 6, i32 6>)
ret <2 x i32> %ret
}

define <2 x i32> @umin_ctlz_2xi32_splat_poison_zero_undefined(<2 x i32> %X) {
; CHECK-LABEL: define <2 x i32> @umin_ctlz_2xi32_splat_poison_zero_undefined(
; CHECK-SAME: <2 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[CTLZ]], <2 x i32> <i32 6, i32 poison>)
; CHECK-NEXT: ret <2 x i32> [[RET]]
;
%ctlz = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %X, i1 true)
%ret = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %ctlz, <2 x i32> <i32 6, i32 poison>)
ret <2 x i32> %ret
}

define <2 x i32> @umin_ctlz_2xi32_no_splat_negative_zero_undefined(<2 x i32> %X) {
; CHECK-LABEL: define <2 x i32> @umin_ctlz_2xi32_no_splat_negative_zero_undefined(
; CHECK-SAME: <2 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[CTLZ]], <2 x i32> <i32 6, i32 0>)
; CHECK-NEXT: ret <2 x i32> [[RET]]
;
%ctlz = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %X, i1 true)
%ret = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %ctlz, <2 x i32> <i32 6, i32 0>)
ret <2 x i32> %ret
}

define i16 @umin_ctlz_i16_negative_non_constant(i16 %X, i16 %Y) {
; CHECK-LABEL: define i16 @umin_ctlz_i16_negative_non_constant(
; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
; CHECK-NEXT: [[CTLZ:%.*]] = call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.umin.i16(i16 [[CTLZ]], i16 [[Y]])
; CHECK-NEXT: ret i16 [[RET]]
;
%ctlz = call i16 @llvm.ctlz.i16(i16 %X, i1 true)
%ret = call i16 @llvm.umin.i16(i16 %ctlz, i16 %Y)
ret i16 %ret
}

define i16 @umin_ctlz_i16_negative_two_uses(i16 %X) {
; CHECK-LABEL: define i16 @umin_ctlz_i16_negative_two_uses(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[CTTZ:%.*]] = call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X]], i1 true)
; CHECK-NEXT: [[OP0:%.*]] = call i16 @llvm.umin.i16(i16 [[CTTZ]], i16 6)
; CHECK-NEXT: [[RET:%.*]] = add nuw nsw i16 [[CTTZ]], [[OP0]]
; CHECK-NEXT: ret i16 [[RET]]
;
%ctlz = call i16 @llvm.ctlz.i16(i16 %X, i1 true)
%op0 = call i16 @llvm.umin.i16(i16 %ctlz, i16 6)
%ret = add i16 %ctlz, %op0
ret i16 %ret
}

0 comments on commit 9fdd0b1

Please sign in to comment.