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