1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4declare i1 @llvm.umin.i1(i1, i1) 5declare i8 @llvm.umin.i8(i8, i8) 6declare i8 @llvm.umax.i8(i8, i8) 7declare i8 @llvm.smin.i8(i8, i8) 8declare i8 @llvm.smax.i8(i8, i8) 9declare <3 x i8> @llvm.umin.v3i8(<3 x i8>, <3 x i8>) 10declare <3 x i8> @llvm.umax.v3i8(<3 x i8>, <3 x i8>) 11declare <3 x i8> @llvm.smin.v3i8(<3 x i8>, <3 x i8>) 12declare <3 x i8> @llvm.smax.v3i8(<3 x i8>, <3 x i8>) 13declare void @use(i8) 14declare void @use_vec(<3 x i8>) 15 16define i8 @umin_known_bits(i8 %x, i8 %y) { 17; CHECK-LABEL: @umin_known_bits( 18; CHECK-NEXT: ret i8 0 19; 20 %x2 = and i8 %x, 127 21 %m = call i8 @llvm.umin.i8(i8 %x2, i8 %y) 22 %r = and i8 %m, -128 23 ret i8 %r 24} 25 26define i8 @umax_known_bits(i8 %x, i8 %y) { 27; CHECK-LABEL: @umax_known_bits( 28; CHECK-NEXT: ret i8 -128 29; 30 %x2 = or i8 %x, -128 31 %m = call i8 @llvm.umax.i8(i8 %x2, i8 %y) 32 %r = and i8 %m, -128 33 ret i8 %r 34} 35 36define i8 @smin_known_bits(i8 %x, i8 %y) { 37; CHECK-LABEL: @smin_known_bits( 38; CHECK-NEXT: ret i8 -128 39; 40 %x2 = or i8 %x, -128 41 %m = call i8 @llvm.smin.i8(i8 %x2, i8 %y) 42 %r = and i8 %m, -128 43 ret i8 %r 44} 45 46define i8 @smax_known_bits(i8 %x, i8 %y) { 47; CHECK-LABEL: @smax_known_bits( 48; CHECK-NEXT: ret i8 0 49; 50 %x2 = and i8 %x, 127 51 %m = call i8 @llvm.smax.i8(i8 %x2, i8 %y) 52 %r = and i8 %m, -128 53 ret i8 %r 54} 55 56define i8 @smax_sext(i5 %x, i5 %y) { 57; CHECK-LABEL: @smax_sext( 58; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 [[Y:%.*]]) 59; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8 60; CHECK-NEXT: ret i8 [[M]] 61; 62 %sx = sext i5 %x to i8 63 %sy = sext i5 %y to i8 64 %m = call i8 @llvm.smax.i8(i8 %sx, i8 %sy) 65 ret i8 %m 66} 67 68; Extra use is ok. 69 70define i8 @smin_sext(i5 %x, i5 %y) { 71; CHECK-LABEL: @smin_sext( 72; CHECK-NEXT: [[SY:%.*]] = sext i5 [[Y:%.*]] to i8 73; CHECK-NEXT: call void @use(i8 [[SY]]) 74; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 [[Y]]) 75; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8 76; CHECK-NEXT: ret i8 [[M]] 77; 78 %sx = sext i5 %x to i8 79 %sy = sext i5 %y to i8 80 call void @use(i8 %sy) 81 %m = call i8 @llvm.smin.i8(i8 %sx, i8 %sy) 82 ret i8 %m 83} 84 85; Sext doesn't change unsigned min/max comparison of narrow values. 86 87define i8 @umax_sext(i5 %x, i5 %y) { 88; CHECK-LABEL: @umax_sext( 89; CHECK-NEXT: [[SX:%.*]] = sext i5 [[X:%.*]] to i8 90; CHECK-NEXT: call void @use(i8 [[SX]]) 91; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X]], i5 [[Y:%.*]]) 92; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8 93; CHECK-NEXT: ret i8 [[M]] 94; 95 %sx = sext i5 %x to i8 96 call void @use(i8 %sx) 97 %sy = sext i5 %y to i8 98 %m = call i8 @llvm.umax.i8(i8 %sx, i8 %sy) 99 ret i8 %m 100} 101 102define <3 x i8> @umin_sext(<3 x i5> %x, <3 x i5> %y) { 103; CHECK-LABEL: @umin_sext( 104; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.umin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> [[Y:%.*]]) 105; CHECK-NEXT: [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8> 106; CHECK-NEXT: ret <3 x i8> [[M]] 107; 108 %sx = sext <3 x i5> %x to <3 x i8> 109 %sy = sext <3 x i5> %y to <3 x i8> 110 %m = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy) 111 ret <3 x i8> %m 112} 113 114; Negative test - zext may change sign of inputs 115 116define i8 @smax_zext(i5 %x, i5 %y) { 117; CHECK-LABEL: @smax_zext( 118; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8 119; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8 120; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[ZX]], i8 [[ZY]]) 121; CHECK-NEXT: ret i8 [[M]] 122; 123 %zx = zext i5 %x to i8 124 %zy = zext i5 %y to i8 125 %m = call i8 @llvm.smax.i8(i8 %zx, i8 %zy) 126 ret i8 %m 127} 128 129; Negative test - zext may change sign of inputs 130 131define i8 @smin_zext(i5 %x, i5 %y) { 132; CHECK-LABEL: @smin_zext( 133; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8 134; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8 135; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[ZX]], i8 [[ZY]]) 136; CHECK-NEXT: ret i8 [[M]] 137; 138 %zx = zext i5 %x to i8 139 %zy = zext i5 %y to i8 140 %m = call i8 @llvm.smin.i8(i8 %zx, i8 %zy) 141 ret i8 %m 142} 143 144define i8 @umax_zext(i5 %x, i5 %y) { 145; CHECK-LABEL: @umax_zext( 146; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 [[Y:%.*]]) 147; CHECK-NEXT: [[M:%.*]] = zext i5 [[TMP1]] to i8 148; CHECK-NEXT: ret i8 [[M]] 149; 150 %zx = zext i5 %x to i8 151 %zy = zext i5 %y to i8 152 %m = call i8 @llvm.umax.i8(i8 %zx, i8 %zy) 153 ret i8 %m 154} 155 156define i8 @umin_zext(i5 %x, i5 %y) { 157; CHECK-LABEL: @umin_zext( 158; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 [[Y:%.*]]) 159; CHECK-NEXT: [[M:%.*]] = zext i5 [[TMP1]] to i8 160; CHECK-NEXT: ret i8 [[M]] 161; 162 %zx = zext i5 %x to i8 163 %zy = zext i5 %y to i8 164 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy) 165 ret i8 %m 166} 167 168; Negative test - mismatched types 169 170define i8 @umin_zext_types(i6 %x, i5 %y) { 171; CHECK-LABEL: @umin_zext_types( 172; CHECK-NEXT: [[ZX:%.*]] = zext i6 [[X:%.*]] to i8 173; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8 174; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]]) 175; CHECK-NEXT: ret i8 [[M]] 176; 177 %zx = zext i6 %x to i8 178 %zy = zext i5 %y to i8 179 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy) 180 ret i8 %m 181} 182 183; Negative test - mismatched extends 184 185define i8 @umin_ext(i5 %x, i5 %y) { 186; CHECK-LABEL: @umin_ext( 187; CHECK-NEXT: [[SX:%.*]] = sext i5 [[X:%.*]] to i8 188; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8 189; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[SX]], i8 [[ZY]]) 190; CHECK-NEXT: ret i8 [[M]] 191; 192 %sx = sext i5 %x to i8 193 %zy = zext i5 %y to i8 194 %m = call i8 @llvm.umin.i8(i8 %sx, i8 %zy) 195 ret i8 %m 196} 197 198; Negative test - too many uses. 199 200define i8 @umin_zext_uses(i5 %x, i5 %y) { 201; CHECK-LABEL: @umin_zext_uses( 202; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i8 203; CHECK-NEXT: call void @use(i8 [[ZX]]) 204; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i8 205; CHECK-NEXT: call void @use(i8 [[ZY]]) 206; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[ZX]], i8 [[ZY]]) 207; CHECK-NEXT: ret i8 [[M]] 208; 209 %zx = zext i5 %x to i8 210 call void @use(i8 %zx) 211 %zy = zext i5 %y to i8 212 call void @use(i8 %zy) 213 %m = call i8 @llvm.umin.i8(i8 %zx, i8 %zy) 214 ret i8 %m 215} 216 217define i8 @smax_sext_constant(i5 %x) { 218; CHECK-LABEL: @smax_sext_constant( 219; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 7) 220; CHECK-NEXT: [[M:%.*]] = zext nneg i5 [[TMP1]] to i8 221; CHECK-NEXT: ret i8 [[M]] 222; 223 %e = sext i5 %x to i8 224 %m = call i8 @llvm.smax.i8(i8 %e, i8 7) 225 ret i8 %m 226} 227 228; simplifies 229 230define i8 @smax_sext_constant_big(i5 %x) { 231; CHECK-LABEL: @smax_sext_constant_big( 232; CHECK-NEXT: ret i8 16 233; 234 %e = sext i5 %x to i8 235 %m = call i8 @llvm.smax.i8(i8 %e, i8 16) 236 ret i8 %m 237} 238 239; negative test 240 241define i8 @smax_zext_constant(i5 %x) { 242; CHECK-LABEL: @smax_zext_constant( 243; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8 244; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[E]], i8 7) 245; CHECK-NEXT: ret i8 [[M]] 246; 247 %e = zext i5 %x to i8 248 %m = call i8 @llvm.smax.i8(i8 %e, i8 7) 249 ret i8 %m 250} 251 252define <3 x i8> @smin_sext_constant(<3 x i5> %x) { 253; CHECK-LABEL: @smin_sext_constant( 254; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.smin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -16>) 255; CHECK-NEXT: [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8> 256; CHECK-NEXT: ret <3 x i8> [[M]] 257; 258 %e = sext <3 x i5> %x to <3 x i8> 259 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 -16>) 260 ret <3 x i8> %m 261} 262 263; negative test 264 265define i8 @smin_zext_constant(i5 %x) { 266; CHECK-LABEL: @smin_zext_constant( 267; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8 268; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[E]], i8 7) 269; CHECK-NEXT: ret i8 [[M]] 270; 271 %e = zext i5 %x to i8 272 %m = call i8 @llvm.smin.i8(i8 %e, i8 7) 273 ret i8 %m 274} 275 276define i8 @umax_sext_constant(i5 %x) { 277; CHECK-LABEL: @umax_sext_constant( 278; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 7) 279; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8 280; CHECK-NEXT: ret i8 [[M]] 281; 282 %e = sext i5 %x to i8 283 %m = call i8 @llvm.umax.i8(i8 %e, i8 7) 284 ret i8 %m 285} 286 287; negative test 288 289define i8 @umax_sext_constant_big(i5 %x) { 290; CHECK-LABEL: @umax_sext_constant_big( 291; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8 292; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[E]], i8 126) 293; CHECK-NEXT: ret i8 [[M]] 294; 295 %e = sext i5 %x to i8 296 %m = call i8 @llvm.umax.i8(i8 %e, i8 126) 297 ret i8 %m 298} 299 300define <3 x i8> @umax_zext_constant(<3 x i5> %x) { 301; CHECK-LABEL: @umax_zext_constant( 302; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -1>) 303; CHECK-NEXT: [[M:%.*]] = zext <3 x i5> [[TMP1]] to <3 x i8> 304; CHECK-NEXT: ret <3 x i8> [[M]] 305; 306 %e = zext <3 x i5> %x to <3 x i8> 307 %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %e, <3 x i8> <i8 7, i8 15, i8 31>) 308 ret <3 x i8> %m 309} 310 311; simplifies 312 313define i8 @umax_zext_constant_big(i5 %x) { 314; CHECK-LABEL: @umax_zext_constant_big( 315; CHECK-NEXT: ret i8 126 316; 317 %e = zext i5 %x to i8 318 %m = call i8 @llvm.umax.i8(i8 %e, i8 126) 319 ret i8 %m 320} 321 322define i8 @umin_sext_constant(i5 %x) { 323; CHECK-LABEL: @umin_sext_constant( 324; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7) 325; CHECK-NEXT: [[M:%.*]] = zext nneg i5 [[TMP1]] to i8 326; CHECK-NEXT: ret i8 [[M]] 327; 328 %e = sext i5 %x to i8 329 %m = call i8 @llvm.umin.i8(i8 %e, i8 7) 330 ret i8 %m 331} 332 333; negative test 334 335define i8 @umin_sext_constant_big(i5 %x) { 336; CHECK-LABEL: @umin_sext_constant_big( 337; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8 338; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 126) 339; CHECK-NEXT: ret i8 [[M]] 340; 341 %e = sext i5 %x to i8 342 %m = call i8 @llvm.umin.i8(i8 %e, i8 126) 343 ret i8 %m 344} 345 346define i8 @umin_zext_constant(i5 %x) { 347; CHECK-LABEL: @umin_zext_constant( 348; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7) 349; CHECK-NEXT: [[M:%.*]] = zext nneg i5 [[TMP1]] to i8 350; CHECK-NEXT: ret i8 [[M]] 351; 352 %e = zext i5 %x to i8 353 %m = call i8 @llvm.umin.i8(i8 %e, i8 7) 354 ret i8 %m 355} 356 357; simplifies 358 359define i8 @umin_zext_constant_big(i5 %x) { 360; CHECK-LABEL: @umin_zext_constant_big( 361; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8 362; CHECK-NEXT: ret i8 [[E]] 363; 364 %e = zext i5 %x to i8 365 %m = call i8 @llvm.umin.i8(i8 %e, i8 126) 366 ret i8 %m 367} 368 369; negative test 370 371define i8 @umin_zext_constant_uses(i5 %x) { 372; CHECK-LABEL: @umin_zext_constant_uses( 373; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8 374; CHECK-NEXT: call void @use(i8 [[E]]) 375; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7) 376; CHECK-NEXT: ret i8 [[M]] 377; 378 %e = zext i5 %x to i8 379 call void @use(i8 %e) 380 %m = call i8 @llvm.umin.i8(i8 %e, i8 7) 381 ret i8 %m 382} 383 384define i8 @smax_of_nots(i8 %x, i8 %y) { 385; CHECK-LABEL: @smax_of_nots( 386; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 387; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1 388; CHECK-NEXT: ret i8 [[M]] 389; 390 %notx = xor i8 %x, -1 391 %noty = xor i8 %y, -1 392 %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty) 393 ret i8 %m 394} 395 396; Vectors are ok (including poison lanes of not ops) 397 398define <3 x i8> @smin_of_nots(<3 x i8> %x, <3 x i8> %y) { 399; CHECK-LABEL: @smin_of_nots( 400; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) 401; CHECK-NEXT: [[M:%.*]] = xor <3 x i8> [[TMP1]], splat (i8 -1) 402; CHECK-NEXT: ret <3 x i8> [[M]] 403; 404 %notx = xor <3 x i8> %x, <i8 -1, i8 poison, i8 -1> 405 %noty = xor <3 x i8> %y, <i8 -1, i8 -1, i8 poison> 406 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %notx, <3 x i8> %noty) 407 ret <3 x i8> %m 408} 409 410; An extra use is ok. 411 412define i8 @umax_of_nots(i8 %x, i8 %y) { 413; CHECK-LABEL: @umax_of_nots( 414; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 415; CHECK-NEXT: call void @use(i8 [[NOTX]]) 416; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X]]) 417; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1 418; CHECK-NEXT: ret i8 [[M]] 419; 420 %notx = xor i8 %x, -1 421 call void @use(i8 %notx) 422 %noty = xor i8 %y, -1 423 %m = call i8 @llvm.umax.i8(i8 %notx, i8 %noty) 424 ret i8 %m 425} 426 427; An extra use is ok. 428 429define i8 @umin_of_nots(i8 %x, i8 %y) { 430; CHECK-LABEL: @umin_of_nots( 431; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1 432; CHECK-NEXT: call void @use(i8 [[NOTY]]) 433; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y]]) 434; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1 435; CHECK-NEXT: ret i8 [[M]] 436; 437 %notx = xor i8 %x, -1 438 %noty = xor i8 %y, -1 439 call void @use(i8 %noty) 440 %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty) 441 ret i8 %m 442} 443 444; Negative test - too many uses 445 446define i8 @umin_of_nots_uses(i8 %x, i8 %y) { 447; CHECK-LABEL: @umin_of_nots_uses( 448; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 449; CHECK-NEXT: call void @use(i8 [[NOTX]]) 450; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1 451; CHECK-NEXT: call void @use(i8 [[NOTY]]) 452; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[NOTY]]) 453; CHECK-NEXT: ret i8 [[M]] 454; 455 %notx = xor i8 %x, -1 456 call void @use(i8 %notx) 457 %noty = xor i8 %y, -1 458 call void @use(i8 %noty) 459 %m = call i8 @llvm.umin.i8(i8 %notx, i8 %noty) 460 ret i8 %m 461} 462 463; Canonicalize 'not' after min/max. 464 465define i8 @smax_of_not_and_const(i8 %x) { 466; CHECK-LABEL: @smax_of_not_and_const( 467; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -43) 468; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1 469; CHECK-NEXT: ret i8 [[M]] 470; 471 %notx = xor i8 %x, -1 472 %m = call i8 @llvm.smax.i8(i8 %notx, i8 42) 473 ret i8 %m 474} 475 476; Vectors are ok (including poison lanes of not ops and min/max constant operand) 477 478define <3 x i8> @smin_of_not_and_const(<3 x i8> %x) { 479; CHECK-LABEL: @smin_of_not_and_const( 480; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 -43, i8 poison, i8 -44>) 481; CHECK-NEXT: [[M:%.*]] = xor <3 x i8> [[TMP1]], splat (i8 -1) 482; CHECK-NEXT: ret <3 x i8> [[M]] 483; 484 %notx = xor <3 x i8> %x, <i8 -1, i8 -1, i8 poison> 485 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> <i8 42, i8 poison, i8 43>, <3 x i8> %notx) 486 ret <3 x i8> %m 487} 488 489define i8 @umax_of_not_and_const(i8 %x) { 490; CHECK-LABEL: @umax_of_not_and_const( 491; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 -45) 492; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1 493; CHECK-NEXT: ret i8 [[M]] 494; 495 %notx = xor i8 %x, -1 496 %m = call i8 @llvm.umax.i8(i8 %notx, i8 44) 497 ret i8 %m 498} 499 500define i8 @umin_of_not_and_const(i8 %x) { 501; CHECK-LABEL: @umin_of_not_and_const( 502; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 44) 503; CHECK-NEXT: [[M:%.*]] = xor i8 [[TMP1]], -1 504; CHECK-NEXT: ret i8 [[M]] 505; 506 %notx = xor i8 %x, -1 507 %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx) 508 ret i8 %m 509} 510 511define i8 @umin_of_not_and_smax(i8 %x, i8 %y, i8 %z) { 512; CHECK-LABEL: @umin_of_not_and_smax( 513; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1 514; CHECK-NEXT: call void @use(i8 [[NOTY]]) 515; CHECK-NEXT: [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1 516; CHECK-NEXT: call void @use(i8 [[NOTZ]]) 517; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[Z]]) 518; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[TMP1]]) 519; CHECK-NEXT: [[M2:%.*]] = xor i8 [[TMP2]], -1 520; CHECK-NEXT: ret i8 [[M2]] 521; 522 %notx = xor i8 %x, -1 523 %noty = xor i8 %y, -1 524 call void @use(i8 %noty) 525 %notz = xor i8 %z, -1 526 call void @use(i8 %notz) 527 %m1 = call i8 @llvm.smax.i8(i8 %noty, i8 %notz) 528 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %notx) 529 ret i8 %m2 530} 531 532define i8 @smin_of_umax_and_not(i8 %x, i8 %y, i8 %z) { 533; CHECK-LABEL: @smin_of_umax_and_not( 534; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1 535; CHECK-NEXT: call void @use(i8 [[NOTY]]) 536; CHECK-NEXT: [[NOTZ:%.*]] = xor i8 [[Z:%.*]], -1 537; CHECK-NEXT: call void @use(i8 [[NOTZ]]) 538; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]]) 539; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[TMP1]]) 540; CHECK-NEXT: [[M2:%.*]] = xor i8 [[TMP2]], -1 541; CHECK-NEXT: ret i8 [[M2]] 542; 543 %notx = xor i8 %x, -1 544 %noty = xor i8 %y, -1 545 call void @use(i8 %noty) 546 %notz = xor i8 %z, -1 547 call void @use(i8 %notz) 548 %m1 = call i8 @llvm.umax.i8(i8 %noty, i8 %notz) 549 %m2 = call i8 @llvm.smin.i8(i8 %notx, i8 %m1) 550 ret i8 %m2 551} 552 553; Negative test - don't infinite loop on constant expression 554 555define i8 @umin_of_not_and_nontrivial_const(i8 %x) { 556; CHECK-LABEL: @umin_of_not_and_nontrivial_const( 557; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 558; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 ptrtoint (ptr @umin_of_not_and_nontrivial_const to i8)) 559; CHECK-NEXT: ret i8 [[M]] 560; 561 %notx = xor i8 %x, -1 562 %m = call i8 @llvm.umin.i8(i8 ptrtoint (ptr @umin_of_not_and_nontrivial_const to i8), i8 %notx) 563 ret i8 %m 564} 565 566; Negative test - too many uses 567 568define i8 @umin_of_not_and_const_uses(i8 %x) { 569; CHECK-LABEL: @umin_of_not_and_const_uses( 570; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 571; CHECK-NEXT: call void @use(i8 [[NOTX]]) 572; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 -45) 573; CHECK-NEXT: ret i8 [[M]] 574; 575 %notx = xor i8 %x, -1 576 call void @use(i8 %notx) 577 %m = call i8 @llvm.umin.i8(i8 -45, i8 %notx) 578 ret i8 %m 579} 580 581define i8 @not_smax_of_nots(i8 %x, i8 %y) { 582; CHECK-LABEL: @not_smax_of_nots( 583; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 584; CHECK-NEXT: call void @use(i8 [[NOTX]]) 585; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1 586; CHECK-NEXT: call void @use(i8 [[NOTY]]) 587; CHECK-NEXT: [[NOTM:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]]) 588; CHECK-NEXT: ret i8 [[NOTM]] 589; 590 %notx = xor i8 %x, -1 591 call void @use(i8 %notx) 592 %noty = xor i8 %y, -1 593 call void @use(i8 %noty) 594 %m = call i8 @llvm.smax.i8(i8 %notx, i8 %noty) 595 %notm = xor i8 %m, -1 596 ret i8 %notm 597} 598 599define i8 @not_smin_of_nots(i8 %x, i8 %y) { 600; CHECK-LABEL: @not_smin_of_nots( 601; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 602; CHECK-NEXT: call void @use(i8 [[NOTX]]) 603; CHECK-NEXT: [[NOTY:%.*]] = xor i8 [[Y:%.*]], -1 604; CHECK-NEXT: call void @use(i8 [[NOTY]]) 605; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTX]], i8 [[NOTY]]) 606; CHECK-NEXT: call void @use(i8 [[M]]) 607; CHECK-NEXT: [[NOTM:%.*]] = xor i8 [[M]], -1 608; CHECK-NEXT: ret i8 [[NOTM]] 609; 610 %notx = xor i8 %x, -1 611 call void @use(i8 %notx) 612 %noty = xor i8 %y, -1 613 call void @use(i8 %noty) 614 %m = call i8 @llvm.smin.i8(i8 %notx, i8 %noty) 615 call void @use(i8 %m) 616 %notm = xor i8 %m, -1 617 ret i8 %notm 618} 619 620define i8 @not_umax_of_not(i8 %x, i8 %y) { 621; CHECK-LABEL: @not_umax_of_not( 622; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 623; CHECK-NEXT: call void @use(i8 [[NOTX]]) 624; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1 625; CHECK-NEXT: [[NOTM:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[TMP1]]) 626; CHECK-NEXT: ret i8 [[NOTM]] 627; 628 %notx = xor i8 %x, -1 629 call void @use(i8 %notx) 630 %m = call i8 @llvm.umax.i8(i8 %notx, i8 %y) 631 %notm = xor i8 %m, -1 632 ret i8 %notm 633} 634 635; Negative test - this would require an extra instruction. 636 637define i8 @not_umin_of_not(i8 %x, i8 %y) { 638; CHECK-LABEL: @not_umin_of_not( 639; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 640; CHECK-NEXT: call void @use(i8 [[NOTX]]) 641; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NOTX]], i8 [[Y:%.*]]) 642; CHECK-NEXT: call void @use(i8 [[M]]) 643; CHECK-NEXT: [[NOTM:%.*]] = xor i8 [[M]], -1 644; CHECK-NEXT: ret i8 [[NOTM]] 645; 646 %notx = xor i8 %x, -1 647 call void @use(i8 %notx) 648 %m = call i8 @llvm.umin.i8(i8 %notx, i8 %y) 649 call void @use(i8 %m) 650 %notm = xor i8 %m, -1 651 ret i8 %notm 652} 653 654define i8 @not_umin_of_not_constant_op(i8 %x) { 655; CHECK-LABEL: @not_umin_of_not_constant_op( 656; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1 657; CHECK-NEXT: call void @use(i8 [[NOTX]]) 658; CHECK-NEXT: [[NOTM:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 -43) 659; CHECK-NEXT: ret i8 [[NOTM]] 660; 661 %notx = xor i8 %x, -1 662 call void @use(i8 %notx) 663 %m = call i8 @llvm.umin.i8(i8 %notx, i8 42) 664 %notm = xor i8 %m, -1 665 ret i8 %notm 666} 667 668define i8 @smax_negation(i8 %x, i8 %y) { 669; CHECK-LABEL: @smax_negation( 670; CHECK-NEXT: [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]] 671; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false) 672; CHECK-NEXT: ret i8 [[R]] 673; 674 %s1 = sub i8 %x, %y 675 %s2 = sub i8 %y, %x 676 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2) 677 ret i8 %r 678} 679 680define i8 @smax_negation_nsw(i8 %x, i8 %y) { 681; CHECK-LABEL: @smax_negation_nsw( 682; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]] 683; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true) 684; CHECK-NEXT: ret i8 [[R]] 685; 686 %s1 = sub nsw i8 %x, %y 687 %s2 = sub nsw i8 %y, %x 688 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2) 689 ret i8 %r 690} 691 692define i8 @smax_negation_not_nsw(i8 %x, i8 %y) { 693; CHECK-LABEL: @smax_negation_not_nsw( 694; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]] 695; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false) 696; CHECK-NEXT: ret i8 [[R]] 697; 698 %s1 = sub nsw i8 %x, %y 699 %s2 = sub nuw i8 %y, %x 700 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2) 701 ret i8 %r 702} 703 704define <3 x i8> @smax_negation_vec(<3 x i8> %x) { 705; CHECK-LABEL: @smax_negation_vec( 706; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8> [[X:%.*]], i1 false) 707; CHECK-NEXT: ret <3 x i8> [[R]] 708; 709 %s = sub <3 x i8> <i8 0, i8 poison, i8 0>, %x 710 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s) 711 ret <3 x i8> %r 712} 713 714define i8 @smin_negation(i8 %x, i8 %y) { 715; CHECK-LABEL: @smin_negation( 716; CHECK-NEXT: [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]] 717; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false) 718; CHECK-NEXT: [[NABS:%.*]] = sub i8 0, [[TMP1]] 719; CHECK-NEXT: ret i8 [[NABS]] 720; 721 %s1 = sub i8 %x, %y 722 %s2 = sub i8 %y, %x 723 %r = call i8 @llvm.smin.i8(i8 %s1, i8 %s2) 724 ret i8 %r 725} 726 727define i8 @umax_negation(i8 %x, i8 %y) { 728; CHECK-LABEL: @umax_negation( 729; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]] 730; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true) 731; CHECK-NEXT: [[NABS:%.*]] = sub nsw i8 0, [[TMP1]] 732; CHECK-NEXT: ret i8 [[NABS]] 733; 734 %s1 = sub nsw i8 %x, %y 735 %s2 = sub nsw i8 %y, %x 736 %r = call i8 @llvm.umax.i8(i8 %s1, i8 %s2) 737 ret i8 %r 738} 739 740define i8 @umin_negation(i8 %x) { 741; CHECK-LABEL: @umin_negation( 742; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true) 743; CHECK-NEXT: ret i8 [[R]] 744; 745 %s = sub nsw i8 0, %x 746 %r = call i8 @llvm.umin.i8(i8 %s, i8 %x) 747 ret i8 %r 748} 749 750define i8 @smax_negation_uses(i8 %x, i8 %y) { 751; CHECK-LABEL: @smax_negation_uses( 752; CHECK-NEXT: [[S2:%.*]] = sub i8 [[Y:%.*]], [[X:%.*]] 753; CHECK-NEXT: call void @use(i8 [[S2]]) 754; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[S2]], i1 false) 755; CHECK-NEXT: ret i8 [[R]] 756; 757 %s1 = sub i8 %x, %y 758 %s2 = sub i8 %y, %x 759 call void @use(i8 %s2) 760 %r = call i8 @llvm.smax.i8(i8 %s1, i8 %s2) 761 ret i8 %r 762} 763 764define i8 @clamp_two_vals_smax_smin(i8 %x) { 765; CHECK-LABEL: @clamp_two_vals_smax_smin( 766; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 43 767; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43 768; CHECK-NEXT: ret i8 [[R]] 769; 770 %m = call i8 @llvm.smax.i8(i8 %x, i8 42) 771 %r = call i8 @llvm.smin.i8(i8 %m, i8 43) 772 ret i8 %r 773} 774 775define <3 x i8> @clamp_two_vals_smin_smax(<3 x i8> %x) { 776; CHECK-LABEL: @clamp_two_vals_smin_smax( 777; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], splat (i8 41) 778; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i8> splat (i8 42), <3 x i8> splat (i8 41) 779; CHECK-NEXT: ret <3 x i8> [[R]] 780; 781 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 42, i8 42>) 782 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m, <3 x i8> <i8 41, i8 41, i8 41>) 783 ret <3 x i8> %r 784} 785 786define i8 @clamp_two_vals_umax_umin(i8 %x) { 787; CHECK-LABEL: @clamp_two_vals_umax_umin( 788; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 43 789; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 43 790; CHECK-NEXT: ret i8 [[R]] 791; 792 %m = call i8 @llvm.umax.i8(i8 %x, i8 42) 793 %r = call i8 @llvm.umin.i8(i8 %m, i8 43) 794 ret i8 %r 795} 796 797define i8 @clamp_two_vals_umin_umax(i8 %x) { 798; CHECK-LABEL: @clamp_two_vals_umin_umax( 799; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], 41 800; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 42, i8 41 801; CHECK-NEXT: ret i8 [[R]] 802; 803 %m = call i8 @llvm.umin.i8(i8 %x, i8 42) 804 %r = call i8 @llvm.umax.i8(i8 %m, i8 41) 805 ret i8 %r 806} 807 808; Negative test - mismatched signs 809 810define i8 @clamp_two_vals_smax_umin(i8 %x) { 811; CHECK-LABEL: @clamp_two_vals_smax_umin( 812; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42) 813; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[M]], i8 43) 814; CHECK-NEXT: ret i8 [[R]] 815; 816 %m = call i8 @llvm.smax.i8(i8 %x, i8 42) 817 %r = call i8 @llvm.umin.i8(i8 %m, i8 43) 818 ret i8 %r 819} 820 821; Negative test - wrong range 822 823define i8 @clamp_three_vals_smax_smin(i8 %x) { 824; CHECK-LABEL: @clamp_three_vals_smax_smin( 825; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 42) 826; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 44) 827; CHECK-NEXT: ret i8 [[R]] 828; 829 %m = call i8 @llvm.smax.i8(i8 %x, i8 42) 830 %r = call i8 @llvm.smin.i8(i8 %m, i8 44) 831 ret i8 %r 832} 833 834; Edge cases are simplified 835 836define i8 @clamp_two_vals_umax_umin_edge(i8 %x) { 837; CHECK-LABEL: @clamp_two_vals_umax_umin_edge( 838; CHECK-NEXT: ret i8 0 839; 840 %m = call i8 @llvm.umax.i8(i8 %x, i8 255) 841 %r = call i8 @llvm.umin.i8(i8 %m, i8 0) 842 ret i8 %r 843} 844 845; Edge cases are simplified 846 847define i8 @clamp_two_vals_umin_umax_edge(i8 %x) { 848; CHECK-LABEL: @clamp_two_vals_umin_umax_edge( 849; CHECK-NEXT: ret i8 -1 850; 851 %m = call i8 @llvm.umin.i8(i8 %x, i8 0) 852 %r = call i8 @llvm.umax.i8(i8 %m, i8 255) 853 ret i8 %r 854} 855 856; Edge cases are simplified 857 858define i8 @clamp_two_vals_smax_smin_edge(i8 %x) { 859; CHECK-LABEL: @clamp_two_vals_smax_smin_edge( 860; CHECK-NEXT: ret i8 -128 861; 862 %m = call i8 @llvm.smax.i8(i8 %x, i8 127) 863 %r = call i8 @llvm.smin.i8(i8 %m, i8 128) 864 ret i8 %r 865} 866 867; Edge cases are simplified 868 869define i8 @clamp_two_vals_smin_smax_edge(i8 %x) { 870; CHECK-LABEL: @clamp_two_vals_smin_smax_edge( 871; CHECK-NEXT: ret i8 127 872; 873 %m = call i8 @llvm.smin.i8(i8 %x, i8 128) 874 %r = call i8 @llvm.smax.i8(i8 %m, i8 127) 875 ret i8 %r 876} 877 878 879define i8 @umin_non_zero_idiom1(i8 %a) { 880; CHECK-LABEL: @umin_non_zero_idiom1( 881; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0 882; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8 883; CHECK-NEXT: ret i8 [[RES]] 884; 885 %res = call i8 @llvm.umin.i8(i8 %a, i8 1) 886 ret i8 %res 887} 888 889define i8 @umin_non_zero_idiom2(i8 %a) { 890; CHECK-LABEL: @umin_non_zero_idiom2( 891; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0 892; CHECK-NEXT: [[RES:%.*]] = zext i1 [[TMP1]] to i8 893; CHECK-NEXT: ret i8 [[RES]] 894; 895 %res = call i8 @llvm.umin.i8(i8 1, i8 %a) 896 ret i8 %res 897} 898 899define <3 x i8> @umin_non_zero_idiom3(<3 x i8> %a) { 900; CHECK-LABEL: @umin_non_zero_idiom3( 901; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer 902; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8> 903; CHECK-NEXT: ret <3 x i8> [[RES]] 904; 905 %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 1, i8 1>) 906 ret <3 x i8> %res 907} 908 909define <3 x i8> @umin_non_zero_idiom4(<3 x i8> %a) { 910; CHECK-LABEL: @umin_non_zero_idiom4( 911; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <3 x i8> [[A:%.*]], zeroinitializer 912; CHECK-NEXT: [[RES:%.*]] = zext <3 x i1> [[TMP1]] to <3 x i8> 913; CHECK-NEXT: ret <3 x i8> [[RES]] 914; 915 %res = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> <i8 1, i8 poison, i8 poison>) 916 ret <3 x i8> %res 917} 918 919define i1 @umin_eq_zero(i8 %a, i8 %b) { 920; CHECK-LABEL: @umin_eq_zero( 921; CHECK-NEXT: [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 922; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[UMIN]], 0 923; CHECK-NEXT: ret i1 [[RES]] 924; 925 %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b) 926 %res = icmp eq i8 %umin, 0 927 ret i1 %res 928} 929 930define <3 x i1> @umin_eq_zero2(<3 x i8> %a, <3 x i8> %b) { 931; CHECK-LABEL: @umin_eq_zero2( 932; CHECK-NEXT: [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]]) 933; CHECK-NEXT: [[RES:%.*]] = icmp eq <3 x i8> [[UMIN]], zeroinitializer 934; CHECK-NEXT: ret <3 x i1> [[RES]] 935; 936 937 %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b) 938 %res = icmp eq <3 x i8> %umin, zeroinitializer 939 ret <3 x i1> %res 940} 941 942define i1 @umin_ne_zero(i8 %a, i8 %b) { 943; CHECK-LABEL: @umin_ne_zero( 944; CHECK-NEXT: [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 945; CHECK-NEXT: [[RES:%.*]] = icmp ne i8 [[UMIN]], 0 946; CHECK-NEXT: ret i1 [[RES]] 947; 948 %umin = call i8 @llvm.umin.i8(i8 %a, i8 %b) 949 %res = icmp ne i8 %umin, 0 950 ret i1 %res 951} 952 953define <3 x i1> @umin_ne_zero2(<3 x i8> %a, <3 x i8> %b) { 954; CHECK-LABEL: @umin_ne_zero2( 955; CHECK-NEXT: [[UMIN:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[A:%.*]], <3 x i8> [[B:%.*]]) 956; CHECK-NEXT: [[RES:%.*]] = icmp ne <3 x i8> [[UMIN]], zeroinitializer 957; CHECK-NEXT: ret <3 x i1> [[RES]] 958; 959 960 %umin = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %a, <3 x i8> %b) 961 %res = icmp ne <3 x i8> %umin, zeroinitializer 962 ret <3 x i1> %res 963} 964 965define i8 @smax(i8 %x, i8 %y, i8 %z) { 966; CHECK-LABEL: @smax( 967; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Z:%.*]]) 968; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M2]], i8 [[Y:%.*]]) 969; CHECK-NEXT: ret i8 [[M3]] 970; 971 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y) 972 %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z) 973 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2) 974 ret i8 %m3 975} 976 977define <3 x i8> @smin(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) { 978; CHECK-LABEL: @smin( 979; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]]) 980; CHECK-NEXT: [[M3:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M2]], <3 x i8> [[Y:%.*]]) 981; CHECK-NEXT: ret <3 x i8> [[M3]] 982; 983 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %y, <3 x i8> %x) 984 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %z) 985 %m3 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %m2) 986 ret <3 x i8> %m3 987} 988 989define i8 @umax(i8 %x, i8 %y, i8 %z) { 990; CHECK-LABEL: @umax( 991; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 992; CHECK-NEXT: call void @use(i8 [[M1]]) 993; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 [[Z:%.*]]) 994; CHECK-NEXT: ret i8 [[M3]] 995; 996 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y) 997 call void @use(i8 %m1) 998 %m2 = call i8 @llvm.umax.i8(i8 %z, i8 %x) 999 %m3 = call i8 @llvm.umax.i8(i8 %m1, i8 %m2) 1000 ret i8 %m3 1001} 1002 1003define i8 @umin(i8 %x, i8 %y, i8 %z) { 1004; CHECK-LABEL: @umin( 1005; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[Z:%.*]], i8 [[X:%.*]]) 1006; CHECK-NEXT: call void @use(i8 [[M2]]) 1007; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.umin.i8(i8 [[M2]], i8 [[Y:%.*]]) 1008; CHECK-NEXT: ret i8 [[M3]] 1009; 1010 %m1 = call i8 @llvm.umin.i8(i8 %y, i8 %x) 1011 %m2 = call i8 @llvm.umin.i8(i8 %z, i8 %x) 1012 call void @use(i8 %m2) 1013 %m3 = call i8 @llvm.umin.i8(i8 %m1, i8 %m2) 1014 ret i8 %m3 1015} 1016 1017; negative test - too many uses 1018 1019define i8 @smax_uses(i8 %x, i8 %y, i8 %z) { 1020; CHECK-LABEL: @smax_uses( 1021; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 1022; CHECK-NEXT: call void @use(i8 [[M1]]) 1023; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Z:%.*]]) 1024; CHECK-NEXT: call void @use(i8 [[M2]]) 1025; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]]) 1026; CHECK-NEXT: ret i8 [[M3]] 1027; 1028 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y) 1029 call void @use(i8 %m1) 1030 %m2 = call i8 @llvm.smax.i8(i8 %x, i8 %z) 1031 call void @use(i8 %m2) 1032 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2) 1033 ret i8 %m3 1034} 1035 1036; negative test - must have common operand 1037 1038define i8 @smax_no_common_op(i8 %x, i8 %y, i8 %z, i8 %w) { 1039; CHECK-LABEL: @smax_no_common_op( 1040; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 1041; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[W:%.*]], i8 [[Z:%.*]]) 1042; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 [[M2]]) 1043; CHECK-NEXT: ret i8 [[M3]] 1044; 1045 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y) 1046 %m2 = call i8 @llvm.smax.i8(i8 %w, i8 %z) 1047 %m3 = call i8 @llvm.smax.i8(i8 %m1, i8 %m2) 1048 ret i8 %m3 1049} 1050 1051define i8 @umax_demand_lshr(i8 %x) { 1052; CHECK-LABEL: @umax_demand_lshr( 1053; CHECK-NEXT: [[R:%.*]] = lshr i8 [[X:%.*]], 4 1054; CHECK-NEXT: ret i8 [[R]] 1055; 1056 %m = call i8 @llvm.umax.i8(i8 %x, i8 15) 1057 %r = lshr i8 %m, 4 1058 ret i8 %r 1059} 1060 1061define i8 @umax_demand_and(i8 %x) { 1062; CHECK-LABEL: @umax_demand_and( 1063; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], 10 1064; CHECK-NEXT: ret i8 [[R]] 1065; 1066 %m = call i8 @llvm.umax.i8(i8 1, i8 %x) 1067 %r = and i8 %m, 10 1068 ret i8 %r 1069} 1070 1071define i8 @umin_demand_or_31_30(i8 %x) { 1072; CHECK-LABEL: @umin_demand_or_31_30( 1073; CHECK-NEXT: [[R:%.*]] = or i8 [[X:%.*]], 31 1074; CHECK-NEXT: ret i8 [[R]] 1075; 1076 %m = call i8 @llvm.umin.i8(i8 -30, i8 %x) 1077 %r = or i8 %m, 31 1078 ret i8 %r 1079} 1080 1081define i8 @umin_demand_and_7_8(i8 %x) { 1082; CHECK-LABEL: @umin_demand_and_7_8( 1083; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], -8 1084; CHECK-NEXT: ret i8 [[R]] 1085; 1086 %m = call i8 @llvm.umin.i8(i8 %x, i8 -7) 1087 %r = and i8 %m, -8 1088 ret i8 %r 1089} 1090 1091define i8 @neg_neg_nsw_smax(i8 %x, i8 %y) { 1092; CHECK-LABEL: @neg_neg_nsw_smax( 1093; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 1094; CHECK-NEXT: [[M:%.*]] = sub nsw i8 0, [[TMP1]] 1095; CHECK-NEXT: ret i8 [[M]] 1096; 1097 %nx = sub nsw i8 0, %x 1098 %ny = sub nsw i8 0, %y 1099 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny) 1100 ret i8 %m 1101} 1102 1103define <3 x i8> @neg_neg_nsw_smin(<3 x i8> %x, <3 x i8> %y) { 1104; CHECK-LABEL: @neg_neg_nsw_smin( 1105; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) 1106; CHECK-NEXT: [[M:%.*]] = sub nsw <3 x i8> zeroinitializer, [[TMP1]] 1107; CHECK-NEXT: ret <3 x i8> [[M]] 1108; 1109 %nx = sub nsw <3 x i8> zeroinitializer, %x 1110 %ny = sub nsw <3 x i8> zeroinitializer, %y 1111 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %nx, <3 x i8> %ny) 1112 ret <3 x i8> %m 1113} 1114 1115define i8 @neg_neg_nsw_smax_use0(i8 %x, i8 %y) { 1116; CHECK-LABEL: @neg_neg_nsw_smax_use0( 1117; CHECK-NEXT: [[NX:%.*]] = sub nsw i8 0, [[X:%.*]] 1118; CHECK-NEXT: call void @use(i8 [[NX]]) 1119; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y:%.*]]) 1120; CHECK-NEXT: [[M:%.*]] = sub nsw i8 0, [[TMP1]] 1121; CHECK-NEXT: ret i8 [[M]] 1122; 1123 %nx = sub nsw i8 0, %x 1124 call void @use(i8 %nx) 1125 %ny = sub nsw i8 0, %y 1126 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny) 1127 ret i8 %m 1128} 1129 1130define i8 @neg_neg_nsw_smin_use1(i8 %x, i8 %y) { 1131; CHECK-LABEL: @neg_neg_nsw_smin_use1( 1132; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]] 1133; CHECK-NEXT: call void @use(i8 [[NY]]) 1134; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y]]) 1135; CHECK-NEXT: [[M:%.*]] = sub nsw i8 0, [[TMP1]] 1136; CHECK-NEXT: ret i8 [[M]] 1137; 1138 %nx = sub nsw i8 0, %x 1139 %ny = sub nsw i8 0, %y 1140 call void @use(i8 %ny) 1141 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny) 1142 ret i8 %m 1143} 1144 1145; negative test - too many uses 1146 1147define i8 @neg_neg_nsw_smin_use2(i8 %x, i8 %y) { 1148; CHECK-LABEL: @neg_neg_nsw_smin_use2( 1149; CHECK-NEXT: [[NX:%.*]] = sub nsw i8 0, [[X:%.*]] 1150; CHECK-NEXT: call void @use(i8 [[NX]]) 1151; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]] 1152; CHECK-NEXT: call void @use(i8 [[NY]]) 1153; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]]) 1154; CHECK-NEXT: ret i8 [[M]] 1155; 1156 %nx = sub nsw i8 0, %x 1157 call void @use(i8 %nx) 1158 %ny = sub nsw i8 0, %y 1159 call void @use(i8 %ny) 1160 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny) 1161 ret i8 %m 1162} 1163 1164; negative test - need nsw on both ops 1165 1166define i8 @neg_neg_smax(i8 %x, i8 %y) { 1167; CHECK-LABEL: @neg_neg_smax( 1168; CHECK-NEXT: [[NX:%.*]] = sub i8 0, [[X:%.*]] 1169; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]] 1170; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[NX]], i8 [[NY]]) 1171; CHECK-NEXT: ret i8 [[M]] 1172; 1173 %nx = sub i8 0, %x 1174 %ny = sub nsw i8 0, %y 1175 %m = call i8 @llvm.smax.i8(i8 %nx, i8 %ny) 1176 ret i8 %m 1177} 1178 1179; negative test - need nsw on both ops 1180 1181define i8 @neg_neg_smin(i8 %x, i8 %y) { 1182; CHECK-LABEL: @neg_neg_smin( 1183; CHECK-NEXT: [[NX:%.*]] = sub i8 0, [[X:%.*]] 1184; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]] 1185; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NX]], i8 [[NY]]) 1186; CHECK-NEXT: ret i8 [[M]] 1187; 1188 %nx = sub i8 0, %x 1189 %ny = sub nsw i8 0, %y 1190 %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny) 1191 ret i8 %m 1192} 1193 1194; negative test - need signed min/max 1195 1196define i8 @neg_neg_nsw_umin(i8 %x, i8 %y) { 1197; CHECK-LABEL: @neg_neg_nsw_umin( 1198; CHECK-NEXT: [[NX:%.*]] = sub nsw i8 0, [[X:%.*]] 1199; CHECK-NEXT: [[NY:%.*]] = sub nsw i8 0, [[Y:%.*]] 1200; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]]) 1201; CHECK-NEXT: ret i8 [[M]] 1202; 1203 %nx = sub nsw i8 0, %x 1204 %ny = sub nsw i8 0, %y 1205 %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny) 1206 ret i8 %m 1207} 1208 1209define i8 @freeToInvertSub(i8 %x, i8 %y, i8 %z) { 1210; CHECK-LABEL: @freeToInvertSub( 1211; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1212; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1213; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1214; CHECK-NEXT: call void @use(i8 [[NX]]) 1215; CHECK-NEXT: call void @use(i8 [[NY]]) 1216; CHECK-NEXT: call void @use(i8 [[NZ]]) 1217; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]]) 1218; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[TMP1]], [[Z]] 1219; CHECK-NEXT: ret i8 [[SUB]] 1220; 1221 %nx = xor i8 %x, -1 1222 %ny = xor i8 %y, -1 1223 %nz = xor i8 %z, -1 1224 call void @use(i8 %nx) 1225 call void @use(i8 %ny) 1226 call void @use(i8 %nz) 1227 %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1228 %sub = sub i8 %nz, %m 1229 ret i8 %sub 1230} 1231 1232define i8 @freeToInvertSub_uses(i8 %x, i8 %y, i8 %z) { 1233; CHECK-LABEL: @freeToInvertSub_uses( 1234; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1235; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1236; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1237; CHECK-NEXT: call void @use(i8 [[NX]]) 1238; CHECK-NEXT: call void @use(i8 [[NY]]) 1239; CHECK-NEXT: call void @use(i8 [[NZ]]) 1240; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]]) 1241; CHECK-NEXT: call void @use(i8 [[M]]) 1242; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[NZ]], [[M]] 1243; CHECK-NEXT: ret i8 [[SUB]] 1244; 1245 %nx = xor i8 %x, -1 1246 %ny = xor i8 %y, -1 1247 %nz = xor i8 %z, -1 1248 call void @use(i8 %nx) 1249 call void @use(i8 %ny) 1250 call void @use(i8 %nz) 1251 %m = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1252 call void @use(i8 %m) 1253 %sub = sub i8 %nz, %m 1254 ret i8 %sub 1255} 1256 1257define i8 @freeToInvert(i8 %x, i8 %y, i8 %z) { 1258; CHECK-LABEL: @freeToInvert( 1259; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1260; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1261; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1262; CHECK-NEXT: call void @use(i8 [[NX]]) 1263; CHECK-NEXT: call void @use(i8 [[NY]]) 1264; CHECK-NEXT: call void @use(i8 [[NZ]]) 1265; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]]) 1266; CHECK-NEXT: [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]]) 1267; CHECK-NEXT: ret i8 [[NOT]] 1268; 1269 %nx = xor i8 %x, -1 1270 %ny = xor i8 %y, -1 1271 %nz = xor i8 %z, -1 1272 call void @use(i8 %nx) 1273 call void @use(i8 %ny) 1274 call void @use(i8 %nz) 1275 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1276 %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz) 1277 %not = xor i8 %m2, -1 1278 ret i8 %not 1279} 1280 1281define i8 @freeToInvert_use1(i8 %x, i8 %y, i8 %z) { 1282; CHECK-LABEL: @freeToInvert_use1( 1283; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1284; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1285; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1286; CHECK-NEXT: call void @use(i8 [[NX]]) 1287; CHECK-NEXT: call void @use(i8 [[NY]]) 1288; CHECK-NEXT: call void @use(i8 [[NZ]]) 1289; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]]) 1290; CHECK-NEXT: call void @use(i8 [[M1]]) 1291; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[M1]], -1 1292; CHECK-NEXT: [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[Z]], i8 [[TMP1]]) 1293; CHECK-NEXT: ret i8 [[NOT]] 1294; 1295 %nx = xor i8 %x, -1 1296 %ny = xor i8 %y, -1 1297 %nz = xor i8 %z, -1 1298 call void @use(i8 %nx) 1299 call void @use(i8 %ny) 1300 call void @use(i8 %nz) 1301 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1302 call void @use(i8 %m1) 1303 %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz) 1304 %not = xor i8 %m2, -1 1305 ret i8 %not 1306} 1307 1308define i8 @freeToInvert_use2(i8 %x, i8 %y, i8 %z) { 1309; CHECK-LABEL: @freeToInvert_use2( 1310; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1311; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1312; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1313; CHECK-NEXT: call void @use(i8 [[NX]]) 1314; CHECK-NEXT: call void @use(i8 [[NY]]) 1315; CHECK-NEXT: call void @use(i8 [[NZ]]) 1316; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]]) 1317; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]]) 1318; CHECK-NEXT: call void @use(i8 [[M2]]) 1319; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M2]], -1 1320; CHECK-NEXT: ret i8 [[NOT]] 1321; 1322 %nx = xor i8 %x, -1 1323 %ny = xor i8 %y, -1 1324 %nz = xor i8 %z, -1 1325 call void @use(i8 %nx) 1326 call void @use(i8 %ny) 1327 call void @use(i8 %nz) 1328 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1329 %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz) 1330 call void @use(i8 %m2) 1331 %not = xor i8 %m2, -1 1332 ret i8 %not 1333} 1334 1335define i8 @freeToInvert_use3(i8 %x, i8 %y, i8 %z) { 1336; CHECK-LABEL: @freeToInvert_use3( 1337; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1338; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1339; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1340; CHECK-NEXT: call void @use(i8 [[NX]]) 1341; CHECK-NEXT: call void @use(i8 [[NY]]) 1342; CHECK-NEXT: call void @use(i8 [[NZ]]) 1343; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]]) 1344; CHECK-NEXT: call void @use(i8 [[M1]]) 1345; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[NZ]]) 1346; CHECK-NEXT: call void @use(i8 [[M2]]) 1347; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M2]], -1 1348; CHECK-NEXT: ret i8 [[NOT]] 1349; 1350 %nx = xor i8 %x, -1 1351 %ny = xor i8 %y, -1 1352 %nz = xor i8 %z, -1 1353 call void @use(i8 %nx) 1354 call void @use(i8 %ny) 1355 call void @use(i8 %nz) 1356 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1357 call void @use(i8 %m1) 1358 %m2 = call i8 @llvm.smin.i8(i8 %m1, i8 %nz) 1359 call void @use(i8 %m2) 1360 %not = xor i8 %m2, -1 1361 ret i8 %not 1362} 1363 1364define i8 @freeToInvert_two_minmax_ops(i8 %x, i8 %y, i8 %z, i8 %w) { 1365; CHECK-LABEL: @freeToInvert_two_minmax_ops( 1366; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1367; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1368; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1369; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -1 1370; CHECK-NEXT: call void @use(i8 [[NX]]) 1371; CHECK-NEXT: call void @use(i8 [[NY]]) 1372; CHECK-NEXT: call void @use(i8 [[NZ]]) 1373; CHECK-NEXT: call void @use(i8 [[NW]]) 1374; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]]) 1375; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smin.i8(i8 [[W]], i8 [[Z]]) 1376; CHECK-NEXT: [[NOT:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP2]]) 1377; CHECK-NEXT: ret i8 [[NOT]] 1378; 1379 %nx = xor i8 %x, -1 1380 %ny = xor i8 %y, -1 1381 %nz = xor i8 %z, -1 1382 %nw = xor i8 %w, -1 1383 call void @use(i8 %nx) 1384 call void @use(i8 %ny) 1385 call void @use(i8 %nz) 1386 call void @use(i8 %nw) 1387 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1388 %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz) 1389 %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2) 1390 %not = xor i8 %m3, -1 1391 ret i8 %not 1392} 1393 1394define i8 @freeToInvert_two_minmax_ops_use1(i8 %x, i8 %y, i8 %z, i8 %w) { 1395; CHECK-LABEL: @freeToInvert_two_minmax_ops_use1( 1396; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1397; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1398; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1399; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -1 1400; CHECK-NEXT: call void @use(i8 [[NX]]) 1401; CHECK-NEXT: call void @use(i8 [[NY]]) 1402; CHECK-NEXT: call void @use(i8 [[NZ]]) 1403; CHECK-NEXT: call void @use(i8 [[NW]]) 1404; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]]) 1405; CHECK-NEXT: call void @use(i8 [[M1]]) 1406; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]]) 1407; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]]) 1408; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M3]], -1 1409; CHECK-NEXT: ret i8 [[NOT]] 1410; 1411 %nx = xor i8 %x, -1 1412 %ny = xor i8 %y, -1 1413 %nz = xor i8 %z, -1 1414 %nw = xor i8 %w, -1 1415 call void @use(i8 %nx) 1416 call void @use(i8 %ny) 1417 call void @use(i8 %nz) 1418 call void @use(i8 %nw) 1419 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1420 call void @use(i8 %m1) 1421 %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz) 1422 %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2) 1423 %not = xor i8 %m3, -1 1424 ret i8 %not 1425} 1426 1427define i8 @freeToInvert_two_minmax_ops_use2(i8 %x, i8 %y, i8 %z, i8 %w) { 1428; CHECK-LABEL: @freeToInvert_two_minmax_ops_use2( 1429; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1430; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1431; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1432; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -1 1433; CHECK-NEXT: call void @use(i8 [[NX]]) 1434; CHECK-NEXT: call void @use(i8 [[NY]]) 1435; CHECK-NEXT: call void @use(i8 [[NZ]]) 1436; CHECK-NEXT: call void @use(i8 [[NW]]) 1437; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]]) 1438; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]]) 1439; CHECK-NEXT: call void @use(i8 [[M2]]) 1440; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]]) 1441; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M3]], -1 1442; CHECK-NEXT: ret i8 [[NOT]] 1443; 1444 %nx = xor i8 %x, -1 1445 %ny = xor i8 %y, -1 1446 %nz = xor i8 %z, -1 1447 %nw = xor i8 %w, -1 1448 call void @use(i8 %nx) 1449 call void @use(i8 %ny) 1450 call void @use(i8 %nz) 1451 call void @use(i8 %nw) 1452 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1453 %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz) 1454 call void @use(i8 %m2) 1455 %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2) 1456 %not = xor i8 %m3, -1 1457 ret i8 %not 1458} 1459 1460define i8 @freeToInvert_two_minmax_ops_use3(i8 %x, i8 %y, i8 %z, i8 %w) { 1461; CHECK-LABEL: @freeToInvert_two_minmax_ops_use3( 1462; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 1463; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1 1464; CHECK-NEXT: [[NZ:%.*]] = xor i8 [[Z:%.*]], -1 1465; CHECK-NEXT: [[NW:%.*]] = xor i8 [[W:%.*]], -1 1466; CHECK-NEXT: call void @use(i8 [[NX]]) 1467; CHECK-NEXT: call void @use(i8 [[NY]]) 1468; CHECK-NEXT: call void @use(i8 [[NZ]]) 1469; CHECK-NEXT: call void @use(i8 [[NW]]) 1470; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[NX]], i8 [[NY]]) 1471; CHECK-NEXT: call void @use(i8 [[M1]]) 1472; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[NW]], i8 [[NZ]]) 1473; CHECK-NEXT: call void @use(i8 [[M2]]) 1474; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 [[M2]]) 1475; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[M3]], -1 1476; CHECK-NEXT: ret i8 [[NOT]] 1477; 1478 %nx = xor i8 %x, -1 1479 %ny = xor i8 %y, -1 1480 %nz = xor i8 %z, -1 1481 %nw = xor i8 %w, -1 1482 call void @use(i8 %nx) 1483 call void @use(i8 %ny) 1484 call void @use(i8 %nz) 1485 call void @use(i8 %nw) 1486 %m1 = call i8 @llvm.umax.i8(i8 %nx, i8 %ny) 1487 call void @use(i8 %m1) 1488 %m2 = call i8 @llvm.smax.i8(i8 %nw, i8 %nz) 1489 call void @use(i8 %m2) 1490 %m3 = call i8 @llvm.smin.i8(i8 %m1, i8 %m2) 1491 %not = xor i8 %m3, -1 1492 ret i8 %not 1493} 1494 1495define i8 @sub_not_min_max(i8 %r, i8 %g, i8 %b) { 1496; CHECK-LABEL: @sub_not_min_max( 1497; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -1 1498; CHECK-NEXT: call void @use(i8 [[NOTG]]) 1499; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1 1500; CHECK-NEXT: call void @use(i8 [[NOTB]]) 1501; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G]]) 1502; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[B]]) 1503; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1504; CHECK-NEXT: ret i8 [[CK]] 1505; 1506 %notr = xor i8 %r, -1 1507 %notg = xor i8 %g, -1 1508 call void @use(i8 %notg) 1509 %notb = xor i8 %b, -1 1510 call void @use(i8 %notb) 1511 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg) 1512 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1513 %ck = sub i8 %notr, %k 1514 ret i8 %ck 1515} 1516 1517define i8 @sub_not_min_max_uses1(i8 %r, i8 %g, i8 %b) { 1518; CHECK-LABEL: @sub_not_min_max_uses1( 1519; CHECK-NEXT: [[NOTR:%.*]] = xor i8 [[R:%.*]], -1 1520; CHECK-NEXT: call void @use(i8 [[NOTR]]) 1521; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -1 1522; CHECK-NEXT: call void @use(i8 [[NOTG]]) 1523; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1 1524; CHECK-NEXT: call void @use(i8 [[NOTB]]) 1525; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R]], i8 [[G]]) 1526; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[B]]) 1527; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1528; CHECK-NEXT: ret i8 [[CK]] 1529; 1530 %notr = xor i8 %r, -1 1531 call void @use(i8 %notr) 1532 %notg = xor i8 %g, -1 1533 call void @use(i8 %notg) 1534 %notb = xor i8 %b, -1 1535 call void @use(i8 %notb) 1536 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg) 1537 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1538 %ck = sub i8 %notr, %k 1539 ret i8 %ck 1540} 1541 1542define i8 @sub_not_min_max_uses2(i8 %r, i8 %g, i8 %b) { 1543; CHECK-LABEL: @sub_not_min_max_uses2( 1544; CHECK-NEXT: [[NOTR:%.*]] = xor i8 [[R:%.*]], -1 1545; CHECK-NEXT: call void @use(i8 [[NOTR]]) 1546; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -1 1547; CHECK-NEXT: call void @use(i8 [[NOTG]]) 1548; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1 1549; CHECK-NEXT: call void @use(i8 [[NOTB]]) 1550; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[NOTR]], i8 [[NOTG]]) 1551; CHECK-NEXT: call void @use(i8 [[M]]) 1552; CHECK-NEXT: [[K:%.*]] = call i8 @llvm.smin.i8(i8 [[M]], i8 [[NOTB]]) 1553; CHECK-NEXT: [[CK:%.*]] = sub i8 [[NOTR]], [[K]] 1554; CHECK-NEXT: ret i8 [[CK]] 1555; 1556 %notr = xor i8 %r, -1 1557 call void @use(i8 %notr) 1558 %notg = xor i8 %g, -1 1559 call void @use(i8 %notg) 1560 %notb = xor i8 %b, -1 1561 call void @use(i8 %notb) 1562 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg) 1563 call void @use(i8 %m) 1564 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1565 %ck = sub i8 %notr, %k 1566 ret i8 %ck 1567} 1568 1569declare void @use4(i8, i8, i8, i8) 1570 1571define void @cmyk(i8 %r, i8 %g, i8 %b) { 1572; CHECK-LABEL: @cmyk( 1573; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]]) 1574; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1575; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1576; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1577; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]] 1578; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]] 1579; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1580; CHECK-NEXT: ret void 1581; 1582 %notr = xor i8 %r, -1 1583 %notg = xor i8 %g, -1 1584 %notb = xor i8 %b, -1 1585 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg) 1586 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1587 %ck = sub i8 %notr, %k 1588 %mk = sub i8 %notg, %k 1589 %yk = sub i8 %notb, %k 1590 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1591 ret void 1592} 1593 1594; Same as above, but flip the operands of %k. 1595 1596define void @cmyk_commute1(i8 %r, i8 %g, i8 %b) { 1597; CHECK-LABEL: @cmyk_commute1( 1598; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]]) 1599; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1600; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1601; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1602; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]] 1603; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]] 1604; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1605; CHECK-NEXT: ret void 1606; 1607 %notr = xor i8 %r, -1 1608 %notg = xor i8 %g, -1 1609 %notb = xor i8 %b, -1 1610 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg) 1611 %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m) 1612 %ck = sub i8 %notr, %k 1613 %mk = sub i8 %notg, %k 1614 %yk = sub i8 %notb, %k 1615 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1616 ret void 1617} 1618 1619; Same as above, but also flip the operands of %m. 1620 1621define void @cmyk_commute2(i8 %r, i8 %g, i8 %b) { 1622; CHECK-LABEL: @cmyk_commute2( 1623; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]]) 1624; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1625; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1626; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1627; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]] 1628; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]] 1629; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1630; CHECK-NEXT: ret void 1631; 1632 %notr = xor i8 %r, -1 1633 %notg = xor i8 %g, -1 1634 %notb = xor i8 %b, -1 1635 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr) 1636 %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m) 1637 %ck = sub i8 %notr, %k 1638 %mk = sub i8 %notg, %k 1639 %yk = sub i8 %notb, %k 1640 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1641 ret void 1642} 1643 1644; Same as original, but only flip the operands of %m. 1645 1646define void @cmyk_commute3(i8 %r, i8 %g, i8 %b) { 1647; CHECK-LABEL: @cmyk_commute3( 1648; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]]) 1649; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1650; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1651; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1652; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]] 1653; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]] 1654; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1655; CHECK-NEXT: ret void 1656; 1657 %notr = xor i8 %r, -1 1658 %notg = xor i8 %g, -1 1659 %notb = xor i8 %b, -1 1660 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr) 1661 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1662 %ck = sub i8 %notr, %k 1663 %mk = sub i8 %notg, %k 1664 %yk = sub i8 %notb, %k 1665 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1666 ret void 1667} 1668 1669; Not exactly a commute, but make sure order of folds doesn't change anything. 1670; Also verify that we don't need matching min/max ops. 1671 1672define void @cmyk_commute4(i8 %r, i8 %g, i8 %b) { 1673; CHECK-LABEL: @cmyk_commute4( 1674; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]]) 1675; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1676; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1677; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]] 1678; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1679; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]] 1680; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1681; CHECK-NEXT: ret void 1682; 1683 %notr = xor i8 %r, -1 1684 %notg = xor i8 %g, -1 1685 %notb = xor i8 %b, -1 1686 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr) 1687 %k = call i8 @llvm.umin.i8(i8 %m, i8 %notb) 1688 %yk = sub i8 %notb, %k 1689 %ck = sub i8 %notr, %k 1690 %mk = sub i8 %notg, %k 1691 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1692 ret void 1693} 1694 1695; Not exactly a commute, but make sure order of folds doesn't change anything. 1696; Also verify that we don't need matching min/max ops. 1697 1698define void @cmyk_commute5(i8 %r, i8 %g, i8 %b) { 1699; CHECK-LABEL: @cmyk_commute5( 1700; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[G:%.*]], i8 [[R:%.*]]) 1701; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1702; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1703; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1704; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]] 1705; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]] 1706; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1707; CHECK-NEXT: ret void 1708; 1709 %notr = xor i8 %r, -1 1710 %notg = xor i8 %g, -1 1711 %notb = xor i8 %b, -1 1712 %m = call i8 @llvm.smax.i8(i8 %notg, i8 %notr) 1713 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1714 %ck = sub i8 %notr, %k 1715 %yk = sub i8 %notb, %k 1716 %mk = sub i8 %notg, %k 1717 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1718 ret void 1719} 1720 1721define void @cmyk_commute6(i8 %r, i8 %g, i8 %b) { 1722; CHECK-LABEL: @cmyk_commute6( 1723; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]]) 1724; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1725; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1726; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]] 1727; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]] 1728; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]] 1729; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1730; CHECK-NEXT: ret void 1731; 1732 %notr = xor i8 %r, -1 1733 %notg = xor i8 %g, -1 1734 %notb = xor i8 %b, -1 1735 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg) 1736 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1737 %ck = sub i8 %k, %notr 1738 %mk = sub i8 %k, %notg 1739 %yk = sub i8 %k, %notb 1740 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1741 ret void 1742} 1743 1744; Same as above, but flip the operands of %k. 1745 1746define void @cmyk_commute7(i8 %r, i8 %g, i8 %b) { 1747; CHECK-LABEL: @cmyk_commute7( 1748; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[R:%.*]], i8 [[G:%.*]]) 1749; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1750; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1751; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]] 1752; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]] 1753; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]] 1754; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1755; CHECK-NEXT: ret void 1756; 1757 %notr = xor i8 %r, -1 1758 %notg = xor i8 %g, -1 1759 %notb = xor i8 %b, -1 1760 %m = call i8 @llvm.smin.i8(i8 %notr, i8 %notg) 1761 %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m) 1762 %ck = sub i8 %k, %notr 1763 %mk = sub i8 %k, %notg 1764 %yk = sub i8 %k, %notb 1765 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1766 ret void 1767} 1768 1769; Same as above, but also flip the operands of %m. 1770 1771define void @cmyk_commute8(i8 %r, i8 %g, i8 %b) { 1772; CHECK-LABEL: @cmyk_commute8( 1773; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]]) 1774; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1775; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1776; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]] 1777; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]] 1778; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]] 1779; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1780; CHECK-NEXT: ret void 1781; 1782 %notr = xor i8 %r, -1 1783 %notg = xor i8 %g, -1 1784 %notb = xor i8 %b, -1 1785 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr) 1786 %k = call i8 @llvm.smin.i8(i8 %notb, i8 %m) 1787 %ck = sub i8 %k, %notr 1788 %mk = sub i8 %k, %notg 1789 %yk = sub i8 %k, %notb 1790 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1791 ret void 1792} 1793 1794; Same as original, but only flip the operands of %m. 1795 1796define void @cmyk_commute9(i8 %r, i8 %g, i8 %b) { 1797; CHECK-LABEL: @cmyk_commute9( 1798; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]]) 1799; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1800; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1801; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]] 1802; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]] 1803; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]] 1804; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1805; CHECK-NEXT: ret void 1806; 1807 %notr = xor i8 %r, -1 1808 %notg = xor i8 %g, -1 1809 %notb = xor i8 %b, -1 1810 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr) 1811 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1812 %ck = sub i8 %k, %notr 1813 %mk = sub i8 %k, %notg 1814 %yk = sub i8 %k, %notb 1815 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1816 ret void 1817} 1818 1819; Not exactly a commute, but make sure order of folds doesn't change anything. 1820; Also verify that we don't need matching min/max ops. 1821 1822define void @cmyk_commute10(i8 %r, i8 %g, i8 %b) { 1823; CHECK-LABEL: @cmyk_commute10( 1824; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[G:%.*]], i8 [[R:%.*]]) 1825; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1826; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1827; CHECK-NEXT: [[YK:%.*]] = sub i8 [[TMP2]], [[B]] 1828; CHECK-NEXT: [[CK:%.*]] = sub i8 [[R]], [[TMP2]] 1829; CHECK-NEXT: [[MK:%.*]] = sub i8 [[TMP2]], [[G]] 1830; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1831; CHECK-NEXT: ret void 1832; 1833 %notr = xor i8 %r, -1 1834 %notg = xor i8 %g, -1 1835 %notb = xor i8 %b, -1 1836 %m = call i8 @llvm.smin.i8(i8 %notg, i8 %notr) 1837 %k = call i8 @llvm.umin.i8(i8 %m, i8 %notb) 1838 %yk = sub i8 %notb, %k 1839 %ck = sub i8 %k, %notr 1840 %mk = sub i8 %notg, %k 1841 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1842 ret void 1843} 1844 1845; Not exactly a commute, but make sure order of folds doesn't change anything. 1846; Also verify that we don't need matching min/max ops. 1847 1848define void @cmyk_commute11(i8 %r, i8 %g, i8 %b) { 1849; CHECK-LABEL: @cmyk_commute11( 1850; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[G:%.*]], i8 [[R:%.*]]) 1851; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.smax.i8(i8 [[B:%.*]], i8 [[TMP1]]) 1852; CHECK-NEXT: [[K:%.*]] = xor i8 [[TMP2]], -1 1853; CHECK-NEXT: [[CK:%.*]] = sub i8 [[TMP2]], [[R]] 1854; CHECK-NEXT: [[YK:%.*]] = sub i8 [[B]], [[TMP2]] 1855; CHECK-NEXT: [[MK:%.*]] = sub i8 [[G]], [[TMP2]] 1856; CHECK-NEXT: call void @use4(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]]) 1857; CHECK-NEXT: ret void 1858; 1859 %notr = xor i8 %r, -1 1860 %notg = xor i8 %g, -1 1861 %notb = xor i8 %b, -1 1862 %m = call i8 @llvm.smax.i8(i8 %notg, i8 %notr) 1863 %k = call i8 @llvm.smin.i8(i8 %m, i8 %notb) 1864 %ck = sub i8 %notr, %k 1865 %yk = sub i8 %k, %notb 1866 %mk = sub i8 %k, %notg 1867 call void @use4(i8 %ck, i8 %mk, i8 %yk, i8 %k) 1868 ret void 1869} 1870 1871define i8 @smax_offset(i8 %x) { 1872; CHECK-LABEL: @smax_offset( 1873; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -127) 1874; CHECK-NEXT: [[M:%.*]] = add nsw i8 [[TMP1]], 3 1875; CHECK-NEXT: ret i8 [[M]] 1876; 1877 %a = add nsw i8 %x, 3 1878 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124) 1879 ret i8 %m 1880} 1881 1882; This is handled by InstSimplify; testing here to confirm assert. 1883 1884define i8 @smax_offset_limit(i8 %x) { 1885; CHECK-LABEL: @smax_offset_limit( 1886; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 3 1887; CHECK-NEXT: ret i8 [[A]] 1888; 1889 %a = add nsw i8 %x, 3 1890 %m = call i8 @llvm.smax.i8(i8 %a, i8 -125) 1891 ret i8 %m 1892} 1893 1894; This is handled by InstSimplify; testing here to confirm assert. 1895 1896define i8 @smax_offset_overflow(i8 %x) { 1897; CHECK-LABEL: @smax_offset_overflow( 1898; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 3 1899; CHECK-NEXT: ret i8 [[A]] 1900; 1901 %a = add nsw i8 %x, 3 1902 %m = call i8 @llvm.smax.i8(i8 %a, i8 -126) 1903 ret i8 %m 1904} 1905 1906; negative test - require nsw 1907 1908define i8 @smax_offset_may_wrap(i8 %x) { 1909; CHECK-LABEL: @smax_offset_may_wrap( 1910; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 3 1911; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124) 1912; CHECK-NEXT: ret i8 [[M]] 1913; 1914 %a = add i8 %x, 3 1915 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124) 1916 ret i8 %m 1917} 1918 1919; negative test 1920 1921define i8 @smax_offset_uses(i8 %x) { 1922; CHECK-LABEL: @smax_offset_uses( 1923; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 3 1924; CHECK-NEXT: call void @use(i8 [[A]]) 1925; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 -124) 1926; CHECK-NEXT: ret i8 [[M]] 1927; 1928 %a = add nsw i8 %x, 3 1929 call void @use(i8 %a) 1930 %m = call i8 @llvm.smax.i8(i8 %a, i8 -124) 1931 ret i8 %m 1932} 1933 1934define <3 x i8> @smin_offset(<3 x i8> %x) { 1935; CHECK-LABEL: @smin_offset( 1936; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> splat (i8 -127)) 1937; CHECK-NEXT: [[M:%.*]] = or disjoint <3 x i8> [[TMP1]], splat (i8 124) 1938; CHECK-NEXT: ret <3 x i8> [[M]] 1939; 1940 %a = add nsw nuw <3 x i8> %x, <i8 124, i8 124, i8 124> 1941 %m = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %a, <3 x i8> <i8 -3, i8 -3, i8 -3>) 1942 ret <3 x i8> %m 1943} 1944 1945; This is handled by InstSimplify; testing here to confirm assert. 1946 1947define i8 @smin_offset_limit(i8 %x) { 1948; CHECK-LABEL: @smin_offset_limit( 1949; CHECK-NEXT: ret i8 -3 1950; 1951 %a = add nsw i8 %x, 125 1952 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3) 1953 ret i8 %m 1954} 1955 1956; This is handled by InstSimplify; testing here to confirm assert. 1957 1958define i8 @smin_offset_overflow(i8 %x) { 1959; CHECK-LABEL: @smin_offset_overflow( 1960; CHECK-NEXT: ret i8 -3 1961; 1962 %a = add nsw i8 %x, 126 1963 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3) 1964 ret i8 %m 1965} 1966 1967; negative test - require nsw 1968 1969define i8 @smin_offset_may_wrap(i8 %x) { 1970; CHECK-LABEL: @smin_offset_may_wrap( 1971; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 124 1972; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3) 1973; CHECK-NEXT: ret i8 [[M]] 1974; 1975 %a = add nuw i8 %x, 124 1976 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3) 1977 ret i8 %m 1978} 1979 1980; negative test 1981 1982define i8 @smin_offset_uses(i8 %x) { 1983; CHECK-LABEL: @smin_offset_uses( 1984; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 124 1985; CHECK-NEXT: call void @use(i8 [[A]]) 1986; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 -3) 1987; CHECK-NEXT: ret i8 [[M]] 1988; 1989 %a = add nsw i8 %x, 124 1990 call void @use(i8 %a) 1991 %m = call i8 @llvm.smin.i8(i8 %a, i8 -3) 1992 ret i8 %m 1993} 1994 1995; Note: 'nsw' must not propagate here. 1996 1997define <3 x i8> @umax_offset(<3 x i8> %x) { 1998; CHECK-LABEL: @umax_offset( 1999; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> splat (i8 3)) 2000; CHECK-NEXT: [[M:%.*]] = add nuw <3 x i8> [[TMP1]], splat (i8 127) 2001; CHECK-NEXT: ret <3 x i8> [[M]] 2002; 2003 %a = add nsw nuw <3 x i8> %x, <i8 127, i8 127, i8 127> 2004 %m = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 130, i8 130, i8 130>) 2005 ret <3 x i8> %m 2006} 2007 2008; This is handled by InstSimplify; testing here to confirm assert. 2009 2010define i8 @umax_offset_limit(i8 %x) { 2011; CHECK-LABEL: @umax_offset_limit( 2012; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 3 2013; CHECK-NEXT: ret i8 [[A]] 2014; 2015 %a = add nuw i8 %x, 3 2016 %m = call i8 @llvm.umax.i8(i8 %a, i8 3) 2017 ret i8 %m 2018} 2019 2020; This is handled by InstSimplify; testing here to confirm assert. 2021 2022define i8 @umax_offset_overflow(i8 %x) { 2023; CHECK-LABEL: @umax_offset_overflow( 2024; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 3 2025; CHECK-NEXT: ret i8 [[A]] 2026; 2027 %a = add nuw i8 %x, 3 2028 %m = call i8 @llvm.umax.i8(i8 %a, i8 2) 2029 ret i8 %m 2030} 2031 2032; negative test - require nuw 2033 2034define i8 @umax_offset_may_wrap(i8 %x) { 2035; CHECK-LABEL: @umax_offset_may_wrap( 2036; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 3 2037; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4) 2038; CHECK-NEXT: ret i8 [[M]] 2039; 2040 %a = add i8 %x, 3 2041 %m = call i8 @llvm.umax.i8(i8 %a, i8 4) 2042 ret i8 %m 2043} 2044 2045; negative test 2046 2047define i8 @umax_offset_uses(i8 %x) { 2048; CHECK-LABEL: @umax_offset_uses( 2049; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], 3 2050; CHECK-NEXT: call void @use(i8 [[A]]) 2051; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 4) 2052; CHECK-NEXT: ret i8 [[M]] 2053; 2054 %a = add nuw i8 %x, 3 2055 call void @use(i8 %a) 2056 %m = call i8 @llvm.umax.i8(i8 %a, i8 4) 2057 ret i8 %m 2058} 2059 2060define i8 @umin_offset(i8 %x) { 2061; CHECK-LABEL: @umin_offset( 2062; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[X:%.*]], 0 2063; CHECK-NEXT: [[M:%.*]] = select i1 [[DOTNOT]], i8 -5, i8 -4 2064; CHECK-NEXT: ret i8 [[M]] 2065; 2066 %a = add nuw i8 %x, 251 2067 %m = call i8 @llvm.umin.i8(i8 %a, i8 252) 2068 ret i8 %m 2069} 2070 2071; This is handled by InstSimplify; testing here to confirm assert. 2072 2073define i8 @umin_offset_limit(i8 %x) { 2074; CHECK-LABEL: @umin_offset_limit( 2075; CHECK-NEXT: ret i8 -4 2076; 2077 %a = add nuw i8 %x, 252 2078 %m = call i8 @llvm.umin.i8(i8 %a, i8 252) 2079 ret i8 %m 2080} 2081 2082; This is handled by InstSimplify; testing here to confirm assert. 2083 2084define i8 @umin_offset_overflow(i8 %x) { 2085; CHECK-LABEL: @umin_offset_overflow( 2086; CHECK-NEXT: ret i8 -4 2087; 2088 %a = add nuw i8 %x, 253 2089 %m = call i8 @llvm.umin.i8(i8 %a, i8 252) 2090 ret i8 %m 2091} 2092 2093; negative test - require nuw 2094 2095define i8 @umin_offset_may_wrap(i8 %x) { 2096; CHECK-LABEL: @umin_offset_may_wrap( 2097; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], -5 2098; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4) 2099; CHECK-NEXT: ret i8 [[M]] 2100; 2101 %a = add nsw i8 %x, 251 2102 %m = call i8 @llvm.umin.i8(i8 %a, i8 252) 2103 ret i8 %m 2104} 2105 2106; negative test 2107 2108define i8 @umin_offset_uses(i8 %x) { 2109; CHECK-LABEL: @umin_offset_uses( 2110; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], -5 2111; CHECK-NEXT: call void @use(i8 [[A]]) 2112; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 -4) 2113; CHECK-NEXT: ret i8 [[M]] 2114; 2115 %a = add nuw i8 %x, 251 2116 call void @use(i8 %a) 2117 %m = call i8 @llvm.umin.i8(i8 %a, i8 252) 2118 ret i8 %m 2119} 2120 2121; TODO: This could transform 2122 2123define <3 x i8> @umax_vector_splat_poison(<3 x i8> %x) { 2124; CHECK-LABEL: @umax_vector_splat_poison( 2125; CHECK-NEXT: [[A:%.*]] = add nuw <3 x i8> [[X:%.*]], <i8 poison, i8 64, i8 64> 2126; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[A]], <3 x i8> <i8 13, i8 -126, i8 -126>) 2127; CHECK-NEXT: ret <3 x i8> [[R]] 2128; 2129 %a = add nuw <3 x i8> %x, <i8 poison, i8 64, i8 64> 2130 %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %a, <3 x i8> <i8 13, i8 130, i8 130>) 2131 ret <3 x i8> %r 2132} 2133 2134; Issue #52884 - this would assert because of a failure to simplify. 2135 2136define i8 @smax_offset_simplify(i8 %x) { 2137; CHECK-LABEL: @smax_offset_simplify( 2138; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i8 [[X:%.*]], 50 2139; CHECK-NEXT: ret i8 [[TMP1]] 2140; 2141 %1 = add nuw nsw i8 50, %x 2142 %m = call i8 @llvm.smax.i8(i8 %1, i8 -124) 2143 ret i8 %m 2144} 2145 2146define <3 x i8> @smax_smax_reassoc_constants(<3 x i8> %x) { 2147; CHECK-LABEL: @smax_smax_reassoc_constants( 2148; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 43, i8 43, i8 44>) 2149; CHECK-NEXT: ret <3 x i8> [[M2]] 2150; 2151 %m1 = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 43, i8 44>) 2152 %m2 = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>) 2153 ret <3 x i8> %m2 2154} 2155 2156define i8 @smin_smin_reassoc_constants(i8 %x) { 2157; CHECK-LABEL: @smin_smin_reassoc_constants( 2158; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -3) 2159; CHECK-NEXT: ret i8 [[M2]] 2160; 2161 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 97) 2162 %m2 = call i8 @llvm.smin.i8(i8 -3, i8 %m1) 2163 ret i8 %m2 2164} 2165 2166define <3 x i8> @umax_umax_reassoc_constants(<3 x i8> %x) { 2167; CHECK-LABEL: @umax_umax_reassoc_constants( 2168; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> <i8 43, i8 -113, i8 poison>) 2169; CHECK-NEXT: ret <3 x i8> [[M2]] 2170; 2171 %m1 = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %x, <3 x i8> <i8 42, i8 43, i8 44>) 2172 %m2 = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 143, i8 poison>) 2173 ret <3 x i8> %m2 2174} 2175 2176; extra use is ok 2177 2178define i8 @umin_umin_reassoc_constants(i8 %x) { 2179; CHECK-LABEL: @umin_umin_reassoc_constants( 2180; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 -116) 2181; CHECK-NEXT: call void @use(i8 [[M1]]) 2182; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42) 2183; CHECK-NEXT: ret i8 [[M2]] 2184; 2185 %m1 = call i8 @llvm.umin.i8(i8 140, i8 %x) 2186 call void @use(i8 %m1) 2187 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 42) 2188 ret i8 %m2 2189} 2190 2191; negative test - must have matching intrinsics 2192 2193define i8 @smin_smax_reassoc_constants(i8 %x) { 2194; CHECK-LABEL: @smin_smax_reassoc_constants( 2195; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 97) 2196; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 -3) 2197; CHECK-NEXT: ret i8 [[M2]] 2198; 2199 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 97) 2200 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 -3) 2201 ret i8 %m2 2202} 2203 2204define i8 @smax_smax_reassoc_constant(i8 %x, i8 %y) { 2205; CHECK-LABEL: @smax_smax_reassoc_constant( 2206; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 2207; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 42) 2208; CHECK-NEXT: ret i8 [[M2]] 2209; 2210 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 %y) 2211 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 42) 2212 ret i8 %m2 2213} 2214 2215define <3 x i8> @smin_smin_reassoc_constant(<3 x i8> %x, <3 x i8> %y) { 2216; CHECK-LABEL: @smin_smin_reassoc_constant( 2217; CHECK-NEXT: [[M1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) 2218; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>) 2219; CHECK-NEXT: ret <3 x i8> [[M2]] 2220; 2221 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> %y) 2222 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>) 2223 ret <3 x i8> %m2 2224} 2225 2226define i8 @umax_umax_reassoc_constant(i8 %x, i8 %y) { 2227; CHECK-LABEL: @umax_umax_reassoc_constant( 2228; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 2229; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42) 2230; CHECK-NEXT: ret i8 [[M2]] 2231; 2232 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 %y) 2233 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 42) 2234 ret i8 %m2 2235} 2236 2237define <3 x i8> @umin_umin_reassoc_constant(<3 x i8> %x, <3 x i8> %y) { 2238; CHECK-LABEL: @umin_umin_reassoc_constant( 2239; CHECK-NEXT: [[M1:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) 2240; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>) 2241; CHECK-NEXT: ret <3 x i8> [[M2]] 2242; 2243 %m1 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %x, <3 x i8> %y) 2244 %m2 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %m1, <3 x i8> <i8 43, i8 -43, i8 0>) 2245 ret <3 x i8> %m2 2246} 2247 2248define i8 @umin_umin_reassoc_constant_use(i8 %x, i8 %y) { 2249; CHECK-LABEL: @umin_umin_reassoc_constant_use( 2250; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 2251; CHECK-NEXT: call void @use(i8 [[M1]]) 2252; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 42) 2253; CHECK-NEXT: ret i8 [[M2]] 2254; 2255 %m1 = call i8 @llvm.umin.i8(i8 %x, i8 %y) 2256 call void @use(i8 %m1) 2257 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 42) 2258 ret i8 %m2 2259} 2260 2261define i8 @smax_smax_reassoc_constant_sink(i8 %x, i8 %y) { 2262; CHECK-LABEL: @smax_smax_reassoc_constant_sink( 2263; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 2264; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 42) 2265; CHECK-NEXT: ret i8 [[M2]] 2266; 2267 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42) 2268 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 %y) 2269 ret i8 %m2 2270} 2271 2272define <3 x i8> @smin_smin_reassoc_constant_sink(<3 x i8> %x, <3 x i8> %y) { 2273; CHECK-LABEL: @smin_smin_reassoc_constant_sink( 2274; CHECK-NEXT: [[M1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) 2275; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>) 2276; CHECK-NEXT: ret <3 x i8> [[M2]] 2277; 2278 %m1 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %x, <3 x i8> <i8 43, i8 -43, i8 0>) 2279 %m2 = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %m1, <3 x i8> %y) 2280 ret <3 x i8> %m2 2281} 2282 2283define i8 @umax_umax_reassoc_constant_sink(i8 %x, i8 %y) { 2284; CHECK-LABEL: @umax_umax_reassoc_constant_sink( 2285; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 2286; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42) 2287; CHECK-NEXT: ret i8 [[M2]] 2288; 2289 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42) 2290 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 %y) 2291 ret i8 %m2 2292} 2293 2294define <3 x i8> @umin_umin_reassoc_constant_sink(<3 x i8> %x, <3 x i8> %y) { 2295; CHECK-LABEL: @umin_umin_reassoc_constant_sink( 2296; CHECK-NEXT: [[M1:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) 2297; CHECK-NEXT: [[M2:%.*]] = call <3 x i8> @llvm.umin.v3i8(<3 x i8> [[M1]], <3 x i8> <i8 43, i8 -43, i8 0>) 2298; CHECK-NEXT: ret <3 x i8> [[M2]] 2299; 2300 %m1 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %x, <3 x i8> <i8 43, i8 -43, i8 0>) 2301 %m2 = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %m1, <3 x i8> %y) 2302 ret <3 x i8> %m2 2303} 2304 2305define i8 @umin_umin_reassoc_constant_sink_use(i8 %x, i8 %y) { 2306; CHECK-LABEL: @umin_umin_reassoc_constant_sink_use( 2307; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 42) 2308; CHECK-NEXT: call void @use(i8 [[M1]]) 2309; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umin.i8(i8 [[M1]], i8 [[Y:%.*]]) 2310; CHECK-NEXT: ret i8 [[M2]] 2311; 2312 %m1 = call i8 @llvm.umin.i8(i8 %x, i8 42) 2313 call void @use(i8 %m1) 2314 %m2 = call i8 @llvm.umin.i8(i8 %m1, i8 %y) 2315 ret i8 %m2 2316} 2317 2318define i8 @smax_smax_smax_reassoc_constants(i8 %x, i8 %y) { 2319; CHECK-LABEL: @smax_smax_smax_reassoc_constants( 2320; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 2321; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 126) 2322; CHECK-NEXT: ret i8 [[M3]] 2323; 2324 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42) 2325 %m2 = call i8 @llvm.smax.i8(i8 %y, i8 %m1) 2326 %m3 = call i8 @llvm.smax.i8(i8 %m2, i8 126) 2327 ret i8 %m3 2328} 2329 2330define i8 @smax_smax_smax_reassoc_constants_swap(i8 %x, i8 %y) { 2331; CHECK-LABEL: @smax_smax_smax_reassoc_constants_swap( 2332; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 2333; CHECK-NEXT: [[M3:%.*]] = call i8 @llvm.smax.i8(i8 [[M1]], i8 126) 2334; CHECK-NEXT: ret i8 [[M3]] 2335; 2336 %m1 = call i8 @llvm.smax.i8(i8 %x, i8 42) 2337 %m2 = call i8 @llvm.smax.i8(i8 %m1, i8 %y) 2338 %m3 = call i8 @llvm.smax.i8(i8 %m2, i8 126) 2339 ret i8 %m3 2340} 2341 2342define i8 @smin_smin_smin_reassoc_constants(i8 %x, i8 %y) { 2343; CHECK-LABEL: @smin_smin_smin_reassoc_constants( 2344; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 2345; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.smin.i8(i8 [[M1]], i8 42) 2346; CHECK-NEXT: ret i8 [[M2]] 2347; 2348 %m1 = call i8 @llvm.smin.i8(i8 %x, i8 42) 2349 %m2 = call i8 @llvm.smin.i8(i8 %y, i8 %m1) 2350 %m3 = call i8 @llvm.smin.i8(i8 %m2, i8 126) 2351 ret i8 %m3 2352} 2353 2354define i8 @umax_umax_reassoc_constantexpr_sink(i8 %x, i8 %y) { 2355; CHECK-LABEL: @umax_umax_reassoc_constantexpr_sink( 2356; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 ptrtoint (ptr @umax_umax_reassoc_constantexpr_sink to i8)) 2357; CHECK-NEXT: [[M2:%.*]] = call i8 @llvm.umax.i8(i8 [[M1]], i8 42) 2358; CHECK-NEXT: ret i8 [[M2]] 2359; 2360 %m1 = call i8 @llvm.umax.i8(i8 %x, i8 42) 2361 %m2 = call i8 @llvm.umax.i8(i8 %m1, i8 ptrtoint (ptr @umax_umax_reassoc_constantexpr_sink to i8)) 2362 ret i8 %m2 2363} 2364 2365define <3 x i8> @smax_unary_shuffle_ops(<3 x i8> %x, <3 x i8> %y) { 2366; CHECK-LABEL: @smax_unary_shuffle_ops( 2367; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) 2368; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2369; CHECK-NEXT: ret <3 x i8> [[R]] 2370; 2371 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2372 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2373 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy) 2374 ret <3 x i8> %r 2375} 2376 2377define <3 x i8> @smin_unary_shuffle_ops_use_poison_mask_elt(<3 x i8> %x, <3 x i8> %y) { 2378; CHECK-LABEL: @smin_unary_shuffle_ops_use_poison_mask_elt( 2379; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2> 2380; CHECK-NEXT: call void @use_vec(<3 x i8> [[SX]]) 2381; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[X]], <3 x i8> [[Y:%.*]]) 2382; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2> 2383; CHECK-NEXT: ret <3 x i8> [[R]] 2384; 2385 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2> 2386 call void @use_vec(<3 x i8> %sx) 2387 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 poison, i32 0, i32 2> 2388 %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> %sy) 2389 ret <3 x i8> %r 2390} 2391 2392define <3 x i8> @umax_unary_shuffle_ops_use_widening(<2 x i8> %x, <2 x i8> %y) { 2393; CHECK-LABEL: @umax_unary_shuffle_ops_use_widening( 2394; CHECK-NEXT: [[SY:%.*]] = shufflevector <2 x i8> [[Y:%.*]], <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0> 2395; CHECK-NEXT: call void @use_vec(<3 x i8> [[SY]]) 2396; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.umax.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y]]) 2397; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0> 2398; CHECK-NEXT: ret <3 x i8> [[R]] 2399; 2400 %sx = shufflevector <2 x i8> %x, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0> 2401 %sy = shufflevector <2 x i8> %y, <2 x i8> poison, <3 x i32> <i32 1, i32 0, i32 0> 2402 call void @use_vec(<3 x i8> %sy) 2403 %r = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %sx, <3 x i8> %sy) 2404 ret <3 x i8> %r 2405} 2406 2407define <3 x i8> @umin_unary_shuffle_ops_narrowing(<4 x i8> %x, <4 x i8> %y) { 2408; CHECK-LABEL: @umin_unary_shuffle_ops_narrowing( 2409; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.umin.v4i8(<4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]]) 2410; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3> 2411; CHECK-NEXT: ret <3 x i8> [[R]] 2412; 2413 %sx = shufflevector <4 x i8> %x, <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3> 2414 %sy = shufflevector <4 x i8> %y, <4 x i8> poison, <3 x i32> <i32 1, i32 0, i32 3> 2415 %r = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sx, <3 x i8> %sy) 2416 ret <3 x i8> %r 2417} 2418 2419; negative test - must have 2 shuffles 2420 2421define <3 x i8> @smax_unary_shuffle_ops_unshuffled_op(<3 x i8> %x, <3 x i8> %y) { 2422; CHECK-LABEL: @smax_unary_shuffle_ops_unshuffled_op( 2423; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2> 2424; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[Y:%.*]]) 2425; CHECK-NEXT: ret <3 x i8> [[R]] 2426; 2427 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2> 2428 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %y) 2429 ret <3 x i8> %r 2430} 2431 2432; negative test - must have identical masks 2433 2434define <3 x i8> @smax_unary_shuffle_ops_wrong_mask(<3 x i8> %x, <3 x i8> %y) { 2435; CHECK-LABEL: @smax_unary_shuffle_ops_wrong_mask( 2436; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2> 2437; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2438; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]]) 2439; CHECK-NEXT: ret <3 x i8> [[R]] 2440; 2441 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 0, i32 0, i32 2> 2442 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2443 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy) 2444 ret <3 x i8> %r 2445} 2446 2447; negative test - must be unary shuffles 2448 2449define <3 x i8> @smax_unary_shuffle_ops_wrong_shuf(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) { 2450; CHECK-LABEL: @smax_unary_shuffle_ops_wrong_shuf( 2451; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> [[Z:%.*]], <3 x i32> <i32 1, i32 0, i32 3> 2452; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> [[Z]], <3 x i32> <i32 1, i32 0, i32 3> 2453; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]]) 2454; CHECK-NEXT: ret <3 x i8> [[R]] 2455; 2456 %sx = shufflevector <3 x i8> %x, <3 x i8> %z, <3 x i32> <i32 1, i32 0, i32 3> 2457 %sy = shufflevector <3 x i8> %y, <3 x i8> %z, <3 x i32> <i32 1, i32 0, i32 3> 2458 %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %sx, <3 x i8> %sy) 2459 ret <3 x i8> %r 2460} 2461 2462; negative test - too many uses 2463 2464define <3 x i8> @smin_unary_shuffle_ops_uses(<3 x i8> %x, <3 x i8> %y) { 2465; CHECK-LABEL: @smin_unary_shuffle_ops_uses( 2466; CHECK-NEXT: [[SX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2467; CHECK-NEXT: call void @use_vec(<3 x i8> [[SX]]) 2468; CHECK-NEXT: [[SY:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2469; CHECK-NEXT: call void @use_vec(<3 x i8> [[SY]]) 2470; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[SX]], <3 x i8> [[SY]]) 2471; CHECK-NEXT: ret <3 x i8> [[R]] 2472; 2473 %sx = shufflevector <3 x i8> %x, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2474 call void @use_vec(<3 x i8> %sx) 2475 %sy = shufflevector <3 x i8> %y, <3 x i8> poison, <3 x i32> <i32 1, i32 0, i32 2> 2476 call void @use_vec(<3 x i8> %sy) 2477 %r = call <3 x i8> @llvm.smin.v3i8(<3 x i8> %sx, <3 x i8> %sy) 2478 ret <3 x i8> %r 2479} 2480 2481; This would assert/crash because we tried to zext to i1. 2482 2483@g = external dso_local global i32, align 4 2484 2485define i1 @PR57986() { 2486; CHECK-LABEL: @PR57986( 2487; CHECK-NEXT: ret i1 ptrtoint (ptr @g to i1) 2488; 2489 %umin = call i1 @llvm.umin.i1(i1 ptrtoint (ptr @g to i1), i1 true) 2490 ret i1 %umin 2491} 2492 2493define i8 @fold_umax_with_knownbits_info(i8 %a, i8 %b) { 2494; CHECK-LABEL: @fold_umax_with_knownbits_info( 2495; CHECK-NEXT: entry: 2496; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 1 2497; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 1 2498; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]] 2499; CHECK-NEXT: ret i8 [[SUB]] 2500; 2501entry: 2502 %a1 = or i8 %a, 1 2503 %a2 = shl i8 %b, 1 2504 %sub = sub i8 %a1, %a2 2505 %val = call i8 @llvm.umax.i8(i8 %sub, i8 1) 2506 ret i8 %val 2507} 2508 2509define <3 x i8> @fold_umax_with_knownbits_info_poison_in_splat(<3 x i8> %a, <3 x i8> %b) { 2510; CHECK-LABEL: @fold_umax_with_knownbits_info_poison_in_splat( 2511; CHECK-NEXT: entry: 2512; CHECK-NEXT: [[A1:%.*]] = or <3 x i8> [[A:%.*]], splat (i8 1) 2513; CHECK-NEXT: [[A2:%.*]] = shl <3 x i8> [[B:%.*]], splat (i8 1) 2514; CHECK-NEXT: [[SUB:%.*]] = sub <3 x i8> [[A1]], [[A2]] 2515; CHECK-NEXT: ret <3 x i8> [[SUB]] 2516; 2517entry: 2518 %a1 = or <3 x i8> %a, <i8 1, i8 1, i8 1> 2519 %a2 = shl <3 x i8> %b, <i8 1, i8 1, i8 1> 2520 %sub = sub <3 x i8> %a1, %a2 2521 %val = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %sub, <3 x i8> <i8 1, i8 poison, i8 1>) 2522 ret <3 x i8> %val 2523} 2524 2525define i8 @fold_umin_with_knownbits_info(i8 %a, i8 %b) { 2526; CHECK-LABEL: @fold_umin_with_knownbits_info( 2527; CHECK-NEXT: entry: 2528; CHECK-NEXT: ret i8 3 2529; 2530entry: 2531 %a1 = or i8 %a, 3 2532 %a2 = shl i8 %b, 2 2533 %sub = sub i8 %a1, %a2 2534 %val = call i8 @llvm.umin.i8(i8 %sub, i8 3) 2535 ret i8 %val 2536} 2537 2538define <3 x i8> @fold_umin_with_knownbits_info_poison_in_splat(<3 x i8> %a, <3 x i8> %b) { 2539; CHECK-LABEL: @fold_umin_with_knownbits_info_poison_in_splat( 2540; CHECK-NEXT: entry: 2541; CHECK-NEXT: ret <3 x i8> splat (i8 3) 2542; 2543entry: 2544 %a1 = or <3 x i8> %a, <i8 3, i8 3, i8 3> 2545 %a2 = shl <3 x i8> %b, <i8 2, i8 2, i8 2> 2546 %sub = sub <3 x i8> %a1, %a2 2547 %val = call <3 x i8> @llvm.umin.v3i8(<3 x i8> %sub, <3 x i8> <i8 3, i8 poison, i8 3>) 2548 ret <3 x i8> %val 2549} 2550 2551define i8 @fold_umax_with_knownbits_info_fail(i8 %a, i8 %b) { 2552; CHECK-LABEL: @fold_umax_with_knownbits_info_fail( 2553; CHECK-NEXT: entry: 2554; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 2 2555; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 1 2556; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]] 2557; CHECK-NEXT: [[VAL:%.*]] = call i8 @llvm.umax.i8(i8 [[SUB]], i8 1) 2558; CHECK-NEXT: ret i8 [[VAL]] 2559; 2560entry: 2561 %a1 = or i8 %a, 2 2562 %a2 = shl i8 %b, 1 2563 %sub = sub i8 %a1, %a2 2564 %val = call i8 @llvm.umax.i8(i8 %sub, i8 1) 2565 ret i8 %val 2566} 2567 2568define i8 @fold_umin_with_knownbits_info_fail(i8 %a, i8 %b) { 2569; CHECK-LABEL: @fold_umin_with_knownbits_info_fail( 2570; CHECK-NEXT: entry: 2571; CHECK-NEXT: [[A1:%.*]] = or i8 [[A:%.*]], 1 2572; CHECK-NEXT: [[A2:%.*]] = shl i8 [[B:%.*]], 2 2573; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A1]], [[A2]] 2574; CHECK-NEXT: [[VAL:%.*]] = call i8 @llvm.umin.i8(i8 [[SUB]], i8 3) 2575; CHECK-NEXT: ret i8 [[VAL]] 2576; 2577entry: 2578 %a1 = or i8 %a, 1 2579 %a2 = shl i8 %b, 2 2580 %sub = sub i8 %a1, %a2 2581 %val = call i8 @llvm.umin.i8(i8 %sub, i8 3) 2582 ret i8 %val 2583} 2584 2585define i8 @test_umax_and(i8 %x, i8 %y) { 2586; CHECK-LABEL: @test_umax_and( 2587; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umax.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]]) 2588; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -64 2589; CHECK-NEXT: ret i8 [[RES1]] 2590; 2591 %x1 = and i8 %x, -64 2592 %y1 = and i8 %y, -64 2593 %res = call i8 @llvm.umax.i8(i8 %x1, i8 %y1) 2594 ret i8 %res 2595} 2596 2597define i8 @test_umin_and(i8 %x, i8 %y) { 2598; CHECK-LABEL: @test_umin_and( 2599; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umin.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]]) 2600; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -64 2601; CHECK-NEXT: ret i8 [[RES1]] 2602; 2603 %x1 = and i8 %x, -64 2604 %y1 = and i8 %y, -64 2605 %res = call i8 @llvm.umin.i8(i8 %x1, i8 %y1) 2606 ret i8 %res 2607} 2608 2609define i8 @test_smax_and(i8 %x, i8 %y) { 2610; CHECK-LABEL: @test_smax_and( 2611; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smax.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]]) 2612; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -64 2613; CHECK-NEXT: ret i8 [[RES1]] 2614; 2615 %x1 = and i8 %x, -64 2616 %y1 = and i8 %y, -64 2617 %res = call i8 @llvm.smax.i8(i8 %x1, i8 %y1) 2618 ret i8 %res 2619} 2620 2621define i8 @test_smin_and(i8 %x, i8 %y) { 2622; CHECK-LABEL: @test_smin_and( 2623; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1:%.*]], i8 [[Y1:%.*]]) 2624; CHECK-NEXT: [[RES1:%.*]] = and i8 [[RES]], -64 2625; CHECK-NEXT: ret i8 [[RES1]] 2626; 2627 %x1 = and i8 %x, -64 2628 %y1 = and i8 %y, -64 2629 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1) 2630 ret i8 %res 2631} 2632 2633define i8 @test_smin_and_mismatch(i8 %x, i8 %y) { 2634; CHECK-LABEL: @test_smin_and_mismatch( 2635; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], -64 2636; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], -32 2637; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]]) 2638; CHECK-NEXT: ret i8 [[RES]] 2639; 2640 %x1 = and i8 %x, -64 2641 %y1 = and i8 %y, -32 2642 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1) 2643 ret i8 %res 2644} 2645 2646define i8 @test_smin_and_non_negated_pow2(i8 %x, i8 %y) { 2647; CHECK-LABEL: @test_smin_and_non_negated_pow2( 2648; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], 31 2649; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], 31 2650; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]]) 2651; CHECK-NEXT: ret i8 [[RES]] 2652; 2653 %x1 = and i8 %x, 31 2654 %y1 = and i8 %y, 31 2655 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1) 2656 ret i8 %res 2657} 2658 2659define i8 @test_smin_and_multiuse(i8 %x, i8 %y) { 2660; CHECK-LABEL: @test_smin_and_multiuse( 2661; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], 31 2662; CHECK-NEXT: [[Y1:%.*]] = and i8 [[Y:%.*]], 31 2663; CHECK-NEXT: call void @use(i8 [[Y1]]) 2664; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.smin.i8(i8 [[X1]], i8 [[Y1]]) 2665; CHECK-NEXT: ret i8 [[RES]] 2666; 2667 %x1 = and i8 %x, 31 2668 %y1 = and i8 %y, 31 2669 call void @use(i8 %y1) 2670 %res = call i8 @llvm.smin.i8(i8 %x1, i8 %y1) 2671 ret i8 %res 2672} 2673