1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s 3 4declare void @use.i16(i16) 5declare i16 @llvm.usub.sat.i16(i16, i16) 6declare i16 @llvm.uadd.sat.i16(i16, i16) 7declare i16 @llvm.umin.i16(i16, i16) 8declare i16 @llvm.abs.i16(i16, i1) 9 10define i16 @sel_true_cond(i16 noundef %x) { 11; CHECK-LABEL: @sel_true_cond( 12; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10 13; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 14; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB1]], i16 42 15; CHECK-NEXT: ret i16 [[SEL]] 16; 17 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 18 %cmp = icmp uge i16 %x, 10 19 %sel = select i1 %cmp, i16 %sub, i16 42 20 ret i16 %sel 21} 22 23define i16 @sel_true_cond_insufficient(i16 %x) { 24; CHECK-LABEL: @sel_true_cond_insufficient( 25; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 26; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 9 27; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42 28; CHECK-NEXT: ret i16 [[SEL]] 29; 30 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 31 %cmp = icmp uge i16 %x, 9 32 %sel = select i1 %cmp, i16 %sub, i16 42 33 ret i16 %sel 34} 35 36define i16 @sel_true_cond_wrong_swap(i16 %x) { 37; CHECK-LABEL: @sel_true_cond_wrong_swap( 38; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 39; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 40; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB]] 41; CHECK-NEXT: ret i16 [[SEL]] 42; 43 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 44 %cmp = icmp uge i16 %x, 10 45 %sel = select i1 %cmp, i16 42, i16 %sub 46 ret i16 %sel 47} 48 49define i16 @sel_true_cond_wrong_op(i16 %x, i16 %y) { 50; CHECK-LABEL: @sel_true_cond_wrong_op( 51; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 52; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[Y:%.*]], 10 53; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42 54; CHECK-NEXT: ret i16 [[SEL]] 55; 56 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 57 %cmp = icmp uge i16 %y, 10 58 %sel = select i1 %cmp, i16 %sub, i16 42 59 ret i16 %sel 60} 61 62define i16 @sel_true_cond_extra_use(i16 %x) { 63; CHECK-LABEL: @sel_true_cond_extra_use( 64; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 65; CHECK-NEXT: call void @use.i16(i16 [[SUB]]) 66; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 67; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SUB]], i16 42 68; CHECK-NEXT: ret i16 [[SEL]] 69; 70 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 71 call void @use.i16(i16 %sub) 72 %cmp = icmp uge i16 %x, 10 73 %sel = select i1 %cmp, i16 %sub, i16 42 74 ret i16 %sel 75} 76 77define i16 @sel_true_cond_chain_speculatable(i16 noundef %x) { 78; CHECK-LABEL: @sel_true_cond_chain_speculatable( 79; CHECK-NEXT: [[SUB1:%.*]] = add nuw i16 [[X:%.*]], 1 80; CHECK-NEXT: [[EXTRA:%.*]] = mul i16 [[SUB1]], 3 81; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[X]], -1 82; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA]], i16 42 83; CHECK-NEXT: ret i16 [[SEL]] 84; 85 %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1) 86 %extra = mul i16 %sub, 3 87 %cmp = icmp ne i16 %x, -1 88 %sel = select i1 %cmp, i16 %extra, i16 42 89 ret i16 %sel 90} 91 92define i16 @sel_true_cond_chain_non_speculatable(i16 %x) { 93; CHECK-LABEL: @sel_true_cond_chain_non_speculatable( 94; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1) 95; CHECK-NEXT: [[EXTRA:%.*]] = udiv i16 3, [[SUB]] 96; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[X]], -1 97; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA]], i16 42 98; CHECK-NEXT: ret i16 [[SEL]] 99; 100 %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1) 101 %extra = udiv i16 3, %sub 102 %cmp = icmp ne i16 %x, -1 103 %sel = select i1 %cmp, i16 %extra, i16 42 104 ret i16 %sel 105} 106 107; TODO: We could handle this case by raising the limit on the number of 108; instructions we look through. 109define i16 @sel_true_cond_longer_chain(i16 %x) { 110; CHECK-LABEL: @sel_true_cond_longer_chain( 111; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1) 112; CHECK-NEXT: [[EXTRA:%.*]] = mul i16 [[SUB]], 3 113; CHECK-NEXT: [[EXTRA2:%.*]] = xor i16 [[SUB]], 7 114; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[X]], -1 115; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA2]], i16 42 116; CHECK-NEXT: ret i16 [[SEL]] 117; 118 %sub = call i16 @llvm.uadd.sat.i16(i16 %x, i16 1) 119 %extra = mul i16 %sub, 3 120 %extra2 = xor i16 %sub, 7 121 %cmp = icmp ne i16 %x, -1 122 %sel = select i1 %cmp, i16 %extra2, i16 42 123 ret i16 %sel 124} 125 126define i16 @sel_false_cond(i16 noundef %x) { 127; CHECK-LABEL: @sel_false_cond( 128; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10 129; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 10 130; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB1]] 131; CHECK-NEXT: ret i16 [[SEL]] 132; 133 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 134 %cmp = icmp ult i16 %x, 10 135 %sel = select i1 %cmp, i16 42, i16 %sub 136 ret i16 %sel 137} 138 139define i16 @sel_false_cond_insufficient(i16 %x) { 140; CHECK-LABEL: @sel_false_cond_insufficient( 141; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 142; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 9 143; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 42, i16 [[SUB]] 144; CHECK-NEXT: ret i16 [[SEL]] 145; 146 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 147 %cmp = icmp ult i16 %x, 9 148 %sel = select i1 %cmp, i16 42, i16 %sub 149 ret i16 %sel 150} 151 152define i16 @phi_true_cond(i16 %x) { 153; CHECK-LABEL: @phi_true_cond( 154; CHECK-NEXT: entry: 155; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10 156; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 157; CHECK-NEXT: br i1 [[CMP]], label [[JOIN:%.*]], label [[SPLIT:%.*]] 158; CHECK: split: 159; CHECK-NEXT: br label [[JOIN]] 160; CHECK: join: 161; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB1]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ] 162; CHECK-NEXT: ret i16 [[PHI]] 163; 164entry: 165 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 166 %cmp = icmp uge i16 %x, 10 167 br i1 %cmp, label %join, label %split 168 169split: 170 br label %join 171 172join: 173 %phi = phi i16 [ %sub, %entry ], [ 42, %split ] 174 ret i16 %phi 175} 176 177define i16 @phi_true_cond_insufficient(i16 %x) { 178; CHECK-LABEL: @phi_true_cond_insufficient( 179; CHECK-NEXT: entry: 180; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 181; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 9 182; CHECK-NEXT: br i1 [[CMP]], label [[JOIN:%.*]], label [[SPLIT:%.*]] 183; CHECK: split: 184; CHECK-NEXT: br label [[JOIN]] 185; CHECK: join: 186; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ] 187; CHECK-NEXT: ret i16 [[PHI]] 188; 189entry: 190 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 191 %cmp = icmp uge i16 %x, 9 192 br i1 %cmp, label %join, label %split 193 194split: 195 br label %join 196 197join: 198 %phi = phi i16 [ %sub, %entry ], [ 42, %split ] 199 ret i16 %phi 200} 201 202; TODO: We could handle this by using conditions that are not directly on the 203; phi edge. 204define i16 @phi_true_cond_non_local(i16 %x) { 205; CHECK-LABEL: @phi_true_cond_non_local( 206; CHECK-NEXT: entry: 207; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 208; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[X]], 10 209; CHECK-NEXT: br i1 [[CMP]], label [[SPLIT:%.*]], label [[JOIN:%.*]] 210; CHECK: split: 211; CHECK-NEXT: br label [[JOIN]] 212; CHECK: join: 213; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB]], [[SPLIT]] ], [ 42, [[ENTRY:%.*]] ] 214; CHECK-NEXT: ret i16 [[PHI]] 215; 216entry: 217 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 218 %cmp = icmp uge i16 %x, 10 219 br i1 %cmp, label %split, label %join 220 221split: 222 br label %join 223 224join: 225 %phi = phi i16 [ %sub, %split ], [ 42, %entry ] 226 ret i16 %phi 227} 228 229define i16 @phi_false_cond(i16 %x) { 230; CHECK-LABEL: @phi_false_cond( 231; CHECK-NEXT: entry: 232; CHECK-NEXT: [[SUB1:%.*]] = sub nuw i16 [[X:%.*]], 10 233; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 10 234; CHECK-NEXT: br i1 [[CMP]], label [[SPLIT:%.*]], label [[JOIN:%.*]] 235; CHECK: split: 236; CHECK-NEXT: br label [[JOIN]] 237; CHECK: join: 238; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB1]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ] 239; CHECK-NEXT: ret i16 [[PHI]] 240; 241entry: 242 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 243 %cmp = icmp ult i16 %x, 10 244 br i1 %cmp, label %split, label %join 245 246split: 247 br label %join 248 249join: 250 %phi = phi i16 [ %sub, %entry ], [ 42, %split ] 251 ret i16 %phi 252} 253 254define i16 @phi_false_cond_insufficient(i16 %x) { 255; CHECK-LABEL: @phi_false_cond_insufficient( 256; CHECK-NEXT: entry: 257; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 258; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 9 259; CHECK-NEXT: br i1 [[CMP]], label [[SPLIT:%.*]], label [[JOIN:%.*]] 260; CHECK: split: 261; CHECK-NEXT: br label [[JOIN]] 262; CHECK: join: 263; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB]], [[ENTRY:%.*]] ], [ 42, [[SPLIT]] ] 264; CHECK-NEXT: ret i16 [[PHI]] 265; 266entry: 267 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 268 %cmp = icmp ult i16 %x, 9 269 br i1 %cmp, label %split, label %join 270 271split: 272 br label %join 273 274join: 275 %phi = phi i16 [ %sub, %entry ], [ 42, %split ] 276 ret i16 %phi 277} 278 279; TODO: We could handle this by using conditions that are not directly on the 280; phi edge. 281define i16 @phi_false_cond_non_local(i16 %x) { 282; CHECK-LABEL: @phi_false_cond_non_local( 283; CHECK-NEXT: entry: 284; CHECK-NEXT: [[SUB:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[X:%.*]], i16 10) 285; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 10 286; CHECK-NEXT: br i1 [[CMP]], label [[JOIN:%.*]], label [[SPLIT:%.*]] 287; CHECK: split: 288; CHECK-NEXT: br label [[JOIN]] 289; CHECK: join: 290; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ [[SUB]], [[SPLIT]] ], [ 42, [[ENTRY:%.*]] ] 291; CHECK-NEXT: ret i16 [[PHI]] 292; 293entry: 294 %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10) 295 %cmp = icmp ult i16 %x, 10 296 br i1 %cmp, label %join, label %split 297 298split: 299 br label %join 300 301join: 302 %phi = phi i16 [ %sub, %split ], [ 42, %entry ] 303 ret i16 %phi 304} 305 306define i16 @loop_cond() { 307; CHECK-LABEL: @loop_cond( 308; CHECK-NEXT: entry: 309; CHECK-NEXT: br label [[LOOP:%.*]] 310; CHECK: loop: 311; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 1000, [[ENTRY:%.*]] ], [ [[IV_NEXT1:%.*]], [[LOOP]] ] 312; CHECK-NEXT: [[COUNT:%.*]] = phi i16 [ 0, [[ENTRY]] ], [ [[COUNT_NEXT:%.*]], [[LOOP]] ] 313; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[IV]], 0 314; CHECK-NEXT: [[IV_NEXT1]] = sub nuw i16 [[IV]], 1 315; CHECK-NEXT: [[COUNT_NEXT]] = add i16 [[COUNT]], 1 316; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 317; CHECK: exit: 318; CHECK-NEXT: ret i16 [[COUNT]] 319; 320entry: 321 br label %loop 322 323loop: 324 %iv = phi i16 [ 1000, %entry ], [ %iv.next, %loop ] 325 %count = phi i16 [ 0, %entry ], [ %count.next, %loop ] 326 %cmp = icmp eq i16 %iv, 0 327 %iv.next = call i16 @llvm.usub.sat.i16(i16 %iv, i16 1) 328 %count.next = add i16 %count, 1 329 br i1 %cmp, label %exit, label %loop 330 331exit: 332 ret i16 %count 333} 334 335define i16 @urem_elide(i16 noundef %x) { 336; CHECK-LABEL: @urem_elide( 337; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X:%.*]], 42 338; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[X]], i16 24 339; CHECK-NEXT: ret i16 [[SEL]] 340; 341 %urem = urem i16 %x, 42 342 %cmp = icmp ult i16 %x, 42 343 %sel = select i1 %cmp, i16 %urem, i16 24 344 ret i16 %sel 345} 346 347define i16 @urem_expand(i16 noundef %x) { 348; CHECK-LABEL: @urem_expand( 349; CHECK-NEXT: [[UREM_UREM:%.*]] = sub nuw i16 [[X:%.*]], 42 350; CHECK-NEXT: [[UREM_CMP:%.*]] = icmp ult i16 [[X]], 42 351; CHECK-NEXT: [[UREM:%.*]] = select i1 [[UREM_CMP]], i16 [[X]], i16 [[UREM_UREM]] 352; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 84 353; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM]], i16 24 354; CHECK-NEXT: ret i16 [[SEL]] 355; 356 %urem = urem i16 %x, 42 357 %cmp = icmp ult i16 %x, 84 358 %sel = select i1 %cmp, i16 %urem, i16 24 359 ret i16 %sel 360} 361 362define i16 @urem_narrow(i16 noundef %x) { 363; CHECK-LABEL: @urem_narrow( 364; CHECK-NEXT: [[UREM_LHS_TRUNC:%.*]] = trunc i16 [[X:%.*]] to i8 365; CHECK-NEXT: [[UREM1:%.*]] = urem i8 [[UREM_LHS_TRUNC]], 42 366; CHECK-NEXT: [[UREM_ZEXT:%.*]] = zext i8 [[UREM1]] to i16 367; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 85 368; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM_ZEXT]], i16 24 369; CHECK-NEXT: ret i16 [[SEL]] 370; 371 %urem = urem i16 %x, 42 372 %cmp = icmp ult i16 %x, 85 373 %sel = select i1 %cmp, i16 %urem, i16 24 374 ret i16 %sel 375} 376 377define i16 @urem_insufficient(i16 %x) { 378; CHECK-LABEL: @urem_insufficient( 379; CHECK-NEXT: [[UREM:%.*]] = urem i16 [[X:%.*]], 42 380; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 257 381; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[UREM]], i16 24 382; CHECK-NEXT: ret i16 [[SEL]] 383; 384 %urem = urem i16 %x, 42 385 %cmp = icmp ult i16 %x, 257 386 %sel = select i1 %cmp, i16 %urem, i16 24 387 ret i16 %sel 388} 389 390define i16 @srem_elide(i16 noundef %x) { 391; CHECK-LABEL: @srem_elide( 392; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i16 [[X:%.*]], 42 393; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i16 [[X]], -42 394; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 395; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], i16 [[X]], i16 24 396; CHECK-NEXT: ret i16 [[SEL]] 397; 398 %srem = srem i16 %x, 42 399 %cmp1 = icmp slt i16 %x, 42 400 %cmp2 = icmp sgt i16 %x, -42 401 %and = and i1 %cmp1, %cmp2 402 %sel = select i1 %and, i16 %srem, i16 24 403 ret i16 %sel 404} 405 406define i16 @srem_narrow(i16 noundef %x) { 407; CHECK-LABEL: @srem_narrow( 408; CHECK-NEXT: [[SREM_LHS_TRUNC:%.*]] = trunc i16 [[X:%.*]] to i8 409; CHECK-NEXT: [[SREM1:%.*]] = srem i8 [[SREM_LHS_TRUNC]], 42 410; CHECK-NEXT: [[SREM_SEXT:%.*]] = sext i8 [[SREM1]] to i16 411; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i16 [[X]], 43 412; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i16 [[X]], -43 413; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 414; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], i16 [[SREM_SEXT]], i16 24 415; CHECK-NEXT: ret i16 [[SEL]] 416; 417 %srem = srem i16 %x, 42 418 %cmp1 = icmp slt i16 %x, 43 419 %cmp2 = icmp sgt i16 %x, -43 420 %and = and i1 %cmp1, %cmp2 421 %sel = select i1 %and, i16 %srem, i16 24 422 ret i16 %sel 423} 424 425define i16 @srem_convert(i16 noundef %x) { 426; CHECK-LABEL: @srem_convert( 427; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i16 0, [[X:%.*]] 428; CHECK-NEXT: [[SREM1:%.*]] = urem i16 [[X_NONNEG]], 42 429; CHECK-NEXT: [[SREM1_NEG:%.*]] = sub i16 0, [[SREM1]] 430; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[X]], 0 431; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SREM1_NEG]], i16 24 432; CHECK-NEXT: ret i16 [[SEL]] 433; 434 %srem = srem i16 %x, 42 435 %cmp = icmp slt i16 %x, 0 436 %sel = select i1 %cmp, i16 %srem, i16 24 437 ret i16 %sel 438} 439 440define i16 @sdiv_convert(i16 noundef %x) { 441; CHECK-LABEL: @sdiv_convert( 442; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i16 0, [[X:%.*]] 443; CHECK-NEXT: [[SREM1:%.*]] = udiv i16 [[X_NONNEG]], 42 444; CHECK-NEXT: [[SREM1_NEG:%.*]] = sub i16 0, [[SREM1]] 445; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[X]], 0 446; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[SREM1_NEG]], i16 24 447; CHECK-NEXT: ret i16 [[SEL]] 448; 449 %srem = sdiv i16 %x, 42 450 %cmp = icmp slt i16 %x, 0 451 %sel = select i1 %cmp, i16 %srem, i16 24 452 ret i16 %sel 453} 454 455define i16 @abs_elide(i16 %x) { 456; CHECK-LABEL: @abs_elide( 457; CHECK-NEXT: [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false) 458; CHECK-NEXT: [[CMP:%.*]] = icmp ule i16 [[X]], -32768 459; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42 460; CHECK-NEXT: ret i16 [[SEL]] 461; 462 %abs = call i16 @llvm.abs.i16(i16 %x, i1 false) 463 %cmp = icmp ule i16 %x, 32768 464 %sel = select i1 %cmp, i16 %abs, i16 42 465 ret i16 %sel 466} 467 468define i16 @abs_elide2(i16 %x) { 469; CHECK-LABEL: @abs_elide2( 470; CHECK-NEXT: [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false) 471; CHECK-NEXT: [[CMP:%.*]] = icmp sle i16 [[X]], 0 472; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42 473; CHECK-NEXT: ret i16 [[SEL]] 474; 475 %abs = call i16 @llvm.abs.i16(i16 %x, i1 false) 476 %cmp = icmp sle i16 %x, 0 477 %sel = select i1 %cmp, i16 %abs, i16 42 478 ret i16 %sel 479} 480 481define i16 @abs_not_int_min(i16 %x) { 482; CHECK-LABEL: @abs_not_int_min( 483; CHECK-NEXT: [[ABS:%.*]] = call i16 @llvm.abs.i16(i16 [[X:%.*]], i1 false) 484; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[X]], -32768 485; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ABS]], i16 42 486; CHECK-NEXT: ret i16 [[SEL]] 487; 488 %abs = call i16 @llvm.abs.i16(i16 %x, i1 false) 489 %cmp = icmp ne i16 %x, 32768 490 %sel = select i1 %cmp, i16 %abs, i16 42 491 ret i16 %sel 492} 493 494define i16 @umin_elide(i16 %x) { 495; CHECK-LABEL: @umin_elide( 496; CHECK-NEXT: [[MIN:%.*]] = call i16 @llvm.umin.i16(i16 [[X:%.*]], i16 10) 497; CHECK-NEXT: [[CMP:%.*]] = icmp ule i16 [[X]], 10 498; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[MIN]], i16 42 499; CHECK-NEXT: ret i16 [[SEL]] 500; 501 %min = call i16 @llvm.umin.i16(i16 %x, i16 10) 502 %cmp = icmp ule i16 %x, 10 503 %sel = select i1 %cmp, i16 %min, i16 42 504 ret i16 %sel 505} 506 507define i16 @ashr_convert(i16 noundef %x, i16 %y) { 508; CHECK-LABEL: @ashr_convert( 509; CHECK-NEXT: [[ASHR:%.*]] = lshr i16 [[X:%.*]], [[Y:%.*]] 510; CHECK-NEXT: [[CMP:%.*]] = icmp sge i16 [[X]], 0 511; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ASHR]], i16 24 512; CHECK-NEXT: ret i16 [[SEL]] 513; 514 %ashr = ashr i16 %x, %y 515 %cmp = icmp sge i16 %x, 0 516 %sel = select i1 %cmp, i16 %ashr, i16 24 517 ret i16 %sel 518} 519 520define i32 @sext_convert(i16 noundef %x) { 521; CHECK-LABEL: @sext_convert( 522; CHECK-NEXT: [[EXT:%.*]] = zext nneg i16 [[X:%.*]] to i32 523; CHECK-NEXT: [[CMP:%.*]] = icmp sge i16 [[X]], 0 524; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[EXT]], i32 24 525; CHECK-NEXT: ret i32 [[SEL]] 526; 527 %ext = sext i16 %x to i32 528 %cmp = icmp sge i16 %x, 0 529 %sel = select i1 %cmp, i32 %ext, i32 24 530 ret i32 %sel 531} 532 533define i16 @infer_flags(i16 %x) { 534; CHECK-LABEL: @infer_flags( 535; CHECK-NEXT: [[ADD:%.*]] = add i16 [[X:%.*]], 42 536; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 100 537; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[ADD]], i16 24 538; CHECK-NEXT: ret i16 [[SEL]] 539; 540 %add = add i16 %x, 42 541 %cmp = icmp ult i16 %x, 100 542 %sel = select i1 %cmp, i16 %add, i16 24 543 ret i16 %sel 544} 545 546define i16 @and_elide(i16 noundef %x) { 547; CHECK-LABEL: @and_elide( 548; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X:%.*]], 8 549; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[X]], i16 24 550; CHECK-NEXT: ret i16 [[SEL]] 551; 552 %and = and i16 %x, 7 553 %cmp = icmp ult i16 %x, 8 554 %sel = select i1 %cmp, i16 %and, i16 24 555 ret i16 %sel 556} 557 558define i16 @cond_value_may_not_well_defined(i16 %x) { 559; CHECK-LABEL: @cond_value_may_not_well_defined( 560; CHECK-NEXT: [[AND:%.*]] = and i16 [[X:%.*]], 7 561; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 8 562; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[AND]], i16 24 563; CHECK-NEXT: ret i16 [[SEL]] 564; 565 %and = and i16 %x, 7 566 %cmp = icmp ult i16 %x, 8 567 %sel = select i1 %cmp, i16 %and, i16 24 568 ret i16 %sel 569} 570 571define i16 @and_elide_poison_flags(i16 noundef %a) { 572; CHECK-LABEL: @and_elide_poison_flags( 573; CHECK-NEXT: [[X:%.*]] = add nuw i16 [[A:%.*]], 1 574; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 8 575; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[X]], i16 24 576; CHECK-NEXT: ret i16 [[SEL]] 577; 578 %x = add nuw i16 %a, 1 579 %and = and i16 %x, 7 580 %cmp = icmp ult i16 %x, 8 581 %sel = select i1 %cmp, i16 %and, i16 24 582 ret i16 %sel 583} 584 585define i16 @and_elide_poison_flags_missing_noundef(i16 %a) { 586; CHECK-LABEL: @and_elide_poison_flags_missing_noundef( 587; CHECK-NEXT: [[X:%.*]] = add nuw i16 [[A:%.*]], 1 588; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], 7 589; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X]], 8 590; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 [[AND]], i16 24 591; CHECK-NEXT: ret i16 [[SEL]] 592; 593 %x = add nuw i16 %a, 1 594 %and = and i16 %x, 7 595 %cmp = icmp ult i16 %x, 8 596 %sel = select i1 %cmp, i16 %and, i16 24 597 ret i16 %sel 598} 599 600define i32 @pr87854(i32 noundef %x.1, i32 noundef %i) { 601; CHECK-LABEL: @pr87854( 602; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[X_1:%.*]], -1 603; CHECK-NEXT: tail call void @llvm.assume(i1 [[COND]]) 604; CHECK-NEXT: [[INBOUNDS:%.*]] = icmp ult i32 [[I:%.*]], [[X_1]] 605; CHECK-NEXT: [[NEXT:%.*]] = add nuw i32 [[I]], 1 606; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[INBOUNDS]], i32 [[NEXT]], i32 -1 607; CHECK-NEXT: ret i32 [[SPEC_SELECT]] 608; 609 %cond = icmp sgt i32 %x.1, -1 610 tail call void @llvm.assume(i1 %cond) 611 %inbounds = icmp ult i32 %i, %x.1 612 %next = add i32 %i, 1 613 %spec.select = select i1 %inbounds, i32 %next, i32 -1 614 ret i32 %spec.select 615} 616 617define i64 @test_shl_nsw_at_use(i64 noundef %x) { 618; CHECK-LABEL: @test_shl_nsw_at_use( 619; CHECK-NEXT: [[ADD:%.*]] = add i64 [[X:%.*]], 2147483648 620; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[ADD]], 4294967296 621; CHECK-NEXT: [[SHL:%.*]] = shl nsw i64 [[X]], 32 622; CHECK-NEXT: [[SHR:%.*]] = ashr exact i64 [[SHL]], 32 623; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i64 [[SHR]], i64 0 624; CHECK-NEXT: ret i64 [[RES]] 625; 626 %add = add i64 %x, 2147483648 627 %cmp = icmp ult i64 %add, 4294967296 628 %shl = shl i64 %x, 32 629 %shr = ashr exact i64 %shl, 32 630 %res = select i1 %cmp, i64 %shr, i64 0 631 ret i64 %res 632} 633 634define i1 @test_icmp_mod(i64 noundef %x) { 635; CHECK-LABEL: @test_icmp_mod( 636; CHECK-NEXT: entry: 637; CHECK-NEXT: [[REM:%.*]] = srem i64 [[X:%.*]], 86400 638; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[REM]], 0 639; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i64 86400, i64 0 640; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]] 641; CHECK-NEXT: ret i1 false 642; 643entry: 644 %rem = srem i64 %x, 86400 645 %cmp = icmp slt i64 %rem, 0 646 %cond = select i1 %cmp, i64 86400, i64 0 647 %add = add nsw i64 %cond, %rem 648 %cmp1 = icmp ugt i64 %add, 86399 649 ret i1 %cmp1 650} 651 652define i1 @test_icmp_mod_commuted1(i64 noundef %x) { 653; CHECK-LABEL: @test_icmp_mod_commuted1( 654; CHECK-NEXT: entry: 655; CHECK-NEXT: [[REM:%.*]] = srem i64 [[X:%.*]], 86400 656; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[REM]], 0 657; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i64 86400, i64 0 658; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[REM]], [[COND]] 659; CHECK-NEXT: ret i1 false 660; 661entry: 662 %rem = srem i64 %x, 86400 663 %cmp = icmp slt i64 %rem, 0 664 %cond = select i1 %cmp, i64 86400, i64 0 665 %add = add nsw i64 %rem, %cond 666 %cmp1 = icmp ugt i64 %add, 86399 667 ret i1 %cmp1 668} 669 670define i1 @test_icmp_mod_commuted2(i64 noundef %x) { 671; CHECK-LABEL: @test_icmp_mod_commuted2( 672; CHECK-NEXT: entry: 673; CHECK-NEXT: [[REM:%.*]] = srem i64 [[X:%.*]], 86400 674; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[REM]], -1 675; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i64 0, i64 86400 676; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]] 677; CHECK-NEXT: ret i1 false 678; 679entry: 680 %rem = srem i64 %x, 86400 681 %cmp = icmp sgt i64 %rem, -1 682 %cond = select i1 %cmp, i64 0, i64 86400 683 %add = add nsw i64 %cond, %rem 684 %cmp1 = icmp ugt i64 %add, 86399 685 ret i1 %cmp1 686} 687 688define i1 @test_icmp_mod_undef(i64 %x) { 689; CHECK-LABEL: @test_icmp_mod_undef( 690; CHECK-NEXT: entry: 691; CHECK-NEXT: [[REM:%.*]] = srem i64 [[X:%.*]], 86400 692; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[REM]], 0 693; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i64 86400, i64 0 694; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]] 695; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[ADD]], 86399 696; CHECK-NEXT: ret i1 [[CMP1]] 697; 698entry: 699 %rem = srem i64 %x, 86400 700 %cmp = icmp slt i64 %rem, 0 701 %cond = select i1 %cmp, i64 86400, i64 0 702 %add = add nsw i64 %cond, %rem 703 %cmp1 = icmp ugt i64 %add, 86399 704 ret i1 %cmp1 705} 706 707define i1 @test_icmp_mod_wrong_range(i64 noundef %x) { 708; CHECK-LABEL: @test_icmp_mod_wrong_range( 709; CHECK-NEXT: entry: 710; CHECK-NEXT: [[REM:%.*]] = srem i64 [[X:%.*]], 86400 711; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[REM]], 0 712; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i64 86401, i64 0 713; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]] 714; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ugt i64 [[ADD]], 86399 715; CHECK-NEXT: ret i1 [[CMP1]] 716; 717entry: 718 %rem = srem i64 %x, 86400 719 %cmp = icmp slt i64 %rem, 0 720 %cond = select i1 %cmp, i64 86401, i64 0 721 %add = add nsw i64 %cond, %rem 722 %cmp1 = icmp ugt i64 %add, 86399 723 ret i1 %cmp1 724} 725