1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4; Test from PR63896 5define i1 @umax_ugt(i32 %x, i32 %y) { 6; CHECK-LABEL: define i1 @umax_ugt 7; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 8; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 1) 9; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[Y]], [[MAX]] 10; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 11; CHECK: if: 12; CHECK-NEXT: [[RET:%.*]] = xor i1 true, true 13; CHECK-NEXT: ret i1 [[RET]] 14; CHECK: end: 15; CHECK-NEXT: ret i1 false 16; 17 %max = call i32 @llvm.umax.i32(i32 %x, i32 1) 18 %cmp = icmp ugt i32 %y, %max 19 br i1 %cmp, label %if, label %end 20 21if: 22 %cmp2 = icmp ugt i32 %y, %x 23 %cmp3 = icmp uge i32 %y, %x 24 %ret = xor i1 %cmp2, %cmp3 25 ret i1 %ret 26 27end: 28 ret i1 false 29} 30 31define i1 @umax_uge(i32 %x, i32 %y) { 32; CHECK-LABEL: define i1 @umax_uge 33; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 34; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 1) 35; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[Y]], [[MAX]] 36; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 37; CHECK: if: 38; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[Y]], [[X]] 39; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], true 40; CHECK-NEXT: ret i1 [[RET]] 41; CHECK: end: 42; CHECK-NEXT: ret i1 false 43; 44 %max = call i32 @llvm.umax.i32(i32 %x, i32 1) 45 %cmp = icmp uge i32 %y, %max 46 br i1 %cmp, label %if, label %end 47 48if: 49 %cmp2 = icmp ugt i32 %y, %x 50 %cmp3 = icmp uge i32 %y, %x 51 %ret = xor i1 %cmp2, %cmp3 52 ret i1 %ret 53 54end: 55 ret i1 false 56} 57 58define i1 @umin_ult(i32 %x, i32 %y) { 59; CHECK-LABEL: define i1 @umin_ult 60; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 61; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 1) 62; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[Y]], [[MIN]] 63; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 64; CHECK: if: 65; CHECK-NEXT: [[RET:%.*]] = xor i1 true, true 66; CHECK-NEXT: ret i1 [[RET]] 67; CHECK: end: 68; CHECK-NEXT: ret i1 false 69; 70 %min = call i32 @llvm.umin.i32(i32 %x, i32 1) 71 %cmp = icmp ult i32 %y, %min 72 br i1 %cmp, label %if, label %end 73 74if: 75 %cmp2 = icmp ult i32 %y, %x 76 %cmp3 = icmp ule i32 %y, %x 77 %ret = xor i1 %cmp2, %cmp3 78 ret i1 %ret 79 80end: 81 ret i1 false 82} 83 84define i1 @umin_ule(i32 %x, i32 %y) { 85; CHECK-LABEL: define i1 @umin_ule 86; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 87; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 1) 88; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[Y]], [[MIN]] 89; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 90; CHECK: if: 91; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y]], [[X]] 92; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], true 93; CHECK-NEXT: ret i1 [[RET]] 94; CHECK: end: 95; CHECK-NEXT: ret i1 false 96; 97 %min = call i32 @llvm.umin.i32(i32 %x, i32 1) 98 %cmp = icmp ule i32 %y, %min 99 br i1 %cmp, label %if, label %end 100 101if: 102 %cmp2 = icmp ult i32 %y, %x 103 %cmp3 = icmp ule i32 %y, %x 104 %ret = xor i1 %cmp2, %cmp3 105 ret i1 %ret 106 107end: 108 ret i1 false 109} 110 111define i1 @smax_sgt(i32 %x, i32 %y) { 112; CHECK-LABEL: define i1 @smax_sgt 113; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 114; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 1) 115; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[Y]], [[MAX]] 116; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 117; CHECK: if: 118; CHECK-NEXT: [[RET:%.*]] = xor i1 true, true 119; CHECK-NEXT: ret i1 [[RET]] 120; CHECK: end: 121; CHECK-NEXT: ret i1 false 122; 123 %max = call i32 @llvm.smax.i32(i32 %x, i32 1) 124 %cmp = icmp sgt i32 %y, %max 125 br i1 %cmp, label %if, label %end 126 127if: 128 %cmp2 = icmp sgt i32 %y, %x 129 %cmp3 = icmp sge i32 %y, %x 130 %ret = xor i1 %cmp2, %cmp3 131 ret i1 %ret 132 133end: 134 ret i1 false 135} 136 137define i1 @smax_sge(i32 %x, i32 %y) { 138; CHECK-LABEL: define i1 @smax_sge 139; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 140; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 1) 141; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[Y]], [[MAX]] 142; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 143; CHECK: if: 144; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[Y]], [[X]] 145; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], true 146; CHECK-NEXT: ret i1 [[RET]] 147; CHECK: end: 148; CHECK-NEXT: ret i1 false 149; 150 %max = call i32 @llvm.smax.i32(i32 %x, i32 1) 151 %cmp = icmp sge i32 %y, %max 152 br i1 %cmp, label %if, label %end 153 154if: 155 %cmp2 = icmp sgt i32 %y, %x 156 %cmp3 = icmp sge i32 %y, %x 157 %ret = xor i1 %cmp2, %cmp3 158 ret i1 %ret 159 160end: 161 ret i1 false 162} 163 164define i1 @smin_slt(i32 %x, i32 %y) { 165; CHECK-LABEL: define i1 @smin_slt 166; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 167; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 1) 168; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[Y]], [[MIN]] 169; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 170; CHECK: if: 171; CHECK-NEXT: [[RET:%.*]] = xor i1 true, true 172; CHECK-NEXT: ret i1 [[RET]] 173; CHECK: end: 174; CHECK-NEXT: ret i1 false 175; 176 %min = call i32 @llvm.smin.i32(i32 %x, i32 1) 177 %cmp = icmp slt i32 %y, %min 178 br i1 %cmp, label %if, label %end 179 180if: 181 %cmp2 = icmp slt i32 %y, %x 182 %cmp3 = icmp sle i32 %y, %x 183 %ret = xor i1 %cmp2, %cmp3 184 ret i1 %ret 185 186end: 187 ret i1 false 188} 189 190define i1 @smin_sle(i32 %x, i32 %y) { 191; CHECK-LABEL: define i1 @smin_sle 192; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 193; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 1) 194; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[Y]], [[MIN]] 195; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 196; CHECK: if: 197; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y]], [[X]] 198; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], true 199; CHECK-NEXT: ret i1 [[RET]] 200; CHECK: end: 201; CHECK-NEXT: ret i1 false 202; 203 %min = call i32 @llvm.smin.i32(i32 %x, i32 1) 204 %cmp = icmp sle i32 %y, %min 205 br i1 %cmp, label %if, label %end 206 207if: 208 %cmp2 = icmp slt i32 %y, %x 209 %cmp3 = icmp sle i32 %y, %x 210 %ret = xor i1 %cmp2, %cmp3 211 ret i1 %ret 212 213end: 214 ret i1 false 215} 216 217define i1 @umax_uge_ugt_with_add_nuw(i32 %x, i32 %y) { 218; CHECK-LABEL: define i1 @umax_uge_ugt_with_add_nuw 219; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 220; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 1) 221; CHECK-NEXT: [[SUM:%.*]] = add nuw i32 [[MAX]], 1 222; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[Y]], [[SUM]] 223; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 224; CHECK: if: 225; CHECK-NEXT: ret i1 true 226; CHECK: end: 227; CHECK-NEXT: ret i1 false 228; 229 %max = call i32 @llvm.umax.i32(i32 %x, i32 1) 230 %sum = add nuw i32 %max, 1 231 %cmp = icmp uge i32 %y, %sum 232 br i1 %cmp, label %if, label %end 233 234if: 235 %cmp2 = icmp ugt i32 %y, %x 236 ret i1 %cmp2 237 238end: 239 ret i1 false 240} 241 242define i1 @smin_ule_mixed(i32 %x, i32 %y) { 243; CHECK-LABEL: define i1 @smin_ule_mixed 244; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 245; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 1) 246; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[Y]], [[MIN]] 247; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 248; CHECK: if: 249; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y]], [[X]] 250; CHECK-NEXT: [[CMP3:%.*]] = icmp sle i32 [[Y]], [[X]] 251; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[Y]], [[X]] 252; CHECK-NEXT: [[CMP5:%.*]] = icmp ule i32 [[Y]], [[X]] 253; CHECK-NEXT: [[XOR1:%.*]] = xor i1 [[CMP2]], [[CMP3]] 254; CHECK-NEXT: [[XOR2:%.*]] = xor i1 [[CMP4]], [[CMP5]] 255; CHECK-NEXT: [[RET:%.*]] = xor i1 [[XOR1]], [[XOR2]] 256; CHECK-NEXT: ret i1 [[RET]] 257; CHECK: end: 258; CHECK-NEXT: ret i1 false 259; 260 %min = call i32 @llvm.smin.i32(i32 %x, i32 1) 261 %cmp = icmp ule i32 %y, %min 262 br i1 %cmp, label %if, label %end 263 264if: 265 %cmp2 = icmp slt i32 %y, %x 266 %cmp3 = icmp sle i32 %y, %x 267 %cmp4 = icmp ult i32 %y, %x 268 %cmp5 = icmp ule i32 %y, %x 269 %xor1 = xor i1 %cmp2, %cmp3 270 %xor2 = xor i1 %cmp4, %cmp5 271 %ret = xor i1 %xor1, %xor2 272 ret i1 %ret 273 274end: 275 ret i1 false 276} 277 278define i1 @umax_ugt_ugt_both(i32 %x, i32 %y, i32 %z) { 279; CHECK-LABEL: define i1 @umax_ugt_ugt_both 280; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) { 281; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]]) 282; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[Z]], [[MAX]] 283; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 284; CHECK: if: 285; CHECK-NEXT: [[AND:%.*]] = xor i1 true, true 286; CHECK-NEXT: ret i1 [[AND]] 287; CHECK: end: 288; CHECK-NEXT: ret i1 false 289; 290 %max = call i32 @llvm.umax.i32(i32 %x, i32 %y) 291 %cmp = icmp ugt i32 %z, %max 292 br i1 %cmp, label %if, label %end 293 294if: 295 %cmp2 = icmp ugt i32 %z, %x 296 %cmp3 = icmp ugt i32 %z, %y 297 %and = xor i1 %cmp2, %cmp3 298 ret i1 %and 299 300end: 301 ret i1 false 302} 303 304define i1 @smin_branchless(i32 %x, i32 %y) { 305; CHECK-LABEL: define i1 @smin_branchless 306; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 307; CHECK-NEXT: entry: 308; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y]]) 309; CHECK-NEXT: [[CMP1:%.*]] = icmp sle i32 [[MIN]], [[X]] 310; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[MIN]], [[X]] 311; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP1]], [[CMP2]] 312; CHECK-NEXT: ret i1 [[RET]] 313; 314entry: 315 %min = call i32 @llvm.smin.i32(i32 %x, i32 %y) 316 %cmp1 = icmp sle i32 %min, %x 317 %cmp2 = icmp sgt i32 %min, %x 318 %ret = xor i1 %cmp1, %cmp2 319 ret i1 %ret 320} 321 322define i32 @simplify_smax(i32 %x, i32 %y, i32 %z) { 323; CHECK-LABEL: define i32 @simplify_smax 324; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) { 325; CHECK-NEXT: entry: 326; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], [[Y]] 327; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] 328; CHECK: if: 329; CHECK-NEXT: [[MAX1:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Z]]) 330; CHECK-NEXT: [[MAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[Y]], i32 [[MAX1]]) 331; CHECK-NEXT: ret i32 [[MAX2]] 332; CHECK: end: 333; CHECK-NEXT: ret i32 0 334; 335entry: 336 %cmp = icmp slt i32 %x, %y 337 br i1 %cmp, label %if, label %end 338if: 339 %max1 = call i32 @llvm.smax.i32(i32 %x, i32 %z) 340 %max2 = call i32 @llvm.smax.i32(i32 %y, i32 %max1) 341 ret i32 %max2 342end: 343 ret i32 0 344} 345 346; Test from PR75155 347define i32 @simplify_slt_smax_val(i32 %a, i32 %b) { 348; CHECK-LABEL: define i32 @simplify_slt_smax_val 349; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 350; CHECK-NEXT: start: 351; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 352; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 353; CHECK: then: 354; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 355; CHECK-NEXT: ret i32 [[B]] 356; CHECK: else: 357; CHECK-NEXT: ret i32 -1 358; 359start: 360 %cmp = icmp slt i32 %a, %b 361 br i1 %cmp, label %then, label %else 362then: 363 %add = add nsw i32 %a, 1 364 %max = call i32 @llvm.smax.i32(i32 %b, i32 %add) 365 ret i32 %max 366else: 367 ret i32 -1 368} 369 370define i32 @simplify_slt_smax_val_commuted(i32 %a, i32 %b) { 371; CHECK-LABEL: define i32 @simplify_slt_smax_val_commuted 372; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 373; CHECK-NEXT: start: 374; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 375; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 376; CHECK: then: 377; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 378; CHECK-NEXT: ret i32 [[B]] 379; CHECK: else: 380; CHECK-NEXT: ret i32 -1 381; 382start: 383 %cmp = icmp slt i32 %a, %b 384 br i1 %cmp, label %then, label %else 385then: 386 %add = add nsw i32 %a, 1 387 %max = call i32 @llvm.smax.i32(i32 %add, i32 %b) 388 ret i32 %max 389else: 390 ret i32 -1 391} 392 393define i32 @simplify_slt_smax_val_at_use(i32 %a, i32 %b) { 394; CHECK-LABEL: define i32 @simplify_slt_smax_val_at_use 395; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 396; CHECK-NEXT: start: 397; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 398; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 399; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[ADD]]) 400; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 401; CHECK: then: 402; CHECK-NEXT: ret i32 [[MAX]] 403; CHECK: else: 404; CHECK-NEXT: ret i32 -1 405; 406start: 407 %cmp = icmp slt i32 %a, %b 408 %add = add nsw i32 %a, 1 409 %max = call i32 @llvm.smax.i32(i32 %b, i32 %add) 410 br i1 %cmp, label %then, label %else 411then: 412 ret i32 %max 413else: 414 ret i32 -1 415} 416 417define i32 @simplify_sgt_smax_val(i32 %a, i32 %b) { 418; CHECK-LABEL: define i32 @simplify_sgt_smax_val 419; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 420; CHECK-NEXT: start: 421; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] 422; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 423; CHECK: then: 424; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 425; CHECK-NEXT: ret i32 [[ADD]] 426; CHECK: else: 427; CHECK-NEXT: ret i32 -1 428; 429start: 430 %cmp = icmp sgt i32 %a, %b 431 br i1 %cmp, label %then, label %else 432then: 433 %add = add nsw i32 %a, 1 434 %max = call i32 @llvm.smax.i32(i32 %b, i32 %add) 435 ret i32 %max 436else: 437 ret i32 -1 438} 439 440define i32 @simplify_sle_smax_val(i32 %a, i32 %b) { 441; CHECK-LABEL: define i32 @simplify_sle_smax_val 442; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 443; CHECK-NEXT: start: 444; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], [[B]] 445; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 446; CHECK: then: 447; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 448; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[ADD]]) 449; CHECK-NEXT: ret i32 [[MAX]] 450; CHECK: else: 451; CHECK-NEXT: ret i32 -1 452; 453start: 454 %cmp = icmp sle i32 %a, %b 455 br i1 %cmp, label %then, label %else 456then: 457 %add = add nsw i32 %a, 1 458 %max = call i32 @llvm.smax.i32(i32 %b, i32 %add) 459 ret i32 %max 460else: 461 ret i32 -1 462} 463 464define i32 @simplify_sge_smax_val(i32 %a, i32 %b) { 465; CHECK-LABEL: define i32 @simplify_sge_smax_val 466; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 467; CHECK-NEXT: start: 468; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A]], [[B]] 469; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 470; CHECK: then: 471; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 472; CHECK-NEXT: ret i32 [[ADD]] 473; CHECK: else: 474; CHECK-NEXT: ret i32 -1 475; 476start: 477 %cmp = icmp sge i32 %a, %b 478 br i1 %cmp, label %then, label %else 479then: 480 %add = add nsw i32 %a, 1 481 %max = call i32 @llvm.smax.i32(i32 %b, i32 %add) 482 ret i32 %max 483else: 484 ret i32 -1 485} 486 487define i32 @simplify_ult_umax_val(i32 %a, i32 %b) { 488; CHECK-LABEL: define i32 @simplify_ult_umax_val 489; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 490; CHECK-NEXT: start: 491; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], [[B]] 492; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 493; CHECK: then: 494; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1 495; CHECK-NEXT: ret i32 [[B]] 496; CHECK: else: 497; CHECK-NEXT: ret i32 -1 498; 499start: 500 %cmp = icmp ult i32 %a, %b 501 br i1 %cmp, label %then, label %else 502then: 503 %add = add nuw i32 %a, 1 504 %max = call i32 @llvm.umax.i32(i32 %b, i32 %add) 505 ret i32 %max 506else: 507 ret i32 -1 508} 509 510define i32 @simplify_slt_smin_val(i32 %a, i32 %b) { 511; CHECK-LABEL: define i32 @simplify_slt_smin_val 512; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 513; CHECK-NEXT: start: 514; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 515; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 516; CHECK: then: 517; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 518; CHECK-NEXT: ret i32 [[ADD]] 519; CHECK: else: 520; CHECK-NEXT: ret i32 -1 521; 522start: 523 %cmp = icmp slt i32 %a, %b 524 br i1 %cmp, label %then, label %else 525then: 526 %add = add nsw i32 %a, 1 527 %max = call i32 @llvm.smin.i32(i32 %b, i32 %add) 528 ret i32 %max 529else: 530 ret i32 -1 531} 532 533define i32 @simplify_ult_umin_val(i32 %a, i32 %b) { 534; CHECK-LABEL: define i32 @simplify_ult_umin_val 535; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 536; CHECK-NEXT: start: 537; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], [[B]] 538; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 539; CHECK: then: 540; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1 541; CHECK-NEXT: ret i32 [[ADD]] 542; CHECK: else: 543; CHECK-NEXT: ret i32 -1 544; 545start: 546 %cmp = icmp ult i32 %a, %b 547 br i1 %cmp, label %then, label %else 548then: 549 %add = add nuw i32 %a, 1 550 %max = call i32 @llvm.umin.i32(i32 %b, i32 %add) 551 ret i32 %max 552else: 553 ret i32 -1 554} 555 556define i32 @simplify_slt_smax_val_fail1(i32 %a, i32 %b) { 557; CHECK-LABEL: define i32 @simplify_slt_smax_val_fail1 558; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 559; CHECK-NEXT: start: 560; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 561; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 562; CHECK: then: 563; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 2 564; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[ADD]]) 565; CHECK-NEXT: ret i32 [[MAX]] 566; CHECK: else: 567; CHECK-NEXT: ret i32 -1 568; 569start: 570 %cmp = icmp slt i32 %a, %b 571 br i1 %cmp, label %then, label %else 572then: 573 %add = add nsw i32 %a, 2 574 %max = call i32 @llvm.smax.i32(i32 %b, i32 %add) 575 ret i32 %max 576else: 577 ret i32 -1 578} 579 580define i32 @simplify_ult_smax_val_fail2(i32 %a, i32 %b) { 581; CHECK-LABEL: define i32 @simplify_ult_smax_val_fail2 582; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 583; CHECK-NEXT: start: 584; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], [[B]] 585; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 586; CHECK: then: 587; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 588; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[ADD]]) 589; CHECK-NEXT: ret i32 [[MAX]] 590; CHECK: else: 591; CHECK-NEXT: ret i32 -1 592; 593start: 594 %cmp = icmp ult i32 %a, %b 595 br i1 %cmp, label %then, label %else 596then: 597 %add = add nsw i32 %a, 1 598 %max = call i32 @llvm.smax.i32(i32 %b, i32 %add) 599 ret i32 %max 600else: 601 ret i32 -1 602} 603 604define i64 @pr82271(i32 %a, i32 %b){ 605; CHECK-LABEL: define i64 @pr82271 606; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 607; CHECK-NEXT: entry: 608; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 609; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 610; CHECK: then: 611; CHECK-NEXT: [[SA:%.*]] = sext i32 [[A]] to i64 612; CHECK-NEXT: [[SB:%.*]] = sext i32 [[B]] to i64 613; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[SA]], 1 614; CHECK-NEXT: ret i64 [[SB]] 615; CHECK: else: 616; CHECK-NEXT: ret i64 0 617; 618entry: 619 %cmp = icmp slt i32 %a, %b 620 br i1 %cmp, label %then, label %else 621 622then: 623 %sa = sext i32 %a to i64 624 %sb = sext i32 %b to i64 625 %add = add nsw i64 %sa, 1 626 %smax = call i64 @llvm.smax.i64(i64 %sb, i64 %add) 627 ret i64 %smax 628 629else: 630 ret i64 0 631} 632 633define i64 @pr82271_sext_zext_nneg(i32 %a, i32 %b){ 634; CHECK-LABEL: define i64 @pr82271_sext_zext_nneg 635; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 636; CHECK-NEXT: entry: 637; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 638; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 639; CHECK: then: 640; CHECK-NEXT: [[SA:%.*]] = sext i32 [[A]] to i64 641; CHECK-NEXT: [[SB:%.*]] = zext nneg i32 [[B]] to i64 642; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[SA]], 1 643; CHECK-NEXT: ret i64 [[SB]] 644; CHECK: else: 645; CHECK-NEXT: ret i64 0 646; 647entry: 648 %cmp = icmp slt i32 %a, %b 649 br i1 %cmp, label %then, label %else 650 651then: 652 %sa = sext i32 %a to i64 653 %sb = zext nneg i32 %b to i64 654 %add = add nsw i64 %sa, 1 655 %smax = call i64 @llvm.smax.i64(i64 %sb, i64 %add) 656 ret i64 %smax 657 658else: 659 ret i64 0 660} 661 662define i64 @pr82271_zext_nneg(i32 %a, i32 %b){ 663; CHECK-LABEL: define i64 @pr82271_zext_nneg 664; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 665; CHECK-NEXT: entry: 666; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 667; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 668; CHECK: then: 669; CHECK-NEXT: [[SA:%.*]] = zext nneg i32 [[A]] to i64 670; CHECK-NEXT: [[SB:%.*]] = zext nneg i32 [[B]] to i64 671; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[SA]], 1 672; CHECK-NEXT: ret i64 [[SB]] 673; CHECK: else: 674; CHECK-NEXT: ret i64 0 675; 676entry: 677 %cmp = icmp slt i32 %a, %b 678 br i1 %cmp, label %then, label %else 679 680then: 681 %sa = zext nneg i32 %a to i64 682 %sb = zext nneg i32 %b to i64 683 %add = add nsw i64 %sa, 1 684 %smax = call i64 @llvm.smax.i64(i64 %sb, i64 %add) 685 ret i64 %smax 686 687else: 688 ret i64 0 689} 690 691define i64 @pr82271_zext(i32 %a, i32 %b){ 692; CHECK-LABEL: define i64 @pr82271_zext 693; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 694; CHECK-NEXT: entry: 695; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] 696; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] 697; CHECK: then: 698; CHECK-NEXT: [[SA:%.*]] = zext i32 [[A]] to i64 699; CHECK-NEXT: [[SB:%.*]] = zext i32 [[B]] to i64 700; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[SA]], 1 701; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[SB]], i64 [[ADD]]) 702; CHECK-NEXT: ret i64 [[SMAX]] 703; CHECK: else: 704; CHECK-NEXT: ret i64 0 705; 706entry: 707 %cmp = icmp slt i32 %a, %b 708 br i1 %cmp, label %then, label %else 709 710then: 711 %sa = zext i32 %a to i64 712 %sb = zext i32 %b to i64 713 %add = add nsw i64 %sa, 1 714 %smax = call i64 @llvm.smax.i64(i64 %sb, i64 %add) 715 ret i64 %smax 716 717else: 718 ret i64 0 719} 720 721declare i32 @llvm.smin.i32(i32, i32) 722declare i32 @llvm.smax.i32(i32, i32) 723declare i32 @llvm.umin.i32(i32, i32) 724declare i32 @llvm.umax.i32(i32, i32) 725