1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4declare void @llvm.assume(i1) 5 6declare void @may_unwind() 7 8declare void @use(i1) 9 10define i1 @assume_dominates(i8 %a, i8 %b, i1 %c) { 11; CHECK-LABEL: @assume_dominates( 12; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 13; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 14; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 15; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 16; CHECK: then: 17; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 18; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 19; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 20; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 21; CHECK-NEXT: ret i1 [[RES_2]] 22; CHECK: else: 23; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true 24; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2 25; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]] 26; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]] 27; CHECK-NEXT: ret i1 [[RES_4]] 28; 29 %add.1 = add nsw nuw i8 %a, 1 30 %cmp.1 = icmp ule i8 %add.1, %b 31 call void @llvm.assume(i1 %cmp.1) 32 br i1 %c, label %then, label %else 33 34then: 35 %t.1 = icmp ule i8 %add.1, %b 36 %t.2 = icmp ule i8 %a, %b 37 %res.1 = xor i1 %t.1, %t.2 38 %add.2 = add nsw nuw i8 %a, 2 39 %c.1 = icmp ule i8 %add.2, %b 40 %res.2 = xor i1 %res.1, %c.1 41 ret i1 %res.2 42 43else: 44 %t.3 = icmp ule i8 %add.1, %b 45 %t.4 = icmp ule i8 %a, %b 46 %res.3 = xor i1 %t.3, %t.4 47 %add.2.1 = add nsw nuw i8 %a, 2 48 %c.2 = icmp ule i8 %add.2.1, %b 49 %res.4 = xor i1 %res.3, %c.2 50 ret i1 %res.4 51} 52 53define i1 @assume_dominates_with_may_unwind_call_before_assume(i8 %a, i8 %b, i1 %c) { 54; CHECK-LABEL: @assume_dominates_with_may_unwind_call_before_assume( 55; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 56; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 57; CHECK-NEXT: call void @may_unwind() 58; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 59; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 60; CHECK: then: 61; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 62; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 63; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 64; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 65; CHECK-NEXT: ret i1 [[RES_2]] 66; CHECK: else: 67; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true 68; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2 69; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]] 70; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]] 71; CHECK-NEXT: ret i1 [[RES_4]] 72; 73 %add.1 = add nsw nuw i8 %a, 1 74 %cmp.1 = icmp ule i8 %add.1, %b 75 call void @may_unwind() 76 call void @llvm.assume(i1 %cmp.1) 77 br i1 %c, label %then, label %else 78 79then: 80 %t.1 = icmp ule i8 %add.1, %b 81 %t.2 = icmp ule i8 %a, %b 82 %res.1 = xor i1 %t.1, %t.2 83 %add.2 = add nsw nuw i8 %a, 2 84 %c.1 = icmp ule i8 %add.2, %b 85 %res.2 = xor i1 %res.1, %c.1 86 ret i1 %res.2 87 88else: 89 %t.3 = icmp ule i8 %add.1, %b 90 %t.4 = icmp ule i8 %a, %b 91 %res.3 = xor i1 %t.3, %t.4 92 %add.2.1 = add nsw nuw i8 %a, 2 93 %c.2 = icmp ule i8 %add.2.1, %b 94 %res.4 = xor i1 %res.3, %c.2 95 ret i1 %res.4 96} 97 98define i1 @assume_dominates_with_may_unwind_call_after_assume(i8 %a, i8 %b, i1 %c) { 99; CHECK-LABEL: @assume_dominates_with_may_unwind_call_after_assume( 100; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 101; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 102; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 103; CHECK-NEXT: call void @may_unwind() 104; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 105; CHECK: then: 106; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 107; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 108; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 109; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 110; CHECK-NEXT: ret i1 [[RES_2]] 111; CHECK: else: 112; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true 113; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2 114; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]] 115; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]] 116; CHECK-NEXT: ret i1 [[RES_4]] 117; 118 %add.1 = add nsw nuw i8 %a, 1 119 %cmp.1 = icmp ule i8 %add.1, %b 120 call void @llvm.assume(i1 %cmp.1) 121 call void @may_unwind() 122 br i1 %c, label %then, label %else 123 124then: 125 %t.1 = icmp ule i8 %add.1, %b 126 %t.2 = icmp ule i8 %a, %b 127 %res.1 = xor i1 %t.1, %t.2 128 %add.2 = add nsw nuw i8 %a, 2 129 %c.1 = icmp ule i8 %add.2, %b 130 %res.2 = xor i1 %res.1, %c.1 131 ret i1 %res.2 132 133else: 134 %t.3 = icmp ule i8 %add.1, %b 135 %t.4 = icmp ule i8 %a, %b 136 %res.3 = xor i1 %t.3, %t.4 137 %add.2.1 = add nsw nuw i8 %a, 2 138 %c.2 = icmp ule i8 %add.2.1, %b 139 %res.4 = xor i1 %res.3, %c.2 140 ret i1 %res.4 141} 142 143; Test case from PR54217. 144define i1 @assume_does_not_dominates_successor_with_may_unwind_call_before_assume(i16 %a, i1 %i.0) { 145; CHECK-LABEL: @assume_does_not_dominates_successor_with_may_unwind_call_before_assume( 146; CHECK-NEXT: entry: 147; CHECK-NEXT: br i1 [[I_0:%.*]], label [[EXIT:%.*]], label [[IF_THEN:%.*]] 148; CHECK: if.then: 149; CHECK-NEXT: call void @may_unwind() 150; CHECK-NEXT: [[C_1:%.*]] = icmp eq i16 [[A:%.*]], 0 151; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]]) 152; CHECK-NEXT: br label [[EXIT]] 153; CHECK: exit: 154; CHECK-NEXT: [[C_2:%.*]] = icmp eq i16 [[A]], 0 155; CHECK-NEXT: ret i1 [[C_2]] 156; 157entry: 158 br i1 %i.0, label %exit, label %if.then 159 160if.then: 161 call void @may_unwind() 162 %c.1 = icmp eq i16 %a, 0 163 call void @llvm.assume(i1 %c.1) 164 br label %exit 165 166exit: 167 %c.2 = icmp eq i16 %a, 0 168 ret i1 %c.2 169} 170 171define i1 @assume_dominates_successor_with_may_unwind_call_before_assume_uncond_branch(i16 %a) { 172; CHECK-LABEL: @assume_dominates_successor_with_may_unwind_call_before_assume_uncond_branch( 173; CHECK-NEXT: entry: 174; CHECK-NEXT: call void @may_unwind() 175; CHECK-NEXT: [[C_1:%.*]] = icmp eq i16 [[A:%.*]], 0 176; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]]) 177; CHECK-NEXT: br label [[EXIT:%.*]] 178; CHECK: exit: 179; CHECK-NEXT: ret i1 true 180; 181entry: 182 call void @may_unwind() 183 %c.1 = icmp eq i16 %a, 0 184 call void @llvm.assume(i1 %c.1) 185 br label %exit 186 187exit: 188 %c.2 = icmp eq i16 %a, 0 189 ret i1 %c.2 190} 191 192define i1 @assume_dominates_successor_with_may_unwind_call_before_assume_uncond_branch_2(i16 %a, i1 %c) { 193; CHECK-LABEL: @assume_dominates_successor_with_may_unwind_call_before_assume_uncond_branch_2( 194; CHECK-NEXT: entry: 195; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 196; CHECK: then: 197; CHECK-NEXT: call void @may_unwind() 198; CHECK-NEXT: [[C_1:%.*]] = icmp eq i16 [[A:%.*]], 0 199; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]]) 200; CHECK-NEXT: br label [[EXIT]] 201; CHECK: exit: 202; CHECK-NEXT: [[C_2:%.*]] = icmp eq i16 [[A]], 0 203; CHECK-NEXT: ret i1 [[C_2]] 204; 205entry: 206 br i1 %c, label %then, label %exit 207 208then: 209 call void @may_unwind() 210 %c.1 = icmp eq i16 %a, 0 211 call void @llvm.assume(i1 %c.1) 212 br label %exit 213 214exit: 215 %c.2 = icmp eq i16 %a, 0 216 ret i1 %c.2 217} 218 219define i1 @assume_dominates_successor_with_may_unwind_call_before_assume_uncond_branch_cycle(i16 %a, i1 %c) { 220; CHECK-LABEL: @assume_dominates_successor_with_may_unwind_call_before_assume_uncond_branch_cycle( 221; CHECK-NEXT: entry: 222; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 223; CHECK: then: 224; CHECK-NEXT: call void @may_unwind() 225; CHECK-NEXT: [[C_1:%.*]] = icmp eq i16 [[A:%.*]], 0 226; CHECK-NEXT: call void @use(i1 [[C_1]]) 227; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]]) 228; CHECK-NEXT: br label [[THEN]] 229; CHECK: exit: 230; CHECK-NEXT: [[C_2:%.*]] = icmp eq i16 [[A]], 0 231; CHECK-NEXT: ret i1 [[C_2]] 232; 233entry: 234 br i1 %c, label %then, label %exit 235 236then: 237 call void @may_unwind() 238 %c.1 = icmp eq i16 %a, 0 239 call void @use(i1 %c.1) 240 call void @llvm.assume(i1 %c.1) 241 br label %then 242 243exit: 244 %c.2 = icmp eq i16 %a, 0 245 ret i1 %c.2 246} 247 248define i1 @assume_single_bb(i8 %a, i8 %b, i1 %c) { 249; CHECK-LABEL: @assume_single_bb( 250; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 251; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 252; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 253; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 254; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 255; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 256; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 257; CHECK-NEXT: ret i1 [[RES_2]] 258; 259 %add.1 = add nsw nuw i8 %a, 1 260 %cmp.1 = icmp ule i8 %add.1, %b 261 call void @llvm.assume(i1 %cmp.1) 262 %t.1 = icmp ule i8 %add.1, %b 263 %t.2 = icmp ule i8 %a, %b 264 %res.1 = xor i1 %t.1, %t.2 265 %add.2 = add nsw nuw i8 %a, 2 266 %c.1 = icmp ule i8 %add.2, %b 267 %res.2 = xor i1 %res.1, %c.1 268 ret i1 %res.2 269} 270 271define i1 @assume_same_bb(i8 %a, i8 %b, i1 %c) { 272; CHECK-LABEL: @assume_same_bb( 273; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 274; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 275; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 276; CHECK: then: 277; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 278; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 279; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 280; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 281; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 282; CHECK-NEXT: ret i1 [[RES_2]] 283; CHECK: else: 284; CHECK-NEXT: [[T_3:%.*]] = icmp ule i8 [[ADD_1]], [[B]] 285; CHECK-NEXT: [[T_4:%.*]] = icmp ule i8 [[A]], [[B]] 286; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[T_3]], [[T_4]] 287; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2 288; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]] 289; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]] 290; CHECK-NEXT: ret i1 [[RES_4]] 291; 292 %add.1 = add nsw nuw i8 %a, 1 293 %cmp.1 = icmp ule i8 %add.1, %b 294 br i1 %c, label %then, label %else 295 296then: 297 call void @llvm.assume(i1 %cmp.1) 298 %t.1 = icmp ule i8 %add.1, %b 299 %t.2 = icmp ule i8 %a, %b 300 %res.1 = xor i1 %t.1, %t.2 301 %add.2 = add nsw nuw i8 %a, 2 302 %c.1 = icmp ule i8 %add.2, %b 303 %res.2 = xor i1 %res.1, %c.1 304 ret i1 %res.2 305 306else: 307 %t.3 = icmp ule i8 %add.1, %b 308 %t.4 = icmp ule i8 %a, %b 309 %res.3 = xor i1 %t.3, %t.4 310 %add.2.1 = add nsw nuw i8 %a, 2 311 %c.2 = icmp ule i8 %add.2.1, %b 312 %res.4 = xor i1 %res.3, %c.2 313 ret i1 %res.4 314} 315 316define i1 @assume_same_bb2(i8 %a, i8 %b, i1 %c) { 317; CHECK-LABEL: @assume_same_bb2( 318; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 319; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 320; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 321; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 322; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 323; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 324; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 325; CHECK-NEXT: br label [[EXIT:%.*]] 326; CHECK: exit: 327; CHECK-NEXT: ret i1 [[RES_2]] 328; 329 %add.1 = add nsw nuw i8 %a, 1 330 %cmp.1 = icmp ule i8 %add.1, %b 331 call void @llvm.assume(i1 %cmp.1) 332 %t.1 = icmp ule i8 %add.1, %b 333 %t.2 = icmp ule i8 %a, %b 334 %res.1 = xor i1 %t.1, %t.2 335 %add.2 = add nsw nuw i8 %a, 2 336 %c.1 = icmp ule i8 %add.2, %b 337 %res.2 = xor i1 %res.1, %c.1 338 br label %exit 339 340exit: 341 ret i1 %res.2 342} 343 344 345; TODO: Keep track of position of assume and may unwinding calls, simplify 346; conditions if possible. 347define i1 @assume_same_bb_after_may_exiting_call(i8 %a, i8 %b, i1 %c) { 348; CHECK-LABEL: @assume_same_bb_after_may_exiting_call( 349; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 350; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 351; CHECK-NEXT: call void @may_unwind() 352; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 353; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 354; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 355; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 356; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 357; CHECK-NEXT: br label [[EXIT:%.*]] 358; CHECK: exit: 359; CHECK-NEXT: ret i1 [[RES_2]] 360; 361 %add.1 = add nsw nuw i8 %a, 1 362 %cmp.1 = icmp ule i8 %add.1, %b 363 call void @may_unwind() 364 call void @llvm.assume(i1 %cmp.1) 365 %t.1 = icmp ule i8 %add.1, %b 366 %t.2 = icmp ule i8 %a, %b 367 %res.1 = xor i1 %t.1, %t.2 368 %add.2 = add nsw nuw i8 %a, 2 369 %c.1 = icmp ule i8 %add.2, %b 370 %res.2 = xor i1 %res.1, %c.1 371 br label %exit 372 373exit: 374 ret i1 %res.2 375} 376 377; TODO: Keep track of position of assume and may unwinding calls, simplify 378; conditions if possible. 379define i1 @assume_same_bb_before_may_exiting_call(i8 %a, i8 %b, i1 %c) { 380; CHECK-LABEL: @assume_same_bb_before_may_exiting_call( 381; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 382; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 383; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 384; CHECK-NEXT: call void @may_unwind() 385; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 386; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 387; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 388; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 389; CHECK-NEXT: br label [[EXIT:%.*]] 390; CHECK: exit: 391; CHECK-NEXT: ret i1 [[RES_2]] 392; 393 %add.1 = add nsw nuw i8 %a, 1 394 %cmp.1 = icmp ule i8 %add.1, %b 395 call void @llvm.assume(i1 %cmp.1) 396 call void @may_unwind() 397 %t.1 = icmp ule i8 %add.1, %b 398 %t.2 = icmp ule i8 %a, %b 399 %res.1 = xor i1 %t.1, %t.2 400 %add.2 = add nsw nuw i8 %a, 2 401 %c.1 = icmp ule i8 %add.2, %b 402 %res.2 = xor i1 %res.1, %c.1 403 br label %exit 404 405exit: 406 ret i1 %res.2 407} 408 409define i1 @assume_same_bb_after_condition(i8 %a, i8 %b, i1 %c) { 410; CHECK-LABEL: @assume_same_bb_after_condition( 411; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 412; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 413; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 414; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B:%.*]] 415; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]] 416; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]] 417; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 418; CHECK-NEXT: br label [[EXIT:%.*]] 419; CHECK: exit: 420; CHECK-NEXT: ret i1 [[RES_2]] 421; 422 %add.1 = add nsw nuw i8 %a, 1 423 %t.1 = icmp ule i8 %add.1, %b 424 %t.2 = icmp ule i8 %a, %b 425 %res.1 = xor i1 %t.1, %t.2 426 %add.2 = add nsw nuw i8 %a, 2 427 %c.1 = icmp ule i8 %add.2, %b 428 %res.2 = xor i1 %res.1, %c.1 429 %cmp.1 = icmp ule i8 %add.1, %b 430 call void @llvm.assume(i1 %cmp.1) 431 br label %exit 432 433exit: 434 ret i1 %res.2 435} 436 437; The function may exit before the assume if @may_unwind unwinds. Conditions 438; before the call cannot be simplified. 439define i1 @assume_same_bb_after_condition_may_unwind_between(i8 %a, i8 %b, i1 %c) { 440; CHECK-LABEL: @assume_same_bb_after_condition_may_unwind_between( 441; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 442; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 443; CHECK-NEXT: call void @use(i1 [[C_1]]) 444; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[A]], [[B]] 445; CHECK-NEXT: call void @use(i1 [[C_2]]) 446; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]] 447; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 448; CHECK-NEXT: [[C_3:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 449; CHECK-NEXT: call void @use(i1 [[C_3]]) 450; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_3]] 451; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]] 452; CHECK-NEXT: call void @may_unwind() 453; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 454; CHECK-NEXT: br label [[EXIT:%.*]] 455; CHECK: exit: 456; CHECK-NEXT: ret i1 [[RES_2]] 457; 458 %add.1 = add nsw nuw i8 %a, 1 459 %c.1 = icmp ule i8 %add.1, %b 460 call void @use(i1 %c.1) 461 %c.2 = icmp ule i8 %a, %b 462 call void @use(i1 %c.2) 463 %res.1 = xor i1 %c.1, %c.2 464 %add.2 = add nsw nuw i8 %a, 2 465 %c.3 = icmp ule i8 %add.2, %b 466 call void @use(i1 %c.3) 467 %res.2 = xor i1 %res.1, %c.3 468 %cmp.1 = icmp ule i8 %add.1, %b 469 call void @may_unwind() 470 call void @llvm.assume(i1 %cmp.1) 471 br label %exit 472 473exit: 474 ret i1 %res.2 475} 476 477; The information of from the assume can be used to simplify %t.2. 478define i1 @assume_single_bb_conditions_after_assume(i8 %a, i8 %b, i1 %c) { 479; CHECK-LABEL: @assume_single_bb_conditions_after_assume( 480; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 481; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 482; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]] 483; CHECK-NEXT: call void @use(i1 [[C_1]]) 484; CHECK-NEXT: call void @may_unwind() 485; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 486; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 487; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 488; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 489; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]] 490; CHECK-NEXT: ret i1 [[RES_2]] 491; 492 %add.1 = add nsw nuw i8 %a, 1 493 %cmp.1 = icmp ule i8 %add.1, %b 494 %c.1 = icmp ule i8 %add.1, %b 495 call void @use(i1 %c.1) 496 497 call void @may_unwind() 498 call void @llvm.assume(i1 %cmp.1) 499 %t.2 = icmp ule i8 %a, %b 500 %res.1 = xor i1 %c.1, %t.2 501 %add.2 = add nsw nuw i8 %a, 2 502 %c.2 = icmp ule i8 %add.2, %b 503 %res.2 = xor i1 %res.1, %c.2 504 ret i1 %res.2 505} 506 507; The information of from the assume can be used to simplify %t.2. 508; TODO 509define i1 @assume_single_bb_assume_at_end_after_may_unwind(i8 %a, i8 %b, i1 %c) { 510; CHECK-LABEL: @assume_single_bb_assume_at_end_after_may_unwind( 511; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 512; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 513; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]] 514; CHECK-NEXT: call void @use(i1 [[C_1]]) 515; CHECK-NEXT: call void @may_unwind() 516; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]] 517; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_2]] 518; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 519; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 520; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]] 521; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 522; CHECK-NEXT: ret i1 [[RES_2]] 523; 524 %add.1 = add nsw nuw i8 %a, 1 525 %cmp.1 = icmp ule i8 %add.1, %b 526 %c.1 = icmp ule i8 %add.1, %b 527 call void @use(i1 %c.1) 528 529 call void @may_unwind() 530 %t.2 = icmp ule i8 %a, %b 531 %res.1 = xor i1 %c.1, %t.2 532 %add.2 = add nsw nuw i8 %a, 2 533 %c.2 = icmp ule i8 %add.2, %b 534 %res.2 = xor i1 %res.1, %c.2 535 call void @llvm.assume(i1 %cmp.1) 536 ret i1 %res.2 537} 538 539; The definition of %t.2 is before the @llvm.assume call, but all uses are 540; after the call. %t.2 can be simplified. 541; TODO 542define i1 @all_uses_after_assume(i8 %a, i8 %b, i1 %c) { 543; CHECK-LABEL: @all_uses_after_assume( 544; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1 545; CHECK-NEXT: [[CMP_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]] 546; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]] 547; CHECK-NEXT: call void @use(i1 [[C_1]]) 548; CHECK-NEXT: call void @may_unwind() 549; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]]) 550; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 551; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2 552; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2]], [[B]] 553; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]] 554; CHECK-NEXT: ret i1 [[RES_2]] 555; 556 %add.1 = add nsw nuw i8 %a, 1 557 %cmp.1 = icmp ule i8 %add.1, %b 558 %c.1 = icmp ule i8 %add.1, %b 559 %t.2 = icmp ule i8 %a, %b 560 call void @use(i1 %c.1) 561 562 call void @may_unwind() 563 call void @llvm.assume(i1 %cmp.1) 564 %res.1 = xor i1 %c.1, %t.2 565 %add.2 = add nsw nuw i8 %a, 2 566 %c.2 = icmp ule i8 %add.2, %b 567 %res.2 = xor i1 %res.1, %c.2 568 ret i1 %res.2 569} 570 571define i1 @test_order_assume_and_conds_in_different_bb(i16 %a, ptr %dst) { 572; CHECK-LABEL: @test_order_assume_and_conds_in_different_bb( 573; CHECK-NEXT: entry: 574; CHECK-NEXT: [[C_1:%.*]] = icmp ult i16 [[A:%.*]], 10 575; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[ELSE:%.*]] 576; CHECK: then: 577; CHECK-NEXT: ret i1 false 578; CHECK: else: 579; CHECK-NEXT: store volatile float 0.000000e+00, ptr [[DST:%.*]], align 4 580; CHECK-NEXT: [[C_2:%.*]] = icmp eq i16 [[A]], 20 581; CHECK-NEXT: tail call void @llvm.assume(i1 [[C_2]]) 582; CHECK-NEXT: ret i1 true 583; 584entry: 585 %c.1 = icmp ult i16 %a, 10 586 br i1 %c.1, label %then, label %else 587 588then: 589 ret i1 0 590 591else: 592 store volatile float 0.000000e+00, ptr %dst 593 %c.2 = icmp eq i16 %a, 20 594 tail call void @llvm.assume(i1 %c.2) 595 ret i1 %c.2 596} 597