739 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 9target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"10 11define <2 x i1> @sge(<2 x i8> %x) {12; CHECK-LABEL: @sge(13; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -128, i8 126>14; CHECK-NEXT: ret <2 x i1> [[CMP]]15;16 %cmp = icmp sge <2 x i8> %x, <i8 -127, i8 -129>17 ret <2 x i1> %cmp18}19 20define <2 x i1> @uge(<2 x i8> %x) {21; CHECK-LABEL: @uge(22; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> [[X:%.*]], <i8 -2, i8 0>23; CHECK-NEXT: ret <2 x i1> [[CMP]]24;25 %cmp = icmp uge <2 x i8> %x, <i8 -1, i8 1>26 ret <2 x i1> %cmp27}28 29define <2 x i1> @sle(<2 x i8> %x) {30; CHECK-LABEL: @sle(31; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 127, i8 -127>32; CHECK-NEXT: ret <2 x i1> [[CMP]]33;34 %cmp = icmp sle <2 x i8> %x, <i8 126, i8 128>35 ret <2 x i1> %cmp36}37 38define <2 x i1> @ule(<2 x i8> %x) {39; CHECK-LABEL: @ule(40; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[X:%.*]], <i8 -1, i8 1>41; CHECK-NEXT: ret <2 x i1> [[CMP]]42;43 %cmp = icmp ule <2 x i8> %x, <i8 254, i8 0>44 ret <2 x i1> %cmp45}46 47define <2 x i1> @ult_min_signed_value(<2 x i8> %x) {48; CHECK-LABEL: @ult_min_signed_value(49; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], splat (i8 -1)50; CHECK-NEXT: ret <2 x i1> [[CMP]]51;52 %cmp = icmp ult <2 x i8> %x, <i8 128, i8 128>53 ret <2 x i1> %cmp54}55 56; Zeros are special: they're ConstantAggregateZero.57 58define <2 x i1> @sge_zero(<2 x i8> %x) {59; CHECK-LABEL: @sge_zero(60; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], splat (i8 -1)61; CHECK-NEXT: ret <2 x i1> [[CMP]]62;63 %cmp = icmp sge <2 x i8> %x, <i8 0, i8 0>64 ret <2 x i1> %cmp65}66 67define <2 x i1> @uge_zero(<2 x i8> %x) {68; CHECK-LABEL: @uge_zero(69; CHECK-NEXT: ret <2 x i1> splat (i1 true)70;71 %cmp = icmp uge <2 x i8> %x, <i8 0, i8 0>72 ret <2 x i1> %cmp73}74 75define <2 x i1> @sle_zero(<2 x i8> %x) {76; CHECK-LABEL: @sle_zero(77; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], splat (i8 1)78; CHECK-NEXT: ret <2 x i1> [[CMP]]79;80 %cmp = icmp sle <2 x i8> %x, <i8 0, i8 0>81 ret <2 x i1> %cmp82}83 84define <2 x i1> @ule_zero(<2 x i8> %x) {85; CHECK-LABEL: @ule_zero(86; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer87; CHECK-NEXT: ret <2 x i1> [[CMP]]88;89 %cmp = icmp ule <2 x i8> %x, <i8 0, i8 0>90 ret <2 x i1> %cmp91}92 93; Weird types are ConstantVectors, not ConstantDataVectors. For an i3 type:94; Signed min = -495; Unsigned min = 096; Signed max = 397; Unsigned max = 798 99define <3 x i1> @sge_weird(<3 x i3> %x) {100; CHECK-LABEL: @sge_weird(101; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i3> [[X:%.*]], <i3 -4, i3 2, i3 -1>102; CHECK-NEXT: ret <3 x i1> [[CMP]]103;104 %cmp = icmp sge <3 x i3> %x, <i3 -3, i3 -5, i3 0>105 ret <3 x i1> %cmp106}107 108define <3 x i1> @uge_weird(<3 x i3> %x) {109; CHECK-LABEL: @uge_weird(110; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <3 x i3> [[X:%.*]], <i3 -2, i3 0, i3 1>111; CHECK-NEXT: ret <3 x i1> [[CMP]]112;113 %cmp = icmp uge <3 x i3> %x, <i3 -1, i3 1, i3 2>114 ret <3 x i1> %cmp115}116 117define <3 x i1> @sle_weird(<3 x i3> %x) {118; CHECK-LABEL: @sle_weird(119; CHECK-NEXT: [[CMP:%.*]] = icmp slt <3 x i3> [[X:%.*]], <i3 3, i3 -3, i3 1>120; CHECK-NEXT: ret <3 x i1> [[CMP]]121;122 %cmp = icmp sle <3 x i3> %x, <i3 2, i3 4, i3 0>123 ret <3 x i1> %cmp124}125 126define <3 x i1> @ule_weird(<3 x i3> %x) {127; CHECK-LABEL: @ule_weird(128; CHECK-NEXT: [[CMP:%.*]] = icmp ult <3 x i3> [[X:%.*]], <i3 -1, i3 1, i3 2>129; CHECK-NEXT: ret <3 x i1> [[CMP]]130;131 %cmp = icmp ule <3 x i3> %x, <i3 6, i3 0, i3 1>132 ret <3 x i1> %cmp133}134 135; We can't do the transform if any constants are already at the limits.136 137define <2 x i1> @sge_min(<2 x i3> %x) {138; CHECK-LABEL: @sge_min(139; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i3> [[X:%.*]], <i3 -4, i3 1>140; CHECK-NEXT: ret <2 x i1> [[CMP]]141;142 %cmp = icmp sge <2 x i3> %x, <i3 -4, i3 1>143 ret <2 x i1> %cmp144}145 146define <2 x i1> @uge_min(<2 x i3> %x) {147; CHECK-LABEL: @uge_min(148; CHECK-NEXT: [[CMP:%.*]] = icmp uge <2 x i3> [[X:%.*]], <i3 1, i3 0>149; CHECK-NEXT: ret <2 x i1> [[CMP]]150;151 %cmp = icmp uge <2 x i3> %x, <i3 1, i3 0>152 ret <2 x i1> %cmp153}154 155define <2 x i1> @sle_max(<2 x i3> %x) {156; CHECK-LABEL: @sle_max(157; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i3> [[X:%.*]], <i3 1, i3 3>158; CHECK-NEXT: ret <2 x i1> [[CMP]]159;160 %cmp = icmp sle <2 x i3> %x, <i3 1, i3 3>161 ret <2 x i1> %cmp162}163 164define <2 x i1> @ule_max(<2 x i3> %x) {165; CHECK-LABEL: @ule_max(166; CHECK-NEXT: [[CMP:%.*]] = icmp ule <2 x i3> [[X:%.*]], <i3 -1, i3 1>167; CHECK-NEXT: ret <2 x i1> [[CMP]]168;169 %cmp = icmp ule <2 x i3> %x, <i3 7, i3 1>170 ret <2 x i1> %cmp171}172 173define <2 x i1> @PR27756_1(<2 x i8> %a) {174; CHECK-LABEL: @PR27756_1(175; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], <i8 34, i8 1>176; CHECK-NEXT: ret <2 x i1> [[CMP]]177;178 %cmp = icmp sle <2 x i8> %a, <i8 bitcast (<2 x i4> <i4 1, i4 2> to i8), i8 0>179 ret <2 x i1> %cmp180}181 182; Undef elements don't prevent the transform of the comparison.183 184define <3 x i1> @PR27756_2(<3 x i8> %a) {185; CHECK-LABEL: @PR27756_2(186; CHECK-NEXT: [[CMP:%.*]] = icmp slt <3 x i8> [[A:%.*]], <i8 43, i8 43, i8 1>187; CHECK-NEXT: ret <3 x i1> [[CMP]]188;189 %cmp = icmp sle <3 x i8> %a, <i8 42, i8 poison, i8 0>190 ret <3 x i1> %cmp191}192 193define <3 x i1> @PR27756_3(<3 x i8> %a) {194; CHECK-LABEL: @PR27756_3(195; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i8> [[A:%.*]], <i8 0, i8 0, i8 41>196; CHECK-NEXT: ret <3 x i1> [[CMP]]197;198 %cmp = icmp sge <3 x i8> %a, <i8 poison, i8 1, i8 42>199 ret <3 x i1> %cmp200}201 202@someglobal = global i32 0203 204define <2 x i1> @PR27786(<2 x i8> %a) {205; CHECK-LABEL: @PR27786(206; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i8> [[A:%.*]], bitcast (i16 ptrtoint (ptr @someglobal to i16) to <2 x i8>)207; CHECK-NEXT: ret <2 x i1> [[CMP]]208;209 %cmp = icmp sle <2 x i8> %a, bitcast (i16 ptrtoint (ptr @someglobal to i16) to <2 x i8>)210 ret <2 x i1> %cmp211}212 213; This is similar to a transform for shuffled binops: compare first, shuffle after.214 215define <4 x i1> @same_shuffle_inputs_icmp(<4 x i8> %x, <4 x i8> %y) {216; CHECK-LABEL: @same_shuffle_inputs_icmp(217; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i8> [[X:%.*]], [[Y:%.*]]218; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 2, i32 0>219; CHECK-NEXT: ret <4 x i1> [[CMP]]220;221 %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 2, i32 0 >222 %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 2, i32 0 >223 %cmp = icmp sgt <4 x i8> %shufx, %shufy224 ret <4 x i1> %cmp225}226 227; fcmp and size-changing shuffles are ok too.228 229define <5 x i1> @same_shuffle_inputs_fcmp(<4 x float> %x, <4 x float> %y) {230; CHECK-LABEL: @same_shuffle_inputs_fcmp(231; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq <4 x float> [[X:%.*]], [[Y:%.*]]232; 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>233; CHECK-NEXT: ret <5 x i1> [[CMP]]234;235 %shufx = shufflevector <4 x float> %x, <4 x float> poison, <5 x i32> < i32 0, i32 1, i32 3, i32 2, i32 0 >236 %shufy = shufflevector <4 x float> %y, <4 x float> poison, <5 x i32> < i32 0, i32 1, i32 3, i32 2, i32 0 >237 %cmp = fcmp oeq <5 x float> %shufx, %shufy238 ret <5 x i1> %cmp239}240 241declare void @use_v4i8(<4 x i8>)242 243define <4 x i1> @same_shuffle_inputs_icmp_extra_use1(<4 x i8> %x, <4 x i8> %y) {244; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use1(245; CHECK-NEXT: [[SHUFX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>246; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt <4 x i8> [[X]], [[Y:%.*]]247; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>248; CHECK-NEXT: call void @use_v4i8(<4 x i8> [[SHUFX]])249; CHECK-NEXT: ret <4 x i1> [[CMP]]250;251 %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 3, i32 3 >252 %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 3, i32 3 >253 %cmp = icmp ugt <4 x i8> %shufx, %shufy254 call void @use_v4i8(<4 x i8> %shufx)255 ret <4 x i1> %cmp256}257 258declare void @use_v2i8(<2 x i8>)259 260define <2 x i1> @same_shuffle_inputs_icmp_extra_use2(<4 x i8> %x, <4 x i8> %y) {261; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use2(262; CHECK-NEXT: [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> <i32 3, i32 2>263; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i8> [[X:%.*]], [[Y]]264; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <2 x i32> <i32 3, i32 2>265; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFY]])266; CHECK-NEXT: ret <2 x i1> [[CMP]]267;268 %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <2 x i32> < i32 3, i32 2 >269 %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <2 x i32> < i32 3, i32 2 >270 %cmp = icmp eq <2 x i8> %shufx, %shufy271 call void @use_v2i8(<2 x i8> %shufy)272 ret <2 x i1> %cmp273}274 275; Negative test: if both shuffles have extra uses, don't transform because that would increase instruction count.276 277define <2 x i1> @same_shuffle_inputs_icmp_extra_use3(<4 x i8> %x, <4 x i8> %y) {278; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use3(279; CHECK-NEXT: [[SHUFX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer280; CHECK-NEXT: [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer281; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[SHUFX]], [[SHUFY]]282; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFX]])283; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[SHUFY]])284; CHECK-NEXT: ret <2 x i1> [[CMP]]285;286 %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <2 x i32> < i32 0, i32 0 >287 %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <2 x i32> < i32 0, i32 0 >288 %cmp = icmp eq <2 x i8> %shufx, %shufy289 call void @use_v2i8(<2 x i8> %shufx)290 call void @use_v2i8(<2 x i8> %shufy)291 ret <2 x i1> %cmp292}293 294define <4 x i1> @splat_icmp(<4 x i8> %x) {295; CHECK-LABEL: @splat_icmp(296; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i8> [[X:%.*]], splat (i8 42)297; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>298; CHECK-NEXT: ret <4 x i1> [[CMP]]299;300 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>301 %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>302 ret <4 x i1> %cmp303}304 305define <4 x i1> @splat_icmp_poison(<4 x i8> %x) {306; CHECK-LABEL: @splat_icmp_poison(307; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <4 x i8> [[X:%.*]], splat (i8 42)308; CHECK-NEXT: [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>309; CHECK-NEXT: ret <4 x i1> [[CMP]]310;311 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 2>312 %cmp = icmp ult <4 x i8> %splatx, <i8 poison, i8 42, i8 poison, i8 42>313 ret <4 x i1> %cmp314}315 316define <4 x i1> @splat_icmp_larger_size(<2 x i8> %x) {317; CHECK-LABEL: @splat_icmp_larger_size(318; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 42)319; CHECK-NEXT: [[CMP:%.*]] = shufflevector <2 x i1> [[TMP1]], <2 x i1> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>320; CHECK-NEXT: ret <4 x i1> [[CMP]]321;322 %splatx = shufflevector <2 x i8> %x, <2 x i8> poison, <4 x i32> <i32 1, i32 poison, i32 1, i32 poison>323 %cmp = icmp eq <4 x i8> %splatx, <i8 42, i8 42, i8 poison, i8 42>324 ret <4 x i1> %cmp325}326 327define <4 x i1> @splat_fcmp_smaller_size(<5 x float> %x) {328; CHECK-LABEL: @splat_fcmp_smaller_size(329; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq <5 x float> [[X:%.*]], splat (float 4.200000e+01)330; CHECK-NEXT: [[CMP:%.*]] = shufflevector <5 x i1> [[TMP1]], <5 x i1> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>331; CHECK-NEXT: ret <4 x i1> [[CMP]]332;333 %splatx = shufflevector <5 x float> %x, <5 x float> poison, <4 x i32> <i32 1, i32 poison, i32 1, i32 poison>334 %cmp = fcmp oeq <4 x float> %splatx, <float 42.0, float 42.0, float poison, float 42.0>335 ret <4 x i1> %cmp336}337 338; Negative test339 340define <4 x i1> @splat_icmp_extra_use(<4 x i8> %x) {341; CHECK-LABEL: @splat_icmp_extra_use(342; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>343; CHECK-NEXT: call void @use_v4i8(<4 x i8> [[SPLATX]])344; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], splat (i8 42)345; CHECK-NEXT: ret <4 x i1> [[CMP]]346;347 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>348 call void @use_v4i8(<4 x i8> %splatx)349 %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>350 ret <4 x i1> %cmp351}352 353; Negative test354 355define <4 x i1> @not_splat_icmp(<4 x i8> %x) {356; CHECK-LABEL: @not_splat_icmp(357; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 3, i32 3>358; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], splat (i8 42)359; CHECK-NEXT: ret <4 x i1> [[CMP]]360;361 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 3, i32 3>362 %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>363 ret <4 x i1> %cmp364}365 366; Negative test367 368define <4 x i1> @not_splat_icmp2(<4 x i8> %x) {369; CHECK-LABEL: @not_splat_icmp2(370; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>371; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], <i8 43, i8 42, i8 42, i8 42>372; CHECK-NEXT: ret <4 x i1> [[CMP]]373;374 %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>375 %cmp = icmp sgt <4 x i8> %splatx, <i8 43, i8 42, i8 42, i8 42>376 ret <4 x i1> %cmp377}378 379; Check that we don't absorb the compare into the select, which is in the380; canonical form of logical or.381define <2 x i1> @icmp_logical_or_vec(<2 x i64> %x, <2 x i64> %y, <2 x i1> %falseval) {382; CHECK-LABEL: @icmp_logical_or_vec(383; CHECK-NEXT: [[CMP_NE:%.*]] = icmp ne <2 x i64> [[X:%.*]], zeroinitializer384; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[CMP_NE]], <2 x i1> splat (i1 true), <2 x i1> [[FALSEVAL:%.*]]385; CHECK-NEXT: ret <2 x i1> [[SEL]]386;387 %cmp.ne = icmp ne <2 x i64> %x, zeroinitializer388 %sel = select <2 x i1> %cmp.ne, <2 x i1> shufflevector (<2 x i1> insertelement (<2 x i1> poison, i1 true, i32 0), <2 x i1> poison, <2 x i32> zeroinitializer), <2 x i1> %falseval389 ret <2 x i1> %sel390}391 392; The above, but for scalable vectors. Absorbing the compare into the select393; and breaking the canonical form led to an infinite loop.394define <vscale x 2 x i1> @icmp_logical_or_scalablevec(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y, <vscale x 2 x i1> %falseval) {395; CHECK-LABEL: @icmp_logical_or_scalablevec(396; CHECK-NEXT: [[CMP_NE:%.*]] = icmp ne <vscale x 2 x i64> [[X:%.*]], zeroinitializer397; CHECK-NEXT: [[SEL:%.*]] = select <vscale x 2 x i1> [[CMP_NE]], <vscale x 2 x i1> splat (i1 true), <vscale x 2 x i1> [[FALSEVAL:%.*]]398; CHECK-NEXT: ret <vscale x 2 x i1> [[SEL]]399;400 %cmp.ne = icmp ne <vscale x 2 x i64> %x, zeroinitializer401 %sel = select <vscale x 2 x i1> %cmp.ne, <vscale x 2 x i1> splat (i1 true), <vscale x 2 x i1> %falseval402 ret <vscale x 2 x i1> %sel403}404 405define i1 @eq_cast_eq-1(<2 x i4> %x, <2 x i4> %y) {406; CHECK-LABEL: @eq_cast_eq-1(407; CHECK-NEXT: [[X_SCALAR:%.*]] = bitcast <2 x i4> [[X:%.*]] to i8408; CHECK-NEXT: [[Y_SCALAR:%.*]] = bitcast <2 x i4> [[Y:%.*]] to i8409; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X_SCALAR]], [[Y_SCALAR]]410; CHECK-NEXT: ret i1 [[R]]411;412 %ic = icmp eq <2 x i4> %x, %y413 %b = bitcast <2 x i1> %ic to i2414 %r = icmp eq i2 %b, -1415 ret i1 %r416}417 418define i1 @ne_cast_eq-1(<3 x i7> %x, <3 x i7> %y) {419; CHECK-LABEL: @ne_cast_eq-1(420; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i7> [[X:%.*]], [[Y:%.*]]421; CHECK-NEXT: [[TMP2:%.*]] = bitcast <3 x i1> [[TMP1]] to i3422; CHECK-NEXT: [[R:%.*]] = icmp eq i3 [[TMP2]], 0423; CHECK-NEXT: ret i1 [[R]]424;425 %ic = icmp ne <3 x i7> %x, %y426 %b = bitcast <3 x i1> %ic to i3427 %r = icmp eq i3 %b, -1428 ret i1 %r429}430 431define i1 @eq_cast_ne-1(<2 x i7> %x, <2 x i7> %y) {432; CHECK-LABEL: @eq_cast_ne-1(433; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i7> [[X:%.*]], [[Y:%.*]]434; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2435; CHECK-NEXT: [[R:%.*]] = icmp ne i2 [[TMP2]], 0436; CHECK-NEXT: ret i1 [[R]]437;438 %ic = icmp eq <2 x i7> %x, %y439 %b = bitcast <2 x i1> %ic to i2440 %r = icmp ne i2 %b, -1441 ret i1 %r442}443 444define i1 @eq_cast_ne-1-legal-scalar(<2 x i8> %x, <2 x i8> %y) {445; CHECK-LABEL: @eq_cast_ne-1-legal-scalar(446; CHECK-NEXT: [[X_SCALAR:%.*]] = bitcast <2 x i8> [[X:%.*]] to i16447; CHECK-NEXT: [[Y_SCALAR:%.*]] = bitcast <2 x i8> [[Y:%.*]] to i16448; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[X_SCALAR]], [[Y_SCALAR]]449; CHECK-NEXT: ret i1 [[R]]450;451 %ic = icmp eq <2 x i8> %x, %y452 %b = bitcast <2 x i1> %ic to i2453 %r = icmp ne i2 %b, -1454 ret i1 %r455}456 457define i1 @ne_cast_ne-1(<3 x i5> %x, <3 x i5> %y) {458; CHECK-LABEL: @ne_cast_ne-1(459; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i5> [[X:%.*]], [[Y:%.*]]460; CHECK-NEXT: [[TMP2:%.*]] = bitcast <3 x i1> [[TMP1]] to i3461; CHECK-NEXT: [[R:%.*]] = icmp ne i3 [[TMP2]], 0462; CHECK-NEXT: ret i1 [[R]]463;464 %ic = icmp ne <3 x i5> %x, %y465 %b = bitcast <3 x i1> %ic to i3466 %r = icmp ne i3 %b, -1467 ret i1 %r468}469 470define i1 @ugt_cast_eq-1(<2 x i4> %x, <2 x i4> %y) {471; CHECK-LABEL: @ugt_cast_eq-1(472; CHECK-NEXT: [[TMP1:%.*]] = icmp ule <2 x i4> [[X:%.*]], [[Y:%.*]]473; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2474; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[TMP2]], 0475; CHECK-NEXT: ret i1 [[R]]476;477 %ic = icmp ugt <2 x i4> %x, %y478 %b = bitcast <2 x i1> %ic to i2479 %r = icmp eq i2 %b, -1480 ret i1 %r481}482 483define i1 @slt_cast_ne-1(<2 x i4> %x, <2 x i4> %y) {484; CHECK-LABEL: @slt_cast_ne-1(485; CHECK-NEXT: [[TMP1:%.*]] = icmp sge <2 x i4> [[X:%.*]], [[Y:%.*]]486; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2487; CHECK-NEXT: [[R:%.*]] = icmp ne i2 [[TMP2]], 0488; CHECK-NEXT: ret i1 [[R]]489;490 %ic = icmp slt <2 x i4> %x, %y491 %b = bitcast <2 x i1> %ic to i2492 %r = icmp ne i2 %b, -1493 ret i1 %r494}495 496define i1 @ueq_cast_eq-1(<3 x float> %x, <3 x float> %y) {497; CHECK-LABEL: @ueq_cast_eq-1(498; CHECK-NEXT: [[TMP1:%.*]] = fcmp one <3 x float> [[X:%.*]], [[Y:%.*]]499; CHECK-NEXT: [[TMP2:%.*]] = bitcast <3 x i1> [[TMP1]] to i3500; CHECK-NEXT: [[R:%.*]] = icmp eq i3 [[TMP2]], 0501; CHECK-NEXT: ret i1 [[R]]502;503 %fc = fcmp ueq <3 x float> %x, %y504 %b = bitcast <3 x i1> %fc to i3505 %r = icmp eq i3 %b, -1506 ret i1 %r507}508 509define i1 @not_cast_ne-1(<3 x i1> %x) {510; CHECK-LABEL: @not_cast_ne-1(511; CHECK-NEXT: [[TMP1:%.*]] = bitcast <3 x i1> [[X:%.*]] to i3512; CHECK-NEXT: [[R:%.*]] = icmp ne i3 [[TMP1]], 0513; CHECK-NEXT: ret i1 [[R]]514;515 %not = xor <3 x i1> %x, <i1 -1, i1 -1, i1 -1>516 %b = bitcast <3 x i1> %not to i3517 %r = icmp ne i3 %b, -1518 ret i1 %r519}520 521define i1 @not_cast_ne-1_uses(<3 x i2> %x, ptr %p) {522; CHECK-LABEL: @not_cast_ne-1_uses(523; CHECK-NEXT: [[NOT:%.*]] = xor <3 x i2> [[X:%.*]], splat (i2 -1)524; CHECK-NEXT: store <3 x i2> [[NOT]], ptr [[P:%.*]], align 1525; CHECK-NEXT: [[TMP1:%.*]] = bitcast <3 x i2> [[X]] to i6526; CHECK-NEXT: [[R:%.*]] = icmp ne i6 [[TMP1]], 0527; CHECK-NEXT: ret i1 [[R]]528;529 %not = xor <3 x i2> %x, <i2 -1, i2 -1, i2 -1>530 store <3 x i2> %not, ptr %p531 %b = bitcast <3 x i2> %not to i6532 %r = icmp ne i6 %b, -1533 ret i1 %r534}535 536; negative test - need equality pred on 2nd cmp537 538define i1 @eq_cast_sgt-1(<3 x i4> %x, <3 x i4> %y) {539; CHECK-LABEL: @eq_cast_sgt-1(540; CHECK-NEXT: [[IC:%.*]] = icmp eq <3 x i4> [[X:%.*]], [[Y:%.*]]541; CHECK-NEXT: [[B:%.*]] = bitcast <3 x i1> [[IC]] to i3542; CHECK-NEXT: [[R:%.*]] = icmp sgt i3 [[B]], -1543; CHECK-NEXT: ret i1 [[R]]544;545 %ic = icmp eq <3 x i4> %x, %y546 %b = bitcast <3 x i1> %ic to i3547 %r = icmp sgt i3 %b, -1548 ret i1 %r549}550 551; negative test - need all-ones constant on 2nd cmp552 553define i1 @eq_cast_eq1(<2 x i4> %x, <2 x i4> %y) {554; CHECK-LABEL: @eq_cast_eq1(555; CHECK-NEXT: [[IC:%.*]] = icmp eq <2 x i4> [[X:%.*]], [[Y:%.*]]556; CHECK-NEXT: [[B:%.*]] = bitcast <2 x i1> [[IC]] to i2557; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[B]], 1558; CHECK-NEXT: ret i1 [[R]]559;560 %ic = icmp eq <2 x i4> %x, %y561 %b = bitcast <2 x i1> %ic to i2562 %r = icmp eq i2 %b, 1563 ret i1 %r564}565 566; negative test - extra use567 568define i1 @eq_cast_eq-1_use1(<2 x i4> %x, <2 x i4> %y, ptr %p) {569; CHECK-LABEL: @eq_cast_eq-1_use1(570; CHECK-NEXT: [[IC:%.*]] = icmp sgt <2 x i4> [[X:%.*]], [[Y:%.*]]571; CHECK-NEXT: store <2 x i1> [[IC]], ptr [[P:%.*]], align 1572; CHECK-NEXT: [[B:%.*]] = bitcast <2 x i1> [[IC]] to i2573; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[B]], -1574; CHECK-NEXT: ret i1 [[R]]575;576 %ic = icmp sgt <2 x i4> %x, %y577 store <2 x i1> %ic, ptr %p578 %b = bitcast <2 x i1> %ic to i2579 %r = icmp eq i2 %b, -1580 ret i1 %r581}582 583; negative test - extra use584 585define i1 @eq_cast_eq-1_use2(<2 x i4> %x, <2 x i4> %y, ptr %p) {586; CHECK-LABEL: @eq_cast_eq-1_use2(587; CHECK-NEXT: [[IC:%.*]] = icmp sgt <2 x i4> [[X:%.*]], [[Y:%.*]]588; CHECK-NEXT: [[B:%.*]] = bitcast <2 x i1> [[IC]] to i2589; CHECK-NEXT: store <2 x i1> [[IC]], ptr [[P:%.*]], align 1590; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[B]], -1591; CHECK-NEXT: ret i1 [[R]]592;593 %ic = icmp sgt <2 x i4> %x, %y594 %b = bitcast <2 x i1> %ic to i2595 store i2 %b, ptr %p596 %r = icmp eq i2 %b, -1597 ret i1 %r598}599 600define i1 @ne_cast_sext(<3 x i1> %b) {601; CHECK-LABEL: @ne_cast_sext(602; CHECK-NEXT: [[TMP1:%.*]] = bitcast <3 x i1> [[B:%.*]] to i3603; CHECK-NEXT: [[R:%.*]] = icmp ne i3 [[TMP1]], 0604; CHECK-NEXT: ret i1 [[R]]605;606 %e = sext <3 x i1> %b to <3 x i8>607 %bc = bitcast <3 x i8> %e to i24608 %r = icmp ne i24 %bc, 0609 ret i1 %r610}611 612define i1 @eq_cast_sext(<8 x i3> %b) {613; CHECK-LABEL: @eq_cast_sext(614; CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i3> [[B:%.*]] to i24615; CHECK-NEXT: [[R:%.*]] = icmp eq i24 [[TMP1]], 0616; CHECK-NEXT: ret i1 [[R]]617;618 %e = sext <8 x i3> %b to <8 x i8>619 %bc = bitcast <8 x i8> %e to i64620 %r = icmp eq i64 %bc, 0621 ret i1 %r622}623 624define i1 @ne_cast_zext(<4 x i1> %b) {625; CHECK-LABEL: @ne_cast_zext(626; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i1> [[B:%.*]] to i4627; CHECK-NEXT: [[R:%.*]] = icmp ne i4 [[TMP1]], 0628; CHECK-NEXT: ret i1 [[R]]629;630 %e = zext <4 x i1> %b to <4 x i8>631 %bc = bitcast <4 x i8> %e to i32632 %r = icmp ne i32 %bc, 0633 ret i1 %r634}635 636define i1 @eq_cast_zext(<5 x i3> %b) {637; CHECK-LABEL: @eq_cast_zext(638; CHECK-NEXT: [[TMP1:%.*]] = bitcast <5 x i3> [[B:%.*]] to i15639; CHECK-NEXT: [[R:%.*]] = icmp eq i15 [[TMP1]], 0640; CHECK-NEXT: ret i1 [[R]]641;642 %e = zext <5 x i3> %b to <5 x i7>643 %bc = bitcast <5 x i7> %e to i35644 %r = icmp eq i35 %bc, 0645 ret i1 %r646}647 648; negative test - valid for eq/ne only649 650define i1 @sgt_cast_zext(<5 x i3> %b) {651; CHECK-LABEL: @sgt_cast_zext(652; CHECK-NEXT: [[TMP1:%.*]] = bitcast <5 x i3> [[B:%.*]] to i15653; CHECK-NEXT: [[R:%.*]] = icmp ne i15 [[TMP1]], 0654; CHECK-NEXT: ret i1 [[R]]655;656 %e = zext <5 x i3> %b to <5 x i7>657 %bc = bitcast <5 x i7> %e to i35658 %r = icmp sgt i35 %bc, 0659 ret i1 %r660}661 662; negative test - not valid with non-zero constants663; TODO: We could handle some non-zero constants by checking for bit-loss after casts.664 665define i1 @eq7_cast_sext(<5 x i3> %b) {666; CHECK-LABEL: @eq7_cast_sext(667; CHECK-NEXT: [[E:%.*]] = sext <5 x i3> [[B:%.*]] to <5 x i7>668; CHECK-NEXT: [[BC:%.*]] = bitcast <5 x i7> [[E]] to i35669; CHECK-NEXT: [[R:%.*]] = icmp eq i35 [[BC]], 7670; CHECK-NEXT: ret i1 [[R]]671;672 %e = sext <5 x i3> %b to <5 x i7>673 %bc = bitcast <5 x i7> %e to i35674 %r = icmp eq i35 %bc, 7675 ret i1 %r676}677 678; extra use of extend is ok679 680define i1 @eq_cast_zext_use1(<5 x i3> %b, ptr %p) {681; CHECK-LABEL: @eq_cast_zext_use1(682; CHECK-NEXT: [[E:%.*]] = zext <5 x i3> [[B:%.*]] to <5 x i7>683; CHECK-NEXT: store <5 x i7> [[E]], ptr [[P:%.*]], align 8684; CHECK-NEXT: [[TMP1:%.*]] = bitcast <5 x i3> [[B]] to i15685; CHECK-NEXT: [[R:%.*]] = icmp eq i15 [[TMP1]], 0686; CHECK-NEXT: ret i1 [[R]]687;688 %e = zext <5 x i3> %b to <5 x i7>689 store <5 x i7> %e, ptr %p690 %bc = bitcast <5 x i7> %e to i35691 %r = icmp eq i35 %bc, 0692 ret i1 %r693}694 695; negative test - don't create an extra cast696 697declare void @use35(i35)698 699define i1 @eq_cast_zext_use2(<5 x i3> %b) {700; CHECK-LABEL: @eq_cast_zext_use2(701; CHECK-NEXT: [[E:%.*]] = zext <5 x i3> [[B:%.*]] to <5 x i7>702; CHECK-NEXT: [[BC:%.*]] = bitcast <5 x i7> [[E]] to i35703; CHECK-NEXT: call void @use35(i35 [[BC]])704; CHECK-NEXT: [[R:%.*]] = icmp eq i35 [[BC]], 0705; CHECK-NEXT: ret i1 [[R]]706;707 %e = zext <5 x i3> %b to <5 x i7>708 %bc = bitcast <5 x i7> %e to i35709 call void @use35(i35 %bc)710 %r = icmp eq i35 %bc, 0711 ret i1 %r712}713 714define i1 @eq_cast_eq_ptr-1(<2 x ptr> %x, <2 x ptr> %y) {715; CHECK-LABEL: @eq_cast_eq_ptr-1(716; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x ptr> [[X:%.*]], [[Y:%.*]]717; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2718; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[TMP2]], 0719; CHECK-NEXT: ret i1 [[R]]720;721 %ic = icmp eq <2 x ptr> %x, %y722 %b = bitcast <2 x i1> %ic to i2723 %r = icmp eq i2 %b, -1724 ret i1 %r725}726 727define i1 @eq_cast_ne_ptr-1(<2 x ptr> %x, <2 x ptr> %y) {728; CHECK-LABEL: @eq_cast_ne_ptr-1(729; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x ptr> [[X:%.*]], [[Y:%.*]]730; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2731; CHECK-NEXT: [[R:%.*]] = icmp ne i2 [[TMP2]], 0732; CHECK-NEXT: ret i1 [[R]]733;734 %ic = icmp eq <2 x ptr> %x, %y735 %b = bitcast <2 x i1> %ic to i2736 %r = icmp ne i2 %b, -1737 ret i1 %r738}739