1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; Canonicalize vector ge/le comparisons with constants to gt/lt. 5 6; Normal types are ConstantDataVectors. Test the constant values adjacent to the 7; 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> %cmp 18} 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> %cmp 27} 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> %cmp 36} 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> %cmp 45} 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> %cmp 54} 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> %cmp 65} 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> %cmp 73} 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> %cmp 82} 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:%.*]], zeroinitializer 87; 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> %cmp 91} 92 93; Weird types are ConstantVectors, not ConstantDataVectors. For an i3 type: 94; Signed min = -4 95; Unsigned min = 0 96; Signed max = 3 97; Unsigned max = 7 98 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> %cmp 106} 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> %cmp 115} 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> %cmp 124} 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> %cmp 133} 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> %cmp 144} 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> %cmp 153} 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> %cmp 162} 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> %cmp 171} 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> %cmp 180} 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> %cmp 191} 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> %cmp 200} 201 202@someglobal = global i32 0 203 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> %cmp 211} 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, %shufy 224 ret <4 x i1> %cmp 225} 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, %shufy 238 ret <5 x i1> %cmp 239} 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, %shufy 254 call void @use_v4i8(<4 x i8> %shufx) 255 ret <4 x i1> %cmp 256} 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, %shufy 271 call void @use_v2i8(<2 x i8> %shufy) 272 ret <2 x i1> %cmp 273} 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> zeroinitializer 280; CHECK-NEXT: [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer 281; 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, %shufy 289 call void @use_v2i8(<2 x i8> %shufx) 290 call void @use_v2i8(<2 x i8> %shufy) 291 ret <2 x i1> %cmp 292} 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> %cmp 303} 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> %cmp 314} 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> %cmp 325} 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> %cmp 336} 337 338; Negative test 339 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> %cmp 351} 352 353; Negative test 354 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> %cmp 364} 365 366; Negative test 367 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> %cmp 377} 378 379; Check that we don't absorb the compare into the select, which is in the 380; 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:%.*]], zeroinitializer 384; 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, zeroinitializer 388 %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> %falseval 389 ret <2 x i1> %sel 390} 391 392; The above, but for scalable vectors. Absorbing the compare into the select 393; 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:%.*]], zeroinitializer 397; 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, zeroinitializer 401 %sel = select <vscale x 2 x i1> %cmp.ne, <vscale x 2 x i1> splat (i1 true), <vscale x 2 x i1> %falseval 402 ret <vscale x 2 x i1> %sel 403} 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 i8 408; CHECK-NEXT: [[Y_SCALAR:%.*]] = bitcast <2 x i4> [[Y:%.*]] to i8 409; 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, %y 413 %b = bitcast <2 x i1> %ic to i2 414 %r = icmp eq i2 %b, -1 415 ret i1 %r 416} 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 i3 422; CHECK-NEXT: [[R:%.*]] = icmp eq i3 [[TMP2]], 0 423; CHECK-NEXT: ret i1 [[R]] 424; 425 %ic = icmp ne <3 x i7> %x, %y 426 %b = bitcast <3 x i1> %ic to i3 427 %r = icmp eq i3 %b, -1 428 ret i1 %r 429} 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 i2 435; CHECK-NEXT: [[R:%.*]] = icmp ne i2 [[TMP2]], 0 436; CHECK-NEXT: ret i1 [[R]] 437; 438 %ic = icmp eq <2 x i7> %x, %y 439 %b = bitcast <2 x i1> %ic to i2 440 %r = icmp ne i2 %b, -1 441 ret i1 %r 442} 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 i16 447; CHECK-NEXT: [[Y_SCALAR:%.*]] = bitcast <2 x i8> [[Y:%.*]] to i16 448; 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, %y 452 %b = bitcast <2 x i1> %ic to i2 453 %r = icmp ne i2 %b, -1 454 ret i1 %r 455} 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 i3 461; CHECK-NEXT: [[R:%.*]] = icmp ne i3 [[TMP2]], 0 462; CHECK-NEXT: ret i1 [[R]] 463; 464 %ic = icmp ne <3 x i5> %x, %y 465 %b = bitcast <3 x i1> %ic to i3 466 %r = icmp ne i3 %b, -1 467 ret i1 %r 468} 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 i2 474; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[TMP2]], 0 475; CHECK-NEXT: ret i1 [[R]] 476; 477 %ic = icmp ugt <2 x i4> %x, %y 478 %b = bitcast <2 x i1> %ic to i2 479 %r = icmp eq i2 %b, -1 480 ret i1 %r 481} 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 i2 487; CHECK-NEXT: [[R:%.*]] = icmp ne i2 [[TMP2]], 0 488; CHECK-NEXT: ret i1 [[R]] 489; 490 %ic = icmp slt <2 x i4> %x, %y 491 %b = bitcast <2 x i1> %ic to i2 492 %r = icmp ne i2 %b, -1 493 ret i1 %r 494} 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 i3 500; CHECK-NEXT: [[R:%.*]] = icmp eq i3 [[TMP2]], 0 501; CHECK-NEXT: ret i1 [[R]] 502; 503 %fc = fcmp ueq <3 x float> %x, %y 504 %b = bitcast <3 x i1> %fc to i3 505 %r = icmp eq i3 %b, -1 506 ret i1 %r 507} 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 i3 512; CHECK-NEXT: [[R:%.*]] = icmp ne i3 [[TMP1]], 0 513; 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 i3 517 %r = icmp ne i3 %b, -1 518 ret i1 %r 519} 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 1 525; CHECK-NEXT: [[TMP1:%.*]] = bitcast <3 x i2> [[X]] to i6 526; CHECK-NEXT: [[R:%.*]] = icmp ne i6 [[TMP1]], 0 527; 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 %p 531 %b = bitcast <3 x i2> %not to i6 532 %r = icmp ne i6 %b, -1 533 ret i1 %r 534} 535 536; negative test - need equality pred on 2nd cmp 537 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 i3 542; CHECK-NEXT: [[R:%.*]] = icmp sgt i3 [[B]], -1 543; CHECK-NEXT: ret i1 [[R]] 544; 545 %ic = icmp eq <3 x i4> %x, %y 546 %b = bitcast <3 x i1> %ic to i3 547 %r = icmp sgt i3 %b, -1 548 ret i1 %r 549} 550 551; negative test - need all-ones constant on 2nd cmp 552 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 i2 557; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[B]], 1 558; CHECK-NEXT: ret i1 [[R]] 559; 560 %ic = icmp eq <2 x i4> %x, %y 561 %b = bitcast <2 x i1> %ic to i2 562 %r = icmp eq i2 %b, 1 563 ret i1 %r 564} 565 566; negative test - extra use 567 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 1 572; CHECK-NEXT: [[B:%.*]] = bitcast <2 x i1> [[IC]] to i2 573; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[B]], -1 574; CHECK-NEXT: ret i1 [[R]] 575; 576 %ic = icmp sgt <2 x i4> %x, %y 577 store <2 x i1> %ic, ptr %p 578 %b = bitcast <2 x i1> %ic to i2 579 %r = icmp eq i2 %b, -1 580 ret i1 %r 581} 582 583; negative test - extra use 584 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 i2 589; CHECK-NEXT: store <2 x i1> [[IC]], ptr [[P:%.*]], align 1 590; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[B]], -1 591; CHECK-NEXT: ret i1 [[R]] 592; 593 %ic = icmp sgt <2 x i4> %x, %y 594 %b = bitcast <2 x i1> %ic to i2 595 store i2 %b, ptr %p 596 %r = icmp eq i2 %b, -1 597 ret i1 %r 598} 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 i3 603; CHECK-NEXT: [[R:%.*]] = icmp ne i3 [[TMP1]], 0 604; 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 i24 608 %r = icmp ne i24 %bc, 0 609 ret i1 %r 610} 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 i24 615; CHECK-NEXT: [[R:%.*]] = icmp eq i24 [[TMP1]], 0 616; 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 i64 620 %r = icmp eq i64 %bc, 0 621 ret i1 %r 622} 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 i4 627; CHECK-NEXT: [[R:%.*]] = icmp ne i4 [[TMP1]], 0 628; 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 i32 632 %r = icmp ne i32 %bc, 0 633 ret i1 %r 634} 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 i15 639; CHECK-NEXT: [[R:%.*]] = icmp eq i15 [[TMP1]], 0 640; 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 i35 644 %r = icmp eq i35 %bc, 0 645 ret i1 %r 646} 647 648; negative test - valid for eq/ne only 649 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 i15 653; CHECK-NEXT: [[R:%.*]] = icmp ne i15 [[TMP1]], 0 654; 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 i35 658 %r = icmp sgt i35 %bc, 0 659 ret i1 %r 660} 661 662; negative test - not valid with non-zero constants 663; 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 i35 669; CHECK-NEXT: [[R:%.*]] = icmp eq i35 [[BC]], 7 670; 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 i35 674 %r = icmp eq i35 %bc, 7 675 ret i1 %r 676} 677 678; extra use of extend is ok 679 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 8 684; CHECK-NEXT: [[TMP1:%.*]] = bitcast <5 x i3> [[B]] to i15 685; CHECK-NEXT: [[R:%.*]] = icmp eq i15 [[TMP1]], 0 686; CHECK-NEXT: ret i1 [[R]] 687; 688 %e = zext <5 x i3> %b to <5 x i7> 689 store <5 x i7> %e, ptr %p 690 %bc = bitcast <5 x i7> %e to i35 691 %r = icmp eq i35 %bc, 0 692 ret i1 %r 693} 694 695; negative test - don't create an extra cast 696 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 i35 703; CHECK-NEXT: call void @use35(i35 [[BC]]) 704; CHECK-NEXT: [[R:%.*]] = icmp eq i35 [[BC]], 0 705; 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 i35 709 call void @use35(i35 %bc) 710 %r = icmp eq i35 %bc, 0 711 ret i1 %r 712} 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 i2 718; CHECK-NEXT: [[R:%.*]] = icmp eq i2 [[TMP2]], 0 719; CHECK-NEXT: ret i1 [[R]] 720; 721 %ic = icmp eq <2 x ptr> %x, %y 722 %b = bitcast <2 x i1> %ic to i2 723 %r = icmp eq i2 %b, -1 724 ret i1 %r 725} 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 i2 731; CHECK-NEXT: [[R:%.*]] = icmp ne i2 [[TMP2]], 0 732; CHECK-NEXT: ret i1 [[R]] 733; 734 %ic = icmp eq <2 x ptr> %x, %y 735 %b = bitcast <2 x i1> %ic to i2 736 %r = icmp ne i2 %b, -1 737 ret i1 %r 738} 739