mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 14:16:08 +00:00

In #88217 a large set of matchers was changed to only accept poison values in splats, but not undef values. This is because we now use poison for non-demanded vector elements, and allowing undef can cause correctness issues. This patch covers the remaining matchers by changing the AllowUndef parameter of getSplatValue() to AllowPoison instead. We also carry out corresponding renames in matchers. As a followup, we may want to change the default for things like m_APInt to m_APIntAllowPoison (as this is much less risky when only allowing poison), but this change doesn't do that. There is one caveat here: We have a single place (X86FixupVectorConstants) which does require handling of vector splats with undefs. This is because this works on backend constant pool entries, which currently still use undef instead of poison for non-demanded elements (because SDAG as a whole does not have an explicit poison representation). As it's just the single use, I've open-coded a getSplatValueAllowUndef() helper there, to discourage use in any other places.
376 lines
14 KiB
LLVM
376 lines
14 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
|
|
|
; Canonicalize vector ge/le comparisons with constants to gt/lt.
|
|
|
|
; Normal types are ConstantDataVectors. Test the constant values adjacent to the
|
|
; min/max values that we're not allowed to transform.
|
|
|
|
define <2 x i1> @sge(<2 x i8> %x) {
|
|
; CHECK-LABEL: @sge(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -128, i8 126>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sge <2 x i8> %x, <i8 -127, i8 -129>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @uge(<2 x i8> %x) {
|
|
; CHECK-LABEL: @uge(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> [[X:%.*]], <i8 -2, i8 0>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp uge <2 x i8> %x, <i8 -1, i8 1>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @sle(<2 x i8> %x) {
|
|
; CHECK-LABEL: @sle(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 127, i8 -127>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sle <2 x i8> %x, <i8 126, i8 128>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @ule(<2 x i8> %x) {
|
|
; CHECK-LABEL: @ule(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[X:%.*]], <i8 -1, i8 1>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp ule <2 x i8> %x, <i8 254, i8 0>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @ult_min_signed_value(<2 x i8> %x) {
|
|
; CHECK-LABEL: @ult_min_signed_value(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp ult <2 x i8> %x, <i8 128, i8 128>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
; Zeros are special: they're ConstantAggregateZero.
|
|
|
|
define <2 x i1> @sge_zero(<2 x i8> %x) {
|
|
; CHECK-LABEL: @sge_zero(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sge <2 x i8> %x, <i8 0, i8 0>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @uge_zero(<2 x i8> %x) {
|
|
; CHECK-LABEL: @uge_zero(
|
|
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
|
|
;
|
|
%cmp = icmp uge <2 x i8> %x, <i8 0, i8 0>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @sle_zero(<2 x i8> %x) {
|
|
; CHECK-LABEL: @sle_zero(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 1, i8 1>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sle <2 x i8> %x, <i8 0, i8 0>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @ule_zero(<2 x i8> %x) {
|
|
; CHECK-LABEL: @ule_zero(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp ule <2 x i8> %x, <i8 0, i8 0>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
; Weird types are ConstantVectors, not ConstantDataVectors. For an i3 type:
|
|
; Signed min = -4
|
|
; Unsigned min = 0
|
|
; Signed max = 3
|
|
; Unsigned max = 7
|
|
|
|
define <3 x i1> @sge_weird(<3 x i3> %x) {
|
|
; CHECK-LABEL: @sge_weird(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i3> [[X:%.*]], <i3 -4, i3 2, i3 -1>
|
|
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sge <3 x i3> %x, <i3 -3, i3 -5, i3 0>
|
|
ret <3 x i1> %cmp
|
|
}
|
|
|
|
define <3 x i1> @uge_weird(<3 x i3> %x) {
|
|
; CHECK-LABEL: @uge_weird(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <3 x i3> [[X:%.*]], <i3 -2, i3 0, i3 1>
|
|
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp uge <3 x i3> %x, <i3 -1, i3 1, i3 2>
|
|
ret <3 x i1> %cmp
|
|
}
|
|
|
|
define <3 x i1> @sle_weird(<3 x i3> %x) {
|
|
; CHECK-LABEL: @sle_weird(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <3 x i3> [[X:%.*]], <i3 3, i3 -3, i3 1>
|
|
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sle <3 x i3> %x, <i3 2, i3 4, i3 0>
|
|
ret <3 x i1> %cmp
|
|
}
|
|
|
|
define <3 x i1> @ule_weird(<3 x i3> %x) {
|
|
; CHECK-LABEL: @ule_weird(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <3 x i3> [[X:%.*]], <i3 -1, i3 1, i3 2>
|
|
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp ule <3 x i3> %x, <i3 6, i3 0, i3 1>
|
|
ret <3 x i1> %cmp
|
|
}
|
|
|
|
; We can't do the transform if any constants are already at the limits.
|
|
|
|
define <2 x i1> @sge_min(<2 x i3> %x) {
|
|
; CHECK-LABEL: @sge_min(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i3> [[X:%.*]], <i3 -4, i3 1>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sge <2 x i3> %x, <i3 -4, i3 1>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @uge_min(<2 x i3> %x) {
|
|
; CHECK-LABEL: @uge_min(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge <2 x i3> [[X:%.*]], <i3 1, i3 0>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp uge <2 x i3> %x, <i3 1, i3 0>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @sle_max(<2 x i3> %x) {
|
|
; CHECK-LABEL: @sle_max(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i3> [[X:%.*]], <i3 1, i3 3>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sle <2 x i3> %x, <i3 1, i3 3>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @ule_max(<2 x i3> %x) {
|
|
; CHECK-LABEL: @ule_max(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ule <2 x i3> [[X:%.*]], <i3 -1, i3 1>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp ule <2 x i3> %x, <i3 7, i3 1>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <2 x i1> @PR27756_1(<2 x i8> %a) {
|
|
; CHECK-LABEL: @PR27756_1(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], <i8 34, i8 1>
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sle <2 x i8> %a, <i8 bitcast (<2 x i4> <i4 1, i4 2> to i8), i8 0>
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
; Undef elements don't prevent the transform of the comparison.
|
|
|
|
define <3 x i1> @PR27756_2(<3 x i8> %a) {
|
|
; CHECK-LABEL: @PR27756_2(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <3 x i8> [[A:%.*]], <i8 43, i8 43, i8 1>
|
|
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sle <3 x i8> %a, <i8 42, i8 poison, i8 0>
|
|
ret <3 x i1> %cmp
|
|
}
|
|
|
|
define <3 x i1> @PR27756_3(<3 x i8> %a) {
|
|
; CHECK-LABEL: @PR27756_3(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i8> [[A:%.*]], <i8 0, i8 0, i8 41>
|
|
; CHECK-NEXT: ret <3 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sge <3 x i8> %a, <i8 poison, i8 1, i8 42>
|
|
ret <3 x i1> %cmp
|
|
}
|
|
|
|
@someglobal = global i32 0
|
|
|
|
define <2 x i1> @PR27786(<2 x i8> %a) {
|
|
; CHECK-LABEL: @PR27786(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i8> [[A:%.*]], bitcast (i16 ptrtoint (ptr @someglobal to i16) to <2 x i8>)
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%cmp = icmp sle <2 x i8> %a, bitcast (i16 ptrtoint (ptr @someglobal to i16) to <2 x i8>)
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
; This is similar to a transform for shuffled binops: compare first, shuffle after.
|
|
|
|
define <4 x i1> @same_shuffle_inputs_icmp(<4 x i8> %x, <4 x i8> %y) {
|
|
; CHECK-LABEL: @same_shuffle_inputs_icmp(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i8> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 2, i32 0>
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 2, i32 0 >
|
|
%shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 2, i32 0 >
|
|
%cmp = icmp sgt <4 x i8> %shufx, %shufy
|
|
ret <4 x i1> %cmp
|
|
}
|
|
|
|
; fcmp and size-changing shuffles are ok too.
|
|
|
|
define <5 x i1> @same_shuffle_inputs_fcmp(<4 x float> %x, <4 x float> %y) {
|
|
; CHECK-LABEL: @same_shuffle_inputs_fcmp(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq <4 x float> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <5 x i32> <i32 0, i32 1, i32 3, i32 2, i32 0>
|
|
; CHECK-NEXT: ret <5 x i1> [[CMP]]
|
|
;
|
|
%shufx = shufflevector <4 x float> %x, <4 x float> poison, <5 x i32> < i32 0, i32 1, i32 3, i32 2, i32 0 >
|
|
%shufy = shufflevector <4 x float> %y, <4 x float> poison, <5 x i32> < i32 0, i32 1, i32 3, i32 2, i32 0 >
|
|
%cmp = fcmp oeq <5 x float> %shufx, %shufy
|
|
ret <5 x i1> %cmp
|
|
}
|
|
|
|
declare void @use_v4i8(<4 x i8>)
|
|
|
|
define <4 x i1> @same_shuffle_inputs_icmp_extra_use1(<4 x i8> %x, <4 x i8> %y) {
|
|
; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use1(
|
|
; CHECK-NEXT: [[SHUFX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt <4 x i8> [[X]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
|
|
; CHECK-NEXT: call void @use_v4i8(<4 x i8> [[SHUFX]])
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 3, i32 3 >
|
|
%shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 3, i32 3 >
|
|
%cmp = icmp ugt <4 x i8> %shufx, %shufy
|
|
call void @use_v4i8(<4 x i8> %shufx)
|
|
ret <4 x i1> %cmp
|
|
}
|
|
|
|
declare void @use_v2i8(<2 x i8>)
|
|
|
|
define <2 x i1> @same_shuffle_inputs_icmp_extra_use2(<4 x i8> %x, <4 x i8> %y) {
|
|
; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use2(
|
|
; CHECK-NEXT: [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> <i32 3, i32 2>
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i8> [[X:%.*]], [[Y]]
|
|
; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <2 x i32> <i32 3, i32 2>
|
|
; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFY]])
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <2 x i32> < i32 3, i32 2 >
|
|
%shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <2 x i32> < i32 3, i32 2 >
|
|
%cmp = icmp eq <2 x i8> %shufx, %shufy
|
|
call void @use_v2i8(<2 x i8> %shufy)
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
; Negative test: if both shuffles have extra uses, don't transform because that would increase instruction count.
|
|
|
|
define <2 x i1> @same_shuffle_inputs_icmp_extra_use3(<4 x i8> %x, <4 x i8> %y) {
|
|
; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use3(
|
|
; CHECK-NEXT: [[SHUFX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer
|
|
; CHECK-NEXT: [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[SHUFX]], [[SHUFY]]
|
|
; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFX]])
|
|
; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFY]])
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
;
|
|
%shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <2 x i32> < i32 0, i32 0 >
|
|
%shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <2 x i32> < i32 0, i32 0 >
|
|
%cmp = icmp eq <2 x i8> %shufx, %shufy
|
|
call void @use_v2i8(<2 x i8> %shufx)
|
|
call void @use_v2i8(<2 x i8> %shufy)
|
|
ret <2 x i1> %cmp
|
|
}
|
|
|
|
define <4 x i1> @splat_icmp(<4 x i8> %x) {
|
|
; CHECK-LABEL: @splat_icmp(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i8> [[X:%.*]], <i8 42, i8 42, i8 42, i8 42>
|
|
; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
|
|
%cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>
|
|
ret <4 x i1> %cmp
|
|
}
|
|
|
|
define <4 x i1> @splat_icmp_poison(<4 x i8> %x) {
|
|
; CHECK-LABEL: @splat_icmp_poison(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <4 x i8> [[X:%.*]], <i8 42, i8 42, i8 42, i8 42>
|
|
; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 2>
|
|
%cmp = icmp ult <4 x i8> %splatx, <i8 poison, i8 42, i8 poison, i8 42>
|
|
ret <4 x i1> %cmp
|
|
}
|
|
|
|
define <4 x i1> @splat_icmp_larger_size(<2 x i8> %x) {
|
|
; CHECK-LABEL: @splat_icmp_larger_size(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 42, i8 42>
|
|
; CHECK-NEXT: [[CMP:%.*]] = shufflevector <2 x i1> [[TMP1]], <2 x i1> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%splatx = shufflevector <2 x i8> %x, <2 x i8> poison, <4 x i32> <i32 1, i32 poison, i32 1, i32 poison>
|
|
%cmp = icmp eq <4 x i8> %splatx, <i8 42, i8 42, i8 poison, i8 42>
|
|
ret <4 x i1> %cmp
|
|
}
|
|
|
|
define <4 x i1> @splat_fcmp_smaller_size(<5 x float> %x) {
|
|
; CHECK-LABEL: @splat_fcmp_smaller_size(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq <5 x float> [[X:%.*]], <float 4.200000e+01, float 4.200000e+01, float 4.200000e+01, float 4.200000e+01, float 4.200000e+01>
|
|
; CHECK-NEXT: [[CMP:%.*]] = shufflevector <5 x i1> [[TMP1]], <5 x i1> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%splatx = shufflevector <5 x float> %x, <5 x float> poison, <4 x i32> <i32 1, i32 poison, i32 1, i32 poison>
|
|
%cmp = fcmp oeq <4 x float> %splatx, <float 42.0, float 42.0, float poison, float 42.0>
|
|
ret <4 x i1> %cmp
|
|
}
|
|
|
|
; Negative test
|
|
|
|
define <4 x i1> @splat_icmp_extra_use(<4 x i8> %x) {
|
|
; CHECK-LABEL: @splat_icmp_extra_use(
|
|
; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
|
|
; CHECK-NEXT: call void @use_v4i8(<4 x i8> [[SPLATX]])
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], <i8 42, i8 42, i8 42, i8 42>
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
|
|
call void @use_v4i8(<4 x i8> %splatx)
|
|
%cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>
|
|
ret <4 x i1> %cmp
|
|
}
|
|
|
|
; Negative test
|
|
|
|
define <4 x i1> @not_splat_icmp(<4 x i8> %x) {
|
|
; CHECK-LABEL: @not_splat_icmp(
|
|
; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 3, i32 3>
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], <i8 42, i8 42, i8 42, i8 42>
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 3, i32 3>
|
|
%cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>
|
|
ret <4 x i1> %cmp
|
|
}
|
|
|
|
; Negative test
|
|
|
|
define <4 x i1> @not_splat_icmp2(<4 x i8> %x) {
|
|
; CHECK-LABEL: @not_splat_icmp2(
|
|
; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], <i8 43, i8 42, i8 42, i8 42>
|
|
; CHECK-NEXT: ret <4 x i1> [[CMP]]
|
|
;
|
|
%splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
|
|
%cmp = icmp sgt <4 x i8> %splatx, <i8 43, i8 42, i8 42, i8 42>
|
|
ret <4 x i1> %cmp
|
|
}
|