1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; This tests the InstructionCombining optimization that reduces things like: 5; %Y = sext i8 %X to i32 6; %C = icmp ult i32 %Y, 1024 7; to 8; %C = i1 true 9; It includes test cases for different constant values, signedness of the 10; cast operands, and types of setCC operators. In all cases, the cast should 11; be eliminated. In many cases the setCC is also eliminated based on the 12; constant value and the range of the casted value. 13; 14 15define i1 @lt_signed_to_large_unsigned(i8 %SB) { 16; CHECK-LABEL: @lt_signed_to_large_unsigned( 17; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[SB:%.*]], -1 18; CHECK-NEXT: ret i1 [[C]] 19; 20 %Y = sext i8 %SB to i32 21 %C = icmp ult i32 %Y, 1024 22 ret i1 %C 23} 24 25; PR28011 - https://llvm.org/bugs/show_bug.cgi?id=28011 26; The above transform only applies to scalar integers; it shouldn't be attempted for constant expressions or vectors. 27 28@a = common global i32** null 29@b = common global [1 x i32] zeroinitializer 30 31define i1 @PR28011(i16 %a) { 32; CHECK-LABEL: @PR28011( 33; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32 34; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[CONV]], or (i32 zext (i1 icmp ne (i32*** bitcast ([1 x i32]* @b to i32***), i32*** @a) to i32), i32 1) 35; CHECK-NEXT: ret i1 [[CMP]] 36; 37 %conv = sext i16 %a to i32 38 %cmp = icmp ne i32 %conv, or (i32 zext (i1 icmp ne (i32*** bitcast ([1 x i32]* @b to i32***), i32*** @a) to i32), i32 1) 39 ret i1 %cmp 40} 41 42define <2 x i1> @lt_signed_to_large_unsigned_vec(<2 x i8> %SB) { 43; CHECK-LABEL: @lt_signed_to_large_unsigned_vec( 44; CHECK-NEXT: [[Y:%.*]] = sext <2 x i8> [[SB:%.*]] to <2 x i32> 45; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i32> [[Y]], <i32 1024, i32 2> 46; CHECK-NEXT: ret <2 x i1> [[C]] 47; 48 %Y = sext <2 x i8> %SB to <2 x i32> 49 %C = icmp ult <2 x i32> %Y, <i32 1024, i32 2> 50 ret <2 x i1> %C 51} 52 53define i1 @lt_signed_to_large_signed(i8 %SB) { 54; CHECK-LABEL: @lt_signed_to_large_signed( 55; CHECK-NEXT: ret i1 true 56; 57 %Y = sext i8 %SB to i32 58 %C = icmp slt i32 %Y, 1024 59 ret i1 %C 60} 61 62define i1 @lt_signed_to_large_negative(i8 %SB) { 63; CHECK-LABEL: @lt_signed_to_large_negative( 64; CHECK-NEXT: ret i1 false 65; 66 %Y = sext i8 %SB to i32 67 %C = icmp slt i32 %Y, -1024 68 ret i1 %C 69} 70 71define i1 @lt_signed_to_small_unsigned(i8 %SB) { 72; CHECK-LABEL: @lt_signed_to_small_unsigned( 73; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17 74; CHECK-NEXT: ret i1 [[C]] 75; 76 %Y = sext i8 %SB to i32 77 %C = icmp ult i32 %Y, 17 78 ret i1 %C 79} 80 81define i1 @lt_signed_to_small_signed(i8 %SB) { 82; CHECK-LABEL: @lt_signed_to_small_signed( 83; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[SB:%.*]], 17 84; CHECK-NEXT: ret i1 [[C]] 85; 86 %Y = sext i8 %SB to i32 87 %C = icmp slt i32 %Y, 17 88 ret i1 %C 89} 90define i1 @lt_signed_to_small_negative(i8 %SB) { 91; CHECK-LABEL: @lt_signed_to_small_negative( 92; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[SB:%.*]], -17 93; CHECK-NEXT: ret i1 [[C]] 94; 95 %Y = sext i8 %SB to i32 96 %C = icmp slt i32 %Y, -17 97 ret i1 %C 98} 99 100define i1 @lt_unsigned_to_large_unsigned(i8 %SB) { 101; CHECK-LABEL: @lt_unsigned_to_large_unsigned( 102; CHECK-NEXT: ret i1 true 103; 104 %Y = zext i8 %SB to i32 105 %C = icmp ult i32 %Y, 1024 106 ret i1 %C 107} 108 109define i1 @lt_unsigned_to_large_signed(i8 %SB) { 110; CHECK-LABEL: @lt_unsigned_to_large_signed( 111; CHECK-NEXT: ret i1 true 112; 113 %Y = zext i8 %SB to i32 114 %C = icmp slt i32 %Y, 1024 115 ret i1 %C 116} 117 118define i1 @lt_unsigned_to_large_negative(i8 %SB) { 119; CHECK-LABEL: @lt_unsigned_to_large_negative( 120; CHECK-NEXT: ret i1 false 121; 122 %Y = zext i8 %SB to i32 123 %C = icmp slt i32 %Y, -1024 124 ret i1 %C 125} 126 127define i1 @lt_unsigned_to_small_unsigned(i8 %SB) { 128; CHECK-LABEL: @lt_unsigned_to_small_unsigned( 129; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17 130; CHECK-NEXT: ret i1 [[C]] 131; 132 %Y = zext i8 %SB to i32 133 %C = icmp ult i32 %Y, 17 134 ret i1 %C 135} 136 137define i1 @lt_unsigned_to_small_signed(i8 %SB) { 138; CHECK-LABEL: @lt_unsigned_to_small_signed( 139; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[SB:%.*]], 17 140; CHECK-NEXT: ret i1 [[C]] 141; 142 %Y = zext i8 %SB to i32 143 %C = icmp slt i32 %Y, 17 144 ret i1 %C 145} 146 147define i1 @lt_unsigned_to_small_negative(i8 %SB) { 148; CHECK-LABEL: @lt_unsigned_to_small_negative( 149; CHECK-NEXT: ret i1 false 150; 151 %Y = zext i8 %SB to i32 152 %C = icmp slt i32 %Y, -17 153 ret i1 %C 154} 155 156define i1 @gt_signed_to_large_unsigned(i8 %SB) { 157; CHECK-LABEL: @gt_signed_to_large_unsigned( 158; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[SB:%.*]], 0 159; CHECK-NEXT: ret i1 [[C]] 160; 161 %Y = sext i8 %SB to i32 162 %C = icmp ugt i32 %Y, 1024 163 ret i1 %C 164} 165 166define i1 @gt_signed_to_large_signed(i8 %SB) { 167; CHECK-LABEL: @gt_signed_to_large_signed( 168; CHECK-NEXT: ret i1 false 169; 170 %Y = sext i8 %SB to i32 171 %C = icmp sgt i32 %Y, 1024 172 ret i1 %C 173} 174 175define i1 @gt_signed_to_large_negative(i8 %SB) { 176; CHECK-LABEL: @gt_signed_to_large_negative( 177; CHECK-NEXT: ret i1 true 178; 179 %Y = sext i8 %SB to i32 180 %C = icmp sgt i32 %Y, -1024 181 ret i1 %C 182} 183 184define i1 @gt_signed_to_small_unsigned(i8 %SB) { 185; CHECK-LABEL: @gt_signed_to_small_unsigned( 186; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17 187; CHECK-NEXT: ret i1 [[C]] 188; 189 %Y = sext i8 %SB to i32 190 %C = icmp ugt i32 %Y, 17 191 ret i1 %C 192} 193 194define i1 @gt_signed_to_small_signed(i8 %SB) { 195; CHECK-LABEL: @gt_signed_to_small_signed( 196; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[SB:%.*]], 17 197; CHECK-NEXT: ret i1 [[C]] 198; 199 %Y = sext i8 %SB to i32 200 %C = icmp sgt i32 %Y, 17 201 ret i1 %C 202} 203 204define i1 @gt_signed_to_small_negative(i8 %SB) { 205; CHECK-LABEL: @gt_signed_to_small_negative( 206; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[SB:%.*]], -17 207; CHECK-NEXT: ret i1 [[C]] 208; 209 %Y = sext i8 %SB to i32 210 %C = icmp sgt i32 %Y, -17 211 ret i1 %C 212} 213 214define i1 @gt_unsigned_to_large_unsigned(i8 %SB) { 215; CHECK-LABEL: @gt_unsigned_to_large_unsigned( 216; CHECK-NEXT: ret i1 false 217; 218 %Y = zext i8 %SB to i32 219 %C = icmp ugt i32 %Y, 1024 220 ret i1 %C 221} 222 223define i1 @gt_unsigned_to_large_signed(i8 %SB) { 224; CHECK-LABEL: @gt_unsigned_to_large_signed( 225; CHECK-NEXT: ret i1 false 226; 227 %Y = zext i8 %SB to i32 228 %C = icmp sgt i32 %Y, 1024 229 ret i1 %C 230} 231 232define i1 @gt_unsigned_to_large_negative(i8 %SB) { 233; CHECK-LABEL: @gt_unsigned_to_large_negative( 234; CHECK-NEXT: ret i1 true 235; 236 %Y = zext i8 %SB to i32 237 %C = icmp sgt i32 %Y, -1024 238 ret i1 %C 239} 240 241define i1 @gt_unsigned_to_small_unsigned(i8 %SB) { 242; CHECK-LABEL: @gt_unsigned_to_small_unsigned( 243; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17 244; CHECK-NEXT: ret i1 [[C]] 245; 246 %Y = zext i8 %SB to i32 247 %C = icmp ugt i32 %Y, 17 248 ret i1 %C 249} 250 251define i1 @gt_unsigned_to_small_signed(i8 %SB) { 252; CHECK-LABEL: @gt_unsigned_to_small_signed( 253; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[SB:%.*]], 17 254; CHECK-NEXT: ret i1 [[C]] 255; 256 %Y = zext i8 %SB to i32 257 %C = icmp sgt i32 %Y, 17 258 ret i1 %C 259} 260 261define i1 @gt_unsigned_to_small_negative(i8 %SB) { 262; CHECK-LABEL: @gt_unsigned_to_small_negative( 263; CHECK-NEXT: ret i1 true 264; 265 %Y = zext i8 %SB to i32 266 %C = icmp sgt i32 %Y, -17 267 ret i1 %C 268} 269 270define i1 @different_size_zext_zext_ugt(i7 %x, i4 %y) { 271; CHECK-LABEL: @different_size_zext_zext_ugt( 272; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7 273; CHECK-NEXT: [[R:%.*]] = icmp ult i7 [[TMP1]], [[X:%.*]] 274; CHECK-NEXT: ret i1 [[R]] 275; 276 %zx = zext i7 %x to i25 277 %zy = zext i4 %y to i25 278 %r = icmp ugt i25 %zx, %zy 279 ret i1 %r 280} 281 282define <2 x i1> @different_size_zext_zext_ugt_commute(<2 x i4> %x, <2 x i7> %y) { 283; CHECK-LABEL: @different_size_zext_zext_ugt_commute( 284; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i4> [[X:%.*]] to <2 x i7> 285; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i7> [[TMP1]], [[Y:%.*]] 286; CHECK-NEXT: ret <2 x i1> [[R]] 287; 288 %zx = zext <2 x i4> %x to <2 x i25> 289 %zy = zext <2 x i7> %y to <2 x i25> 290 %r = icmp ugt <2 x i25> %zx, %zy 291 ret <2 x i1> %r 292} 293 294define i1 @different_size_zext_zext_ult(i4 %x, i7 %y) { 295; CHECK-LABEL: @different_size_zext_zext_ult( 296; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[X:%.*]] to i7 297; CHECK-NEXT: [[R:%.*]] = icmp ult i7 [[TMP1]], [[Y:%.*]] 298; CHECK-NEXT: ret i1 [[R]] 299; 300 %zx = zext i4 %x to i25 301 %zy = zext i7 %y to i25 302 %r = icmp ult i25 %zx, %zy 303 ret i1 %r 304} 305 306define i1 @different_size_zext_zext_eq(i4 %x, i7 %y) { 307; CHECK-LABEL: @different_size_zext_zext_eq( 308; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[X:%.*]] to i7 309; CHECK-NEXT: [[R:%.*]] = icmp eq i7 [[TMP1]], [[Y:%.*]] 310; CHECK-NEXT: ret i1 [[R]] 311; 312 %zx = zext i4 %x to i25 313 %zy = zext i7 %y to i25 314 %r = icmp eq i25 %zx, %zy 315 ret i1 %r 316} 317 318define i1 @different_size_zext_zext_ne_commute(i7 %x, i4 %y) { 319; CHECK-LABEL: @different_size_zext_zext_ne_commute( 320; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7 321; CHECK-NEXT: [[R:%.*]] = icmp ne i7 [[TMP1]], [[X:%.*]] 322; CHECK-NEXT: ret i1 [[R]] 323; 324 %zx = zext i7 %x to i25 325 %zy = zext i4 %y to i25 326 %r = icmp ne i25 %zx, %zy 327 ret i1 %r 328} 329 330define i1 @different_size_zext_zext_slt(i7 %x, i4 %y) { 331; CHECK-LABEL: @different_size_zext_zext_slt( 332; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7 333; CHECK-NEXT: [[R:%.*]] = icmp ugt i7 [[TMP1]], [[X:%.*]] 334; CHECK-NEXT: ret i1 [[R]] 335; 336 %zx = zext i7 %x to i25 337 %zy = zext i4 %y to i25 338 %r = icmp slt i25 %zx, %zy 339 ret i1 %r 340} 341 342define i1 @different_size_zext_zext_sgt(i7 %x, i4 %y) { 343; CHECK-LABEL: @different_size_zext_zext_sgt( 344; CHECK-NEXT: [[TMP1:%.*]] = zext i4 [[Y:%.*]] to i7 345; CHECK-NEXT: [[R:%.*]] = icmp ult i7 [[TMP1]], [[X:%.*]] 346; CHECK-NEXT: ret i1 [[R]] 347; 348 %zx = zext i7 %x to i25 349 %zy = zext i4 %y to i25 350 %r = icmp sgt i25 %zx, %zy 351 ret i1 %r 352} 353 354define i1 @different_size_sext_sext_sgt(i7 %x, i4 %y) { 355; CHECK-LABEL: @different_size_sext_sext_sgt( 356; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7 357; CHECK-NEXT: [[R:%.*]] = icmp slt i7 [[TMP1]], [[X:%.*]] 358; CHECK-NEXT: ret i1 [[R]] 359; 360 %sx = sext i7 %x to i25 361 %sy = sext i4 %y to i25 362 %r = icmp sgt i25 %sx, %sy 363 ret i1 %r 364} 365 366define i1 @different_size_sext_sext_sle(i7 %x, i4 %y) { 367; CHECK-LABEL: @different_size_sext_sext_sle( 368; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7 369; CHECK-NEXT: [[R:%.*]] = icmp sge i7 [[TMP1]], [[X:%.*]] 370; CHECK-NEXT: ret i1 [[R]] 371; 372 %sx = sext i7 %x to i25 373 %sy = sext i4 %y to i25 374 %r = icmp sle i25 %sx, %sy 375 ret i1 %r 376} 377 378define i1 @different_size_sext_sext_eq(i7 %x, i4 %y) { 379; CHECK-LABEL: @different_size_sext_sext_eq( 380; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7 381; CHECK-NEXT: [[R:%.*]] = icmp eq i7 [[TMP1]], [[X:%.*]] 382; CHECK-NEXT: ret i1 [[R]] 383; 384 %sx = sext i7 %x to i25 385 %sy = sext i4 %y to i25 386 %r = icmp eq i25 %sx, %sy 387 ret i1 %r 388} 389 390define i1 @different_size_sext_sext_ule(i7 %x, i4 %y) { 391; CHECK-LABEL: @different_size_sext_sext_ule( 392; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7 393; CHECK-NEXT: [[R:%.*]] = icmp uge i7 [[TMP1]], [[X:%.*]] 394; CHECK-NEXT: ret i1 [[R]] 395; 396 %sx = sext i7 %x to i25 397 %sy = sext i4 %y to i25 398 %r = icmp ule i25 %sx, %sy 399 ret i1 %r 400} 401 402; TODO: This can be reduced. 403 404define i1 @different_size_sext_zext_ne(i7 %x, i4 %y) { 405; CHECK-LABEL: @different_size_sext_zext_ne( 406; CHECK-NEXT: [[SX:%.*]] = sext i7 [[X:%.*]] to i25 407; CHECK-NEXT: [[ZY:%.*]] = zext i4 [[Y:%.*]] to i25 408; CHECK-NEXT: [[R:%.*]] = icmp ne i25 [[SX]], [[ZY]] 409; CHECK-NEXT: ret i1 [[R]] 410; 411 %sx = sext i7 %x to i25 412 %zy = zext i4 %y to i25 413 %r = icmp ne i25 %sx, %zy 414 ret i1 %r 415} 416 417declare void @use(i25) 418 419define i1 @different_size_sext_sext_ule_extra_use1(i7 %x, i4 %y) { 420; CHECK-LABEL: @different_size_sext_sext_ule_extra_use1( 421; CHECK-NEXT: [[SY:%.*]] = sext i4 [[Y:%.*]] to i25 422; CHECK-NEXT: call void @use(i25 [[SY]]) 423; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y]] to i7 424; CHECK-NEXT: [[R:%.*]] = icmp uge i7 [[TMP1]], [[X:%.*]] 425; CHECK-NEXT: ret i1 [[R]] 426; 427 %sx = sext i7 %x to i25 428 %sy = sext i4 %y to i25 429 call void @use(i25 %sy) 430 %r = icmp ule i25 %sx, %sy 431 ret i1 %r 432} 433 434define i1 @different_size_sext_sext_ule_extra_use2(i7 %x, i4 %y) { 435; CHECK-LABEL: @different_size_sext_sext_ule_extra_use2( 436; CHECK-NEXT: [[SX:%.*]] = sext i7 [[X:%.*]] to i25 437; CHECK-NEXT: call void @use(i25 [[SX]]) 438; CHECK-NEXT: [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7 439; CHECK-NEXT: [[R:%.*]] = icmp uge i7 [[TMP1]], [[X]] 440; CHECK-NEXT: ret i1 [[R]] 441; 442 %sx = sext i7 %x to i25 443 call void @use(i25 %sx) 444 %sy = sext i4 %y to i25 445 %r = icmp ule i25 %sx, %sy 446 ret i1 %r 447} 448 449; Negative test - extra uses on both casts is too much. 450 451define i1 @different_size_sext_sext_ule_extra_use3(i7 %x, i4 %y) { 452; CHECK-LABEL: @different_size_sext_sext_ule_extra_use3( 453; CHECK-NEXT: [[SX:%.*]] = sext i7 [[X:%.*]] to i25 454; CHECK-NEXT: call void @use(i25 [[SX]]) 455; CHECK-NEXT: [[SY:%.*]] = sext i4 [[Y:%.*]] to i25 456; CHECK-NEXT: call void @use(i25 [[SY]]) 457; CHECK-NEXT: [[R:%.*]] = icmp ule i25 [[SX]], [[SY]] 458; CHECK-NEXT: ret i1 [[R]] 459; 460 %sx = sext i7 %x to i25 461 call void @use(i25 %sx) 462 %sy = sext i4 %y to i25 463 call void @use(i25 %sy) 464 %r = icmp ule i25 %sx, %sy 465 ret i1 %r 466} 467