376 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; Canonicalize vector ge/le comparisons with constants to gt/lt.5 6; Normal types are ConstantDataVectors. Test the constant values adjacent to the7; min/max values that we're not allowed to transform.8 9define <2 x i1> @sge(<2 x i8> %x) {10; CHECK-LABEL: @sge(11; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -128, i8 126>12; CHECK-NEXT: ret <2 x i1> [[CMP]]13;14 %cmp = icmp sge <2 x i8> %x, <i8 -127, i8 -129>15 ret <2 x i1> %cmp16}17 18define <2 x i1> @uge(<2 x i8> %x) {19; CHECK-LABEL: @uge(20; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> [[X:%.*]], <i8 -2, i8 0>21; CHECK-NEXT: ret <2 x i1> [[CMP]]22;23 %cmp = icmp uge <2 x i8> %x, <i8 -1, i8 1>24 ret <2 x i1> %cmp25}26 27define <2 x i1> @sle(<2 x i8> %x) {28; CHECK-LABEL: @sle(29; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 127, i8 -127>30; CHECK-NEXT: ret <2 x i1> [[CMP]]31;32 %cmp = icmp sle <2 x i8> %x, <i8 126, i8 128>33 ret <2 x i1> %cmp34}35 36define <2 x i1> @ule(<2 x i8> %x) {37; CHECK-LABEL: @ule(38; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[X:%.*]], <i8 -1, i8 1>39; CHECK-NEXT: ret <2 x i1> [[CMP]]40;41 %cmp = icmp ule <2 x i8> %x, <i8 254, i8 0>42 ret <2 x i1> %cmp43}44 45define <2 x i1> @ult_min_signed_value(<2 x i8> %x) {46; CHECK-LABEL: @ult_min_signed_value(47; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], splat (i8 -1)48; CHECK-NEXT: ret <2 x i1> [[CMP]]49;50 %cmp = icmp ult <2 x i8> %x, <i8 128, i8 128>51 ret <2 x i1> %cmp52}53 54; Zeros are special: they're ConstantAggregateZero.55 56define <2 x i1> @sge_zero(<2 x i8> %x) {57; CHECK-LABEL: @sge_zero(58; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], splat (i8 -1)59; CHECK-NEXT: ret <2 x i1> [[CMP]]60;61 %cmp = icmp sge <2 x i8> %x, <i8 0, i8 0>62 ret <2 x i1> %cmp63}64 65define <2 x i1> @uge_zero(<2 x i8> %x) {66; CHECK-LABEL: @uge_zero(67; CHECK-NEXT: ret <2 x i1> splat (i1 true)68;69 %cmp = icmp uge <2 x i8> %x, <i8 0, i8 0>70 ret <2 x i1> %cmp71}72 73define <2 x i1> @sle_zero(<2 x i8> %x) {74; CHECK-LABEL: @sle_zero(75; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], splat (i8 1)76; CHECK-NEXT: ret <2 x i1> [[CMP]]77;78 %cmp = icmp sle <2 x i8> %x, <i8 0, i8 0>79 ret <2 x i1> %cmp80}81 82define <2 x i1> @ule_zero(<2 x i8> %x) {83; CHECK-LABEL: @ule_zero(84; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer85; CHECK-NEXT: ret <2 x i1> [[CMP]]86;87 %cmp = icmp ule <2 x i8> %x, <i8 0, i8 0>88 ret <2 x i1> %cmp89}90 91; Weird types are ConstantVectors, not ConstantDataVectors. For an i3 type:92; Signed min = -493; Unsigned min = 094; Signed max = 395; Unsigned max = 796 97define <3 x i1> @sge_weird(<3 x i3> %x) {98; CHECK-LABEL: @sge_weird(99; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i3> [[X:%.*]], <i3 -4, i3 2, i3 -1>100; CHECK-NEXT: ret <3 x i1> [[CMP]]101;102 %cmp = icmp sge <3 x i3> %x, <i3 -3, i3 -5, i3 0>103 ret <3 x i1> %cmp104}105 106define <3 x i1> @uge_weird(<3 x i3> %x) {107; CHECK-LABEL: @uge_weird(108; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <3 x i3> [[X:%.*]], <i3 -2, i3 0, i3 1>109; CHECK-NEXT: ret <3 x i1> [[CMP]]110;111 %cmp = icmp uge <3 x i3> %x, <i3 -1, i3 1, i3 2>112 ret <3 x i1> %cmp113}114 115define <3 x i1> @sle_weird(<3 x i3> %x) {116; CHECK-LABEL: @sle_weird(117; CHECK-NEXT: [[CMP:%.*]] = icmp slt <3 x i3> [[X:%.*]], <i3 3, i3 -3, i3 1>118; CHECK-NEXT: ret <3 x i1> [[CMP]]119;120 %cmp = icmp sle <3 x i3> %x, <i3 2, i3 4, i3 0>121 ret <3 x i1> %cmp122}123 124define <3 x i1> @ule_weird(<3 x i3> %x) {125; CHECK-LABEL: @ule_weird(126; CHECK-NEXT: [[CMP:%.*]] = icmp ult <3 x i3> [[X:%.*]], <i3 -1, i3 1, i3 2>127; CHECK-NEXT: ret <3 x i1> [[CMP]]128;129 %cmp = icmp ule <3 x i3> %x, <i3 6, i3 0, i3 1>130 ret <3 x i1> %cmp131}132 133; We can't do the transform if any constants are already at the limits.134 135define <2 x i1> @sge_min(<2 x i3> %x) {136; CHECK-LABEL: @sge_min(137; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i3> [[X:%.*]], <i3 -4, i3 1>138; CHECK-NEXT: ret <2 x i1> [[CMP]]139;140 %cmp = icmp sge <2 x i3> %x, <i3 -4, i3 1>141 ret <2 x i1> %cmp142}143 144define <2 x i1> @uge_min(<2 x i3> %x) {145; CHECK-LABEL: @uge_min(146; CHECK-NEXT: [[CMP:%.*]] = icmp uge <2 x i3> [[X:%.*]], <i3 1, i3 0>147; CHECK-NEXT: ret <2 x i1> [[CMP]]148;149 %cmp = icmp uge <2 x i3> %x, <i3 1, i3 0>150 ret <2 x i1> %cmp151}152 153define <2 x i1> @sle_max(<2 x i3> %x) {154; CHECK-LABEL: @sle_max(155; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i3> [[X:%.*]], <i3 1, i3 3>156; CHECK-NEXT: ret <2 x i1> [[CMP]]157;158 %cmp = icmp sle <2 x i3> %x, <i3 1, i3 3>159 ret <2 x i1> %cmp160}161 162define <2 x i1> @ule_max(<2 x i3> %x) {163; CHECK-LABEL: @ule_max(164; CHECK-NEXT: [[CMP:%.*]] = icmp ule <2 x i3> [[X:%.*]], <i3 -1, i3 1>165; CHECK-NEXT: ret <2 x i1> [[CMP]]166;167 %cmp = icmp ule <2 x i3> %x, <i3 7, i3 1>168 ret <2 x i1> %cmp169}170 171define <2 x i1> @PR27756_1(<2 x i8> %a) {172; CHECK-LABEL: @PR27756_1(173; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], <i8 34, i8 1>174; CHECK-NEXT: ret <2 x i1> [[CMP]]175;176 %cmp = icmp sle <2 x i8> %a, <i8 bitcast (<2 x i4> <i4 1, i4 2> to i8), i8 0>177 ret <2 x i1> %cmp178}179 180; Undef elements don't prevent the transform of the comparison.181 182define <3 x i1> @PR27756_2(<3 x i8> %a) {183; CHECK-LABEL: @PR27756_2(184; CHECK-NEXT: [[CMP:%.*]] = icmp slt <3 x i8> [[A:%.*]], <i8 43, i8 43, i8 1>185; CHECK-NEXT: ret <3 x i1> [[CMP]]186;187 %cmp = icmp sle <3 x i8> %a, <i8 42, i8 poison, i8 0>188 ret <3 x i1> %cmp189}190 191define <3 x i1> @PR27756_3(<3 x i8> %a) {192; CHECK-LABEL: @PR27756_3(193; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i8> [[A:%.*]], <i8 0, i8 0, i8 41>194; CHECK-NEXT: ret <3 x i1> [[CMP]]195;196 %cmp = icmp sge <3 x i8> %a, <i8 poison, i8 1, i8 42>197 ret <3 x i1> %cmp198}199 200@someglobal = global i32 0201 202define <2 x i1> @PR27786(<2 x i8> %a) {203; CHECK-LABEL: @PR27786(204; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i8> [[A:%.*]], bitcast (i16 ptrtoint (ptr @someglobal to i16) to <2 x i8>)205; CHECK-NEXT: ret <2 x i1> [[CMP]]206;207 %cmp = icmp sle <2 x i8> %a, bitcast (i16 ptrtoint (ptr @someglobal to i16) to <2 x i8>)208 ret <2 x i1> %cmp209}210 211; This is similar to a transform for shuffled binops: compare first, shuffle after.212 213define <4 x i1> @same_shuffle_inputs_icmp(<4 x i8> %x, <4 x i8> %y) {214; CHECK-LABEL: @same_shuffle_inputs_icmp(215; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i8> [[X:%.*]], [[Y:%.*]]216; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 2, i32 0>217; CHECK-NEXT: ret <4 x i1> [[CMP]]218;219 %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 2, i32 0 >220 %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 2, i32 0 >221 %cmp = icmp sgt <4 x i8> %shufx, %shufy222 ret <4 x i1> %cmp223}224 225; fcmp and size-changing shuffles are ok too.226 227define <5 x i1> @same_shuffle_inputs_fcmp(<4 x float> %x, <4 x float> %y) {228; CHECK-LABEL: @same_shuffle_inputs_fcmp(229; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq <4 x float> [[X:%.*]], [[Y:%.*]]230; 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>231; CHECK-NEXT: ret <5 x i1> [[CMP]]232;233 %shufx = shufflevector <4 x float> %x, <4 x float> poison, <5 x i32> < i32 0, i32 1, i32 3, i32 2, i32 0 >234 %shufy = shufflevector <4 x float> %y, <4 x float> poison, <5 x i32> < i32 0, i32 1, i32 3, i32 2, i32 0 >235 %cmp = fcmp oeq <5 x float> %shufx, %shufy236 ret <5 x i1> %cmp237}238 239declare void @use_v4i8(<4 x i8>)240 241define <4 x i1> @same_shuffle_inputs_icmp_extra_use1(<4 x i8> %x, <4 x i8> %y) {242; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use1(243; CHECK-NEXT: [[SHUFX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>244; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt <4 x i8> [[X]], [[Y:%.*]]245; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>246; CHECK-NEXT: call void @use_v4i8(<4 x i8> [[SHUFX]])247; CHECK-NEXT: ret <4 x i1> [[CMP]]248;249 %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 3, i32 3 >250 %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 3, i32 3 >251 %cmp = icmp ugt <4 x i8> %shufx, %shufy252 call void @use_v4i8(<4 x i8> %shufx)253 ret <4 x i1> %cmp254}255 256declare void @use_v2i8(<2 x i8>)257 258define <2 x i1> @same_shuffle_inputs_icmp_extra_use2(<4 x i8> %x, <4 x i8> %y) {259; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use2(260; CHECK-NEXT: [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> <i32 3, i32 2>261; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i8> [[X:%.*]], [[Y]]262; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <2 x i32> <i32 3, i32 2>263; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFY]])264; CHECK-NEXT: ret <2 x i1> [[CMP]]265;266 %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <2 x i32> < i32 3, i32 2 >267 %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <2 x i32> < i32 3, i32 2 >268 %cmp = icmp eq <2 x i8> %shufx, %shufy269 call void @use_v2i8(<2 x i8> %shufy)270 ret <2 x i1> %cmp271}272 273; Negative test: if both shuffles have extra uses, don't transform because that would increase instruction count.274 275define <2 x i1> @same_shuffle_inputs_icmp_extra_use3(<4 x i8> %x, <4 x i8> %y) {276; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use3(277; CHECK-NEXT: [[SHUFX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer278; CHECK-NEXT: [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer279; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[SHUFX]], [[SHUFY]]280; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFX]])281; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFY]])282; CHECK-NEXT: ret <2 x i1> [[CMP]]283;284 %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <2 x i32> < i32 0, i32 0 >285 %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <2 x i32> < i32 0, i32 0 >286 %cmp = icmp eq <2 x i8> %shufx, %shufy287 call void @use_v2i8(<2 x i8> %shufx)288 call void @use_v2i8(<2 x i8> %shufy)289 ret <2 x i1> %cmp290}291 292define <4 x i1> @splat_icmp(<4 x i8> %x) {293; CHECK-LABEL: @splat_icmp(294; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i8> [[X:%.*]], splat (i8 42)295; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>296; CHECK-NEXT: ret <4 x i1> [[CMP]]297;298 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>299 %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>300 ret <4 x i1> %cmp301}302 303define <4 x i1> @splat_icmp_poison(<4 x i8> %x) {304; CHECK-LABEL: @splat_icmp_poison(305; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <4 x i8> [[X:%.*]], splat (i8 42)306; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>307; CHECK-NEXT: ret <4 x i1> [[CMP]]308;309 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 2>310 %cmp = icmp ult <4 x i8> %splatx, <i8 poison, i8 42, i8 poison, i8 42>311 ret <4 x i1> %cmp312}313 314define <4 x i1> @splat_icmp_larger_size(<2 x i8> %x) {315; CHECK-LABEL: @splat_icmp_larger_size(316; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 42)317; CHECK-NEXT: [[CMP:%.*]] = shufflevector <2 x i1> [[TMP1]], <2 x i1> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>318; CHECK-NEXT: ret <4 x i1> [[CMP]]319;320 %splatx = shufflevector <2 x i8> %x, <2 x i8> poison, <4 x i32> <i32 1, i32 poison, i32 1, i32 poison>321 %cmp = icmp eq <4 x i8> %splatx, <i8 42, i8 42, i8 poison, i8 42>322 ret <4 x i1> %cmp323}324 325define <4 x i1> @splat_fcmp_smaller_size(<5 x float> %x) {326; CHECK-LABEL: @splat_fcmp_smaller_size(327; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq <5 x float> [[X:%.*]], splat (float 4.200000e+01)328; CHECK-NEXT: [[CMP:%.*]] = shufflevector <5 x i1> [[TMP1]], <5 x i1> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>329; CHECK-NEXT: ret <4 x i1> [[CMP]]330;331 %splatx = shufflevector <5 x float> %x, <5 x float> poison, <4 x i32> <i32 1, i32 poison, i32 1, i32 poison>332 %cmp = fcmp oeq <4 x float> %splatx, <float 42.0, float 42.0, float poison, float 42.0>333 ret <4 x i1> %cmp334}335 336; Negative test337 338define <4 x i1> @splat_icmp_extra_use(<4 x i8> %x) {339; CHECK-LABEL: @splat_icmp_extra_use(340; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>341; CHECK-NEXT: call void @use_v4i8(<4 x i8> [[SPLATX]])342; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], splat (i8 42)343; CHECK-NEXT: ret <4 x i1> [[CMP]]344;345 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>346 call void @use_v4i8(<4 x i8> %splatx)347 %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>348 ret <4 x i1> %cmp349}350 351; Negative test352 353define <4 x i1> @not_splat_icmp(<4 x i8> %x) {354; CHECK-LABEL: @not_splat_icmp(355; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 3, i32 3>356; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], splat (i8 42)357; CHECK-NEXT: ret <4 x i1> [[CMP]]358;359 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 3, i32 3>360 %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>361 ret <4 x i1> %cmp362}363 364; Negative test365 366define <4 x i1> @not_splat_icmp2(<4 x i8> %x) {367; CHECK-LABEL: @not_splat_icmp2(368; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>369; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], <i8 43, i8 42, i8 42, i8 42>370; CHECK-NEXT: ret <4 x i1> [[CMP]]371;372 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>373 %cmp = icmp sgt <4 x i8> %splatx, <i8 43, i8 42, i8 42, i8 42>374 ret <4 x i1> %cmp375}376