1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; Instcombine should recognize that this code can be adjusted to fit the canonical max/min pattern. 5 6; No change 7 8define i32 @smax1(i32 %n) { 9; CHECK-LABEL: @smax1( 10; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0) 11; CHECK-NEXT: ret i32 [[M]] 12; 13 %t = icmp sgt i32 %n, 0 14 %m = select i1 %t, i32 %n, i32 0 15 ret i32 %m 16} 17 18; No change 19 20define i32 @smin1(i32 %n) { 21; CHECK-LABEL: @smin1( 22; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smin.i32(i32 [[N:%.*]], i32 0) 23; CHECK-NEXT: ret i32 [[M]] 24; 25 %t = icmp slt i32 %n, 0 26 %m = select i1 %t, i32 %n, i32 0 27 ret i32 %m 28} 29 30; Canonicalize min/max. 31 32define i32 @smax2(i32 %n) { 33; CHECK-LABEL: @smax2( 34; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0) 35; CHECK-NEXT: ret i32 [[M]] 36; 37 %t = icmp sge i32 %n, 1 38 %m = select i1 %t, i32 %n, i32 0 39 ret i32 %m 40} 41 42; Canonicalize min/max. 43 44define i32 @smin2(i32 %n) { 45; CHECK-LABEL: @smin2( 46; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smin.i32(i32 [[N:%.*]], i32 0) 47; CHECK-NEXT: ret i32 [[M]] 48; 49 %t = icmp sle i32 %n, -1 50 %m = select i1 %t, i32 %n, i32 0 51 ret i32 %m 52} 53 54; Canonicalize min/max. 55 56define i32 @smax3(i32 %n) { 57; CHECK-LABEL: @smax3( 58; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0) 59; CHECK-NEXT: ret i32 [[M]] 60; 61 %t = icmp sgt i32 %n, -1 62 %m = select i1 %t, i32 %n, i32 0 63 ret i32 %m 64} 65 66; Canonicalize min/max. 67 68define <2 x i32> @smax3_vec(<2 x i32> %n) { 69; CHECK-LABEL: @smax3_vec( 70; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[N:%.*]], <2 x i32> zeroinitializer) 71; CHECK-NEXT: ret <2 x i32> [[M]] 72; 73 %t = icmp sgt <2 x i32> %n, <i32 -1, i32 -1> 74 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer 75 ret <2 x i32> %m 76} 77 78; Canonicalize min/max. 79 80define i32 @smin3(i32 %n) { 81; CHECK-LABEL: @smin3( 82; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smin.i32(i32 [[N:%.*]], i32 0) 83; CHECK-NEXT: ret i32 [[M]] 84; 85 %t = icmp slt i32 %n, 1 86 %m = select i1 %t, i32 %n, i32 0 87 ret i32 %m 88} 89 90; Canonicalize min/max. 91 92define <2 x i32> @smin3_vec(<2 x i32> %n) { 93; CHECK-LABEL: @smin3_vec( 94; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[N:%.*]], <2 x i32> zeroinitializer) 95; CHECK-NEXT: ret <2 x i32> [[M]] 96; 97 %t = icmp slt <2 x i32> %n, <i32 1, i32 1> 98 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer 99 ret <2 x i32> %m 100} 101 102; Canonicalize min/max. 103 104define i32 @umax3(i32 %n) { 105; CHECK-LABEL: @umax3( 106; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 5) 107; CHECK-NEXT: ret i32 [[M]] 108; 109 %t = icmp ugt i32 %n, 4 110 %m = select i1 %t, i32 %n, i32 5 111 ret i32 %m 112} 113 114; Canonicalize min/max. 115 116define <2 x i32> @umax3_vec(<2 x i32> %n) { 117; CHECK-LABEL: @umax3_vec( 118; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[N:%.*]], <2 x i32> splat (i32 5)) 119; CHECK-NEXT: ret <2 x i32> [[M]] 120; 121 %t = icmp ugt <2 x i32> %n, <i32 4, i32 4> 122 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> <i32 5, i32 5> 123 ret <2 x i32> %m 124} 125 126; Canonicalize min/max. 127 128define i32 @umin3(i32 %n) { 129; CHECK-LABEL: @umin3( 130; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.umin.i32(i32 [[N:%.*]], i32 6) 131; CHECK-NEXT: ret i32 [[M]] 132; 133 %t = icmp ult i32 %n, 7 134 %m = select i1 %t, i32 %n, i32 6 135 ret i32 %m 136} 137 138; Canonicalize min/max. 139 140define <2 x i32> @umin3_vec(<2 x i32> %n) { 141; CHECK-LABEL: @umin3_vec( 142; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[N:%.*]], <2 x i32> splat (i32 6)) 143; CHECK-NEXT: ret <2 x i32> [[M]] 144; 145 %t = icmp ult <2 x i32> %n, <i32 7, i32 7> 146 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> <i32 6, i32 6> 147 ret <2 x i32> %m 148} 149 150; Canonicalize min/max. 151 152define i32 @smax4(i32 %n) { 153; CHECK-LABEL: @smax4( 154; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0) 155; CHECK-NEXT: ret i32 [[M]] 156; 157 %t = icmp sge i32 %n, 0 158 %m = select i1 %t, i32 %n, i32 0 159 ret i32 %m 160} 161 162; Canonicalize min/max. 163 164define <2 x i32> @smax4_vec(<2 x i32> %n) { 165; CHECK-LABEL: @smax4_vec( 166; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[N:%.*]], <2 x i32> zeroinitializer) 167; CHECK-NEXT: ret <2 x i32> [[M]] 168; 169 %t = icmp sge <2 x i32> %n, zeroinitializer 170 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer 171 ret <2 x i32> %m 172} 173 174; Canonicalize min/max. 175 176define i32 @smin4(i32 %n) { 177; CHECK-LABEL: @smin4( 178; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smin.i32(i32 [[N:%.*]], i32 0) 179; CHECK-NEXT: ret i32 [[M]] 180; 181 %t = icmp sle i32 %n, 0 182 %m = select i1 %t, i32 %n, i32 0 183 ret i32 %m 184} 185 186; Canonicalize min/max. 187 188define <2 x i32> @smin4_vec(<2 x i32> %n) { 189; CHECK-LABEL: @smin4_vec( 190; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[N:%.*]], <2 x i32> zeroinitializer) 191; CHECK-NEXT: ret <2 x i32> [[M]] 192; 193 %t = icmp sle <2 x i32> %n, zeroinitializer 194 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer 195 ret <2 x i32> %m 196} 197 198; Canonicalize min/max. 199 200define i32 @umax4(i32 %n) { 201; CHECK-LABEL: @umax4( 202; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 8) 203; CHECK-NEXT: ret i32 [[M]] 204; 205 %t = icmp uge i32 %n, 8 206 %m = select i1 %t, i32 %n, i32 8 207 ret i32 %m 208} 209 210; Canonicalize min/max. 211 212define <2 x i32> @umax4_vec(<2 x i32> %n) { 213; CHECK-LABEL: @umax4_vec( 214; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[N:%.*]], <2 x i32> splat (i32 8)) 215; CHECK-NEXT: ret <2 x i32> [[M]] 216; 217 %t = icmp uge <2 x i32> %n, <i32 8, i32 8> 218 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> <i32 8, i32 8> 219 ret <2 x i32> %m 220} 221 222; Canonicalize min/max. 223 224define i32 @umin4(i32 %n) { 225; CHECK-LABEL: @umin4( 226; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.umin.i32(i32 [[N:%.*]], i32 9) 227; CHECK-NEXT: ret i32 [[M]] 228; 229 %t = icmp ule i32 %n, 9 230 %m = select i1 %t, i32 %n, i32 9 231 ret i32 %m 232} 233 234; Canonicalize min/max. 235 236define <2 x i32> @umin4_vec(<2 x i32> %n) { 237; CHECK-LABEL: @umin4_vec( 238; CHECK-NEXT: [[M:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[N:%.*]], <2 x i32> splat (i32 9)) 239; CHECK-NEXT: ret <2 x i32> [[M]] 240; 241 %t = icmp ule <2 x i32> %n, <i32 9, i32 9> 242 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> <i32 9, i32 9> 243 ret <2 x i32> %m 244} 245 246define i64 @smax_sext(i32 %a) { 247; CHECK-LABEL: @smax_sext( 248; CHECK-NEXT: [[NARROW:%.*]] = call i32 @llvm.smax.i32(i32 [[A:%.*]], i32 0) 249; CHECK-NEXT: [[MAX:%.*]] = zext nneg i32 [[NARROW]] to i64 250; CHECK-NEXT: ret i64 [[MAX]] 251; 252 %a_ext = sext i32 %a to i64 253 %cmp = icmp sgt i32 %a, -1 254 %max = select i1 %cmp, i64 %a_ext, i64 0 255 ret i64 %max 256} 257 258define <2 x i64> @smax_sext_vec(<2 x i32> %a) { 259; CHECK-LABEL: @smax_sext_vec( 260; CHECK-NEXT: [[NARROW:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[A:%.*]], <2 x i32> zeroinitializer) 261; CHECK-NEXT: [[MAX:%.*]] = zext nneg <2 x i32> [[NARROW]] to <2 x i64> 262; CHECK-NEXT: ret <2 x i64> [[MAX]] 263; 264 %a_ext = sext <2 x i32> %a to <2 x i64> 265 %cmp = icmp sgt <2 x i32> %a, <i32 -1, i32 -1> 266 %max = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> zeroinitializer 267 ret <2 x i64> %max 268} 269 270define i64 @smin_sext(i32 %a) { 271; CHECK-LABEL: @smin_sext( 272; CHECK-NEXT: [[NARROW:%.*]] = call i32 @llvm.smin.i32(i32 [[A:%.*]], i32 0) 273; CHECK-NEXT: [[MIN:%.*]] = sext i32 [[NARROW]] to i64 274; CHECK-NEXT: ret i64 [[MIN]] 275; 276 %a_ext = sext i32 %a to i64 277 %cmp = icmp slt i32 %a, 1 278 %min = select i1 %cmp, i64 %a_ext, i64 0 279 ret i64 %min 280} 281 282define <2 x i64>@smin_sext_vec(<2 x i32> %a) { 283; CHECK-LABEL: @smin_sext_vec( 284; CHECK-NEXT: [[NARROW:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[A:%.*]], <2 x i32> zeroinitializer) 285; CHECK-NEXT: [[MIN:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64> 286; CHECK-NEXT: ret <2 x i64> [[MIN]] 287; 288 %a_ext = sext <2 x i32> %a to <2 x i64> 289 %cmp = icmp slt <2 x i32> %a, <i32 1, i32 1> 290 %min = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> zeroinitializer 291 ret <2 x i64> %min 292} 293 294define i64 @umax_sext(i32 %a) { 295; CHECK-LABEL: @umax_sext( 296; CHECK-NEXT: [[NARROW:%.*]] = call i32 @llvm.umax.i32(i32 [[A:%.*]], i32 3) 297; CHECK-NEXT: [[MAX:%.*]] = sext i32 [[NARROW]] to i64 298; CHECK-NEXT: ret i64 [[MAX]] 299; 300 %a_ext = sext i32 %a to i64 301 %cmp = icmp ugt i32 %a, 2 302 %max = select i1 %cmp, i64 %a_ext, i64 3 303 ret i64 %max 304} 305 306define <2 x i64> @umax_sext_vec(<2 x i32> %a) { 307; CHECK-LABEL: @umax_sext_vec( 308; CHECK-NEXT: [[NARROW:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 3)) 309; CHECK-NEXT: [[MAX:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64> 310; CHECK-NEXT: ret <2 x i64> [[MAX]] 311; 312 %a_ext = sext <2 x i32> %a to <2 x i64> 313 %cmp = icmp ugt <2 x i32> %a, <i32 2, i32 2> 314 %max = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> <i64 3, i64 3> 315 ret <2 x i64> %max 316} 317 318define i64 @umin_sext(i32 %a) { 319; CHECK-LABEL: @umin_sext( 320; CHECK-NEXT: [[NARROW:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 2) 321; CHECK-NEXT: [[MIN:%.*]] = zext nneg i32 [[NARROW]] to i64 322; CHECK-NEXT: ret i64 [[MIN]] 323; 324 %a_ext = sext i32 %a to i64 325 %cmp = icmp ult i32 %a, 3 326 %min = select i1 %cmp, i64 %a_ext, i64 2 327 ret i64 %min 328} 329 330define <2 x i64> @umin_sext_vec(<2 x i32> %a) { 331; CHECK-LABEL: @umin_sext_vec( 332; CHECK-NEXT: [[NARROW:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 2)) 333; CHECK-NEXT: [[MIN:%.*]] = zext nneg <2 x i32> [[NARROW]] to <2 x i64> 334; CHECK-NEXT: ret <2 x i64> [[MIN]] 335; 336 %a_ext = sext <2 x i32> %a to <2 x i64> 337 %cmp = icmp ult <2 x i32> %a, <i32 3, i32 3> 338 %min = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> <i64 2, i64 2> 339 ret <2 x i64> %min 340} 341 342define i64 @umax_sext2(i32 %a) { 343; CHECK-LABEL: @umax_sext2( 344; CHECK-NEXT: [[NARROW:%.*]] = call i32 @llvm.umax.i32(i32 [[A:%.*]], i32 2) 345; CHECK-NEXT: [[MIN:%.*]] = sext i32 [[NARROW]] to i64 346; CHECK-NEXT: ret i64 [[MIN]] 347; 348 %a_ext = sext i32 %a to i64 349 %cmp = icmp ult i32 %a, 3 350 %min = select i1 %cmp, i64 2, i64 %a_ext 351 ret i64 %min 352} 353 354define <2 x i64> @umax_sext2_vec(<2 x i32> %a) { 355; CHECK-LABEL: @umax_sext2_vec( 356; CHECK-NEXT: [[NARROW:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 2)) 357; CHECK-NEXT: [[MIN:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64> 358; CHECK-NEXT: ret <2 x i64> [[MIN]] 359; 360 %a_ext = sext <2 x i32> %a to <2 x i64> 361 %cmp = icmp ult <2 x i32> %a, <i32 3, i32 3> 362 %min = select <2 x i1> %cmp, <2 x i64> <i64 2, i64 2>, <2 x i64> %a_ext 363 ret <2 x i64> %min 364} 365 366define i64 @umin_sext2(i32 %a) { 367; CHECK-LABEL: @umin_sext2( 368; CHECK-NEXT: [[NARROW:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 3) 369; CHECK-NEXT: [[MIN:%.*]] = zext nneg i32 [[NARROW]] to i64 370; CHECK-NEXT: ret i64 [[MIN]] 371; 372 %a_ext = sext i32 %a to i64 373 %cmp = icmp ugt i32 %a, 2 374 %min = select i1 %cmp, i64 3, i64 %a_ext 375 ret i64 %min 376} 377 378define <2 x i64> @umin_sext2_vec(<2 x i32> %a) { 379; CHECK-LABEL: @umin_sext2_vec( 380; CHECK-NEXT: [[NARROW:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 3)) 381; CHECK-NEXT: [[MIN:%.*]] = zext nneg <2 x i32> [[NARROW]] to <2 x i64> 382; CHECK-NEXT: ret <2 x i64> [[MIN]] 383; 384 %a_ext = sext <2 x i32> %a to <2 x i64> 385 %cmp = icmp ugt <2 x i32> %a, <i32 2, i32 2> 386 %min = select <2 x i1> %cmp, <2 x i64> <i64 3, i64 3>, <2 x i64> %a_ext 387 ret <2 x i64> %min 388} 389 390define i64 @umax_zext(i32 %a) { 391; CHECK-LABEL: @umax_zext( 392; CHECK-NEXT: [[NARROW:%.*]] = call i32 @llvm.umax.i32(i32 [[A:%.*]], i32 3) 393; CHECK-NEXT: [[MAX:%.*]] = zext i32 [[NARROW]] to i64 394; CHECK-NEXT: ret i64 [[MAX]] 395; 396 %a_ext = zext i32 %a to i64 397 %cmp = icmp ugt i32 %a, 2 398 %max = select i1 %cmp, i64 %a_ext, i64 3 399 ret i64 %max 400} 401 402define <2 x i64> @umax_zext_vec(<2 x i32> %a) { 403; CHECK-LABEL: @umax_zext_vec( 404; CHECK-NEXT: [[NARROW:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 3)) 405; CHECK-NEXT: [[MAX:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64> 406; CHECK-NEXT: ret <2 x i64> [[MAX]] 407; 408 %a_ext = zext <2 x i32> %a to <2 x i64> 409 %cmp = icmp ugt <2 x i32> %a, <i32 2, i32 2> 410 %max = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> <i64 3, i64 3> 411 ret <2 x i64> %max 412} 413 414define i64 @umin_zext(i32 %a) { 415; CHECK-LABEL: @umin_zext( 416; CHECK-NEXT: [[NARROW:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 2) 417; CHECK-NEXT: [[MIN:%.*]] = zext nneg i32 [[NARROW]] to i64 418; CHECK-NEXT: ret i64 [[MIN]] 419; 420 %a_ext = zext i32 %a to i64 421 %cmp = icmp ult i32 %a, 3 422 %min = select i1 %cmp, i64 %a_ext, i64 2 423 ret i64 %min 424} 425 426define <2 x i64> @umin_zext_vec(<2 x i32> %a) { 427; CHECK-LABEL: @umin_zext_vec( 428; CHECK-NEXT: [[NARROW:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 2)) 429; CHECK-NEXT: [[MIN:%.*]] = zext nneg <2 x i32> [[NARROW]] to <2 x i64> 430; CHECK-NEXT: ret <2 x i64> [[MIN]] 431; 432 %a_ext = zext <2 x i32> %a to <2 x i64> 433 %cmp = icmp ult <2 x i32> %a, <i32 3, i32 3> 434 %min = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> <i64 2, i64 2> 435 ret <2 x i64> %min 436} 437 438; Don't crash mishandling a pattern that can't be transformed. 439 440define <2 x i16> @scalar_select_of_vectors(<2 x i16> %a, <2 x i16> %b, i8 %x) { 441; CHECK-LABEL: @scalar_select_of_vectors( 442; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 443; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], <2 x i16> [[A:%.*]], <2 x i16> [[B:%.*]] 444; CHECK-NEXT: ret <2 x i16> [[SEL]] 445; 446 %cmp = icmp slt i8 %x, 0 447 %sel = select i1 %cmp, <2 x i16> %a, <2 x i16> %b 448 ret <2 x i16> %sel 449} 450 451