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 @use(i1) 5 6define void @test_or_ule(i4 %x, i4 %y, i4 %z, i4 %a) { 7; CHECK-LABEL: @test_or_ule( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]] 10; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]] 11; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_1]], [[C_2]] 12; CHECK-NEXT: br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]] 13; CHECK: bb1: 14; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 [[X]], [[Z]] 15; CHECK-NEXT: call void @use(i1 [[C_3]]) 16; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 [[X]], [[A:%.*]] 17; CHECK-NEXT: call void @use(i1 [[C_4]]) 18; CHECK-NEXT: ret void 19; CHECK: exit: 20; CHECK-NEXT: call void @use(i1 false) 21; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[A]] 22; CHECK-NEXT: call void @use(i1 [[C_5]]) 23; CHECK-NEXT: call void @use(i1 true) 24; CHECK-NEXT: call void @use(i1 true) 25; CHECK-NEXT: call void @use(i1 true) 26; CHECK-NEXT: ret void 27; 28entry: 29 %c.1 = icmp ule i4 %x, %y 30 %c.2 = icmp ule i4 %y, %z 31 %or = or i1 %c.1, %c.2 32 br i1 %or, label %bb1, label %exit 33 34bb1: 35 %c.3 = icmp ule i4 %x, %z 36 call void @use(i1 %c.3) 37 38 %c.4 = icmp ule i4 %x, %a 39 call void @use(i1 %c.4) 40 41 ret void 42 43exit: 44 %f.1 = icmp ule i4 %x, %z 45 call void @use(i1 %f.1) 46 47 %c.5 = icmp ule i4 %x, %a 48 call void @use(i1 %c.5) 49 50 %t.1 = icmp ugt i4 %y, %z 51 call void @use(i1 %t.1) 52 53 %t.2 = icmp ugt i4 %x, %y 54 call void @use(i1 %t.2) 55 56 %t.3 = icmp ugt i4 %x, %z 57 call void @use(i1 %t.3) 58 59 ret void 60} 61 62; The result of test_or_ule and test_or_select_ule should be same 63define void @test_or_select_ule(i4 %x, i4 %y, i4 %z, i4 %a) { 64; CHECK-LABEL: @test_or_select_ule( 65; CHECK-NEXT: entry: 66; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]] 67; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]] 68; CHECK-NEXT: [[OR:%.*]] = select i1 [[C_1]], i1 true, i1 [[C_2]] 69; CHECK-NEXT: br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]] 70; CHECK: bb1: 71; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 [[X]], [[Z]] 72; CHECK-NEXT: call void @use(i1 [[C_3]]) 73; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 [[X]], [[A:%.*]] 74; CHECK-NEXT: call void @use(i1 [[C_4]]) 75; CHECK-NEXT: ret void 76; CHECK: exit: 77; CHECK-NEXT: call void @use(i1 false) 78; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[A]] 79; CHECK-NEXT: call void @use(i1 [[C_5]]) 80; CHECK-NEXT: call void @use(i1 true) 81; CHECK-NEXT: call void @use(i1 true) 82; CHECK-NEXT: call void @use(i1 true) 83; CHECK-NEXT: ret void 84; 85entry: 86 %c.1 = icmp ule i4 %x, %y 87 %c.2 = icmp ule i4 %y, %z 88 %or = select i1 %c.1, i1 true, i1 %c.2 89 br i1 %or, label %bb1, label %exit 90 91bb1: 92 %c.3 = icmp ule i4 %x, %z 93 call void @use(i1 %c.3) 94 95 %c.4 = icmp ule i4 %x, %a 96 call void @use(i1 %c.4) 97 98 ret void 99 100exit: 101 %f.1 = icmp ule i4 %x, %z 102 call void @use(i1 %f.1) 103 104 %c.5 = icmp ule i4 %x, %a 105 call void @use(i1 %c.5) 106 107 %t.1 = icmp ugt i4 %y, %z 108 call void @use(i1 %t.1) 109 110 %t.2 = icmp ugt i4 %x, %y 111 call void @use(i1 %t.2) 112 113 %t.3 = icmp ugt i4 %x, %z 114 call void @use(i1 %t.3) 115 116 ret void 117} 118 119define i1 @test_or_chain_ule_1(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) { 120; CHECK-LABEL: @test_or_chain_ule_1( 121; CHECK-NEXT: entry: 122; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]] 123; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]] 124; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 2, [[X]] 125; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]] 126; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]] 127; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[OR_1]], true 128; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[C_4]], [[OR_2]] 129; CHECK-NEXT: br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]] 130; CHECK: bb1: 131; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]] 132; CHECK-NEXT: [[C_6:%.*]] = icmp ule i4 [[X]], [[A]] 133; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]] 134; CHECK-NEXT: [[C_7:%.*]] = icmp ule i4 2, [[X]] 135; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]] 136; CHECK-NEXT: ret i1 [[RES_2]] 137; CHECK: exit: 138; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true 139; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true 140; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true 141; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], true 142; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], true 143; CHECK-NEXT: [[RES_8:%.*]] = xor i1 [[RES_7]], true 144; CHECK-NEXT: [[RES_9:%.*]] = xor i1 [[RES_8]], true 145; CHECK-NEXT: ret i1 [[RES_9]] 146; 147entry: 148 %c.1 = icmp ule i4 %x, %y 149 %c.2 = icmp ule i4 %y, %z 150 %c.3 = icmp ule i4 2, %x 151 %c.4 = icmp ule i4 2, %a 152 %or.1 = or i1 %c.1, %c.2 153 %or.2 = or i1 %or.1, %c.3 154 %or.3 = or i1 %c.4, %or.2 155 br i1 %or.3, label %bb1, label %exit 156 157bb1: 158 %c.5 = icmp ule i4 %x, %z 159 %c.6 = icmp ule i4 %x, %a 160 %res.1 = xor i1 %c.5, %c.6 161 %c.7 = icmp ule i4 2, %x 162 %res.2 = xor i1 %res.1, %c.7 163 ret i1 %res.2 164 165exit: 166 %f.1 = icmp ule i4 %x, %z 167 %f.2 = icmp ule i4 2, %x 168 %res.3 = xor i1 %f.1, %f.2 169 170 %t.1 = icmp ugt i4 %y, %z 171 %res.4 = xor i1 %res.3, %t.1 172 173 %t.2 = icmp ugt i4 %x, %y 174 %res.5 = xor i1 %res.4, %t.2 175 176 %t.3 = icmp ugt i4 %x, %z 177 %res.6 = xor i1 %res.5, %t.3 178 179 %t.4 = icmp ugt i4 2, %a 180 %res.7 = xor i1 %res.6, %t.4 181 182 %c.8 = icmp ule i4 %x, %a 183 %res.8 = xor i1 %res.7, %c.8 184 185 %c.9 = icmp ule i4 %x, %b 186 %res.9 = xor i1 %res.8, %c.9 187 188 ret i1 %res.9 189} 190 191; Same as @test_or_chain_ule_1, but with the `or`s ordered differently. 192define i1 @test_or_chain_ule_2(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) { 193; CHECK-LABEL: @test_or_chain_ule_2( 194; CHECK-NEXT: entry: 195; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]] 196; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]] 197; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 2, [[X]] 198; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]] 199; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]] 200; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[C_3]], [[C_4]] 201; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[OR_1]], [[OR_2]] 202; CHECK-NEXT: br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]] 203; CHECK: bb1: 204; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]] 205; CHECK-NEXT: [[C_6:%.*]] = icmp ule i4 [[X]], [[A]] 206; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]] 207; CHECK-NEXT: [[C_7:%.*]] = icmp ule i4 2, [[X]] 208; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]] 209; CHECK-NEXT: ret i1 [[RES_2]] 210; CHECK: exit: 211; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true 212; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true 213; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true 214; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], true 215; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], true 216; CHECK-NEXT: [[RES_8:%.*]] = xor i1 [[RES_7]], true 217; CHECK-NEXT: [[RES_9:%.*]] = xor i1 [[RES_8]], true 218; CHECK-NEXT: ret i1 [[RES_9]] 219; 220entry: 221 %c.1 = icmp ule i4 %x, %y 222 %c.2 = icmp ule i4 %y, %z 223 %c.3 = icmp ule i4 2, %x 224 %c.4 = icmp ule i4 2, %a 225 %or.1 = or i1 %c.1, %c.2 226 %or.2 = or i1 %c.3, %c.4 227 %or.3 = or i1 %or.1, %or.2 228 br i1 %or.3, label %bb1, label %exit 229 230bb1: 231 %c.5 = icmp ule i4 %x, %z 232 %c.6 = icmp ule i4 %x, %a 233 %res.1 = xor i1 %c.5, %c.6 234 %c.7 = icmp ule i4 2, %x 235 %res.2 = xor i1 %res.1, %c.7 236 ret i1 %res.2 237 238exit: 239 %f.1 = icmp ule i4 %x, %z 240 %f.2 = icmp ule i4 2, %x 241 %res.3 = xor i1 %f.1, %f.2 242 243 %t.1 = icmp ugt i4 %y, %z 244 %res.4 = xor i1 %res.3, %t.1 245 246 %t.2 = icmp ugt i4 %x, %y 247 %res.5 = xor i1 %res.4, %t.2 248 249 %t.3 = icmp ugt i4 %x, %z 250 %res.6 = xor i1 %res.5, %t.3 251 252 %t.4 = icmp ugt i4 2, %a 253 %res.7 = xor i1 %res.6, %t.4 254 255 %c.8 = icmp ule i4 %x, %a 256 %res.8 = xor i1 %res.7, %c.8 257 258 %c.9 = icmp ule i4 %x, %b 259 %res.9 = xor i1 %res.8, %c.9 260 261 ret i1 %res.9 262} 263 264declare i1 @cond() readnone 265 266; Test with `or` chain that also contains instructions other than `or` and `icmp`. 267define i1 @test_or_chain_with_other_conds_ule(i4 %x, i4 %y, i4 %z, i4 %a, i1 %arg.c) { 268; CHECK-LABEL: @test_or_chain_with_other_conds_ule( 269; CHECK-NEXT: entry: 270; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]] 271; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]] 272; CHECK-NEXT: [[C_3:%.*]] = call i1 @cond() 273; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]] 274; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[C_3]], [[OR_1]] 275; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[OR_2]], [[ARG_C:%.*]] 276; CHECK-NEXT: br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]] 277; CHECK: bb1: 278; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]] 279; CHECK-NEXT: [[C_6:%.*]] = icmp ule i4 [[X]], [[A:%.*]] 280; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]] 281; CHECK-NEXT: [[C_7:%.*]] = icmp ule i4 2, [[X]] 282; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]] 283; CHECK-NEXT: ret i1 [[RES_2]] 284; CHECK: exit: 285; CHECK-NEXT: [[RES_3:%.*]] = xor i1 false, true 286; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true 287; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true 288; CHECK-NEXT: [[C_8:%.*]] = icmp ule i4 [[X]], [[A]] 289; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[C_8]] 290; CHECK-NEXT: ret i1 [[RES_6]] 291; 292entry: 293 %c.1 = icmp ule i4 %x, %y 294 %c.2 = icmp ule i4 %y, %z 295 %c.3 = call i1 @cond() 296 %or.1 = or i1 %c.1, %c.2 297 %or.2 = or i1 %c.3, %or.1 298 %or.3 = or i1 %or.2, %arg.c 299 br i1 %or.3, label %bb1, label %exit 300 301bb1: 302 %c.5 = icmp ule i4 %x, %z 303 %c.6 = icmp ule i4 %x, %a 304 %res.1 = xor i1 %c.5, %c.6 305 %c.7 = icmp ule i4 2, %x 306 %res.2 = xor i1 %res.1, %c.7 307 ret i1 %res.2 308 309exit: 310 %f.1 = icmp ule i4 %x, %z 311 312 %t.1 = icmp ugt i4 %y, %z 313 %res.3 = xor i1 %f.1, %t.1 314 315 %t.2 = icmp ugt i4 %x, %y 316 %res.4 = xor i1 %res.3, %t.2 317 318 %t.3 = icmp ugt i4 %x, %z 319 %res.5 = xor i1 %res.4, %t.3 320 321 %c.8 = icmp ule i4 %x, %a 322 %res.6 = xor i1 %res.5, %c.8 323 324 ret i1 %res.6 325} 326 327define i1 @test_or_chain_with_and_ule(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) { 328; CHECK-LABEL: @test_or_chain_with_and_ule( 329; CHECK-NEXT: entry: 330; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]] 331; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]] 332; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 2, [[X]] 333; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]] 334; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]] 335; CHECK-NEXT: [[AND_2:%.*]] = and i1 [[C_3]], [[C_4]] 336; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[OR_1]], [[AND_2]] 337; CHECK-NEXT: br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]] 338; CHECK: bb1: 339; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]] 340; CHECK-NEXT: [[C_6:%.*]] = icmp ule i4 [[X]], [[A]] 341; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]] 342; CHECK-NEXT: [[C_7:%.*]] = icmp ule i4 2, [[X]] 343; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]] 344; CHECK-NEXT: ret i1 [[RES_2]] 345; CHECK: exit: 346; CHECK-NEXT: [[RES_3:%.*]] = xor i1 false, true 347; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true 348; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true 349; CHECK-NEXT: [[C_8:%.*]] = icmp ule i4 [[X]], [[A]] 350; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[C_8]] 351; CHECK-NEXT: [[C_9:%.*]] = icmp ule i4 [[X]], [[B:%.*]] 352; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], [[C_9]] 353; CHECK-NEXT: [[RES_8:%.*]] = xor i1 [[RES_7]], true 354; CHECK-NEXT: [[C_11:%.*]] = icmp ugt i4 2, [[A]] 355; CHECK-NEXT: [[RES_9:%.*]] = xor i1 [[RES_8]], [[C_11]] 356; CHECK-NEXT: ret i1 [[RES_9]] 357; 358entry: 359 %c.1 = icmp ule i4 %x, %y 360 %c.2 = icmp ule i4 %y, %z 361 %c.3 = icmp ule i4 2, %x 362 %c.4 = icmp ule i4 2, %a 363 %or.1 = or i1 %c.1, %c.2 364 %and.2 = and i1 %c.3, %c.4 365 %or.3 = or i1 %or.1, %and.2 366 br i1 %or.3, label %bb1, label %exit 367 368bb1: 369 %c.5 = icmp ule i4 %x, %z 370 %c.6 = icmp ule i4 %x, %a 371 %res.1 = xor i1 %c.5, %c.6 372 %c.7 = icmp ule i4 2, %x 373 %res.2 = xor i1 %res.1, %c.7 374 ret i1 %res.2 375 376exit: 377 %f.1 = icmp ule i4 %x, %z 378 %t.1 = icmp ugt i4 %y, %z 379 %res.3 = xor i1 %f.1, %t.1 380 381 %t.2 = icmp ugt i4 %x, %y 382 %res.4 = xor i1 %res.3, %t.2 383 384 %t.3 = icmp ugt i4 %x, %z 385 %res.5 = xor i1 %res.4, %t.3 386 387 %c.8 = icmp ule i4 %x, %a 388 %res.6 = xor i1 %res.5, %c.8 389 390 %c.9 = icmp ule i4 %x, %b 391 %res.7 = xor i1 %res.6, %c.9 392 393 %c.10 = icmp ule i4 2, %x 394 %res.8 = xor i1 %res.7, %c.10 395 396 %c.11 = icmp ugt i4 2, %a 397 %res.9 = xor i1 %res.8, %c.11 398 399 ret i1 %res.9 400} 401 402define void @test_or_as_add_ult(i8 %init_val, i8 %high) { 403; CHECK-LABEL: @test_or_as_add_ult( 404; CHECK-NEXT: entry: 405; CHECK-NEXT: [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2 406; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3 407; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]] 408; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]] 409; CHECK: then: 410; CHECK-NEXT: [[F_0:%.*]] = icmp ult i8 [[START]], [[HIGH]] 411; CHECK-NEXT: call void @use(i1 [[F_0]]) 412; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1 413; CHECK-NEXT: [[F_1:%.*]] = icmp ult i8 [[I_1]], [[HIGH]] 414; CHECK-NEXT: call void @use(i1 [[F_1]]) 415; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2 416; CHECK-NEXT: [[F_2:%.*]] = icmp ult i8 [[I_2]], [[HIGH]] 417; CHECK-NEXT: call void @use(i1 [[F_2]]) 418; CHECK-NEXT: ret void 419; CHECK: end: 420; CHECK-NEXT: call void @use(i1 true) 421; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1 422; CHECK-NEXT: call void @use(i1 true) 423; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2 424; CHECK-NEXT: call void @use(i1 true) 425; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3 426; CHECK-NEXT: call void @use(i1 true) 427; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4 428; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8 [[START_4]], [[HIGH]] 429; CHECK-NEXT: call void @use(i1 [[C_4]]) 430; CHECK-NEXT: ret void 431; 432entry: 433 %start = shl nuw nsw i8 %init_val, 2 434 %start.plus.3 = add nuw i8 %start, 3 435 %c.1 = icmp uge i8 %start.plus.3, %high 436 br i1 %c.1, label %then, label %end 437 438then: ; preds = %entry 439 %f.0 = icmp ult i8 %start, %high 440 call void @use(i1 %f.0) 441 %i.1 = or disjoint i8 %start, 1 442 %f.1 = icmp ult i8 %i.1, %high 443 call void @use(i1 %f.1) 444 %i.2 = or disjoint i8 %start, 2 445 %f.2 = icmp ult i8 %i.2, %high 446 call void @use(i1 %f.2) 447 ret void 448 449end: ; preds = %entry 450 %t.0 = icmp ult i8 %start, %high 451 call void @use(i1 %t.0) 452 %start.1 = or disjoint i8 %start, 1 453 %t.1 = icmp ult i8 %start.1, %high 454 call void @use(i1 %t.1) 455 %start.2 = or disjoint i8 %start, 2 456 %t.2 = icmp ult i8 %start.2, %high 457 call void @use(i1 %t.2) 458 %start.3 = or disjoint i8 %start, 3 459 %t.3 = icmp ult i8 %start.3, %high 460 call void @use(i1 %t.3) 461 %start.4 = or i8 %start, 4 462 %c.4 = icmp ult i8 %start.4, %high 463 call void @use(i1 %c.4) 464 ret void 465} 466 467define void @test_or_as_add_ule(i8 %init_val, i8 %high) { 468; CHECK-LABEL: @test_or_as_add_ule( 469; CHECK-NEXT: entry: 470; CHECK-NEXT: [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2 471; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3 472; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]] 473; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]] 474; CHECK: then: 475; CHECK-NEXT: [[F_0:%.*]] = icmp ule i8 [[START]], [[HIGH]] 476; CHECK-NEXT: call void @use(i1 [[F_0]]) 477; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1 478; CHECK-NEXT: [[F_1:%.*]] = icmp ule i8 [[I_1]], [[HIGH]] 479; CHECK-NEXT: call void @use(i1 [[F_1]]) 480; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2 481; CHECK-NEXT: [[F_2:%.*]] = icmp ule i8 [[I_2]], [[HIGH]] 482; CHECK-NEXT: call void @use(i1 [[F_2]]) 483; CHECK-NEXT: ret void 484; CHECK: end: 485; CHECK-NEXT: call void @use(i1 true) 486; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1 487; CHECK-NEXT: call void @use(i1 true) 488; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2 489; CHECK-NEXT: call void @use(i1 true) 490; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3 491; CHECK-NEXT: call void @use(i1 true) 492; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4 493; CHECK-NEXT: [[T_4:%.*]] = icmp ule i8 [[START_4]], [[HIGH]] 494; CHECK-NEXT: call void @use(i1 [[T_4]]) 495; CHECK-NEXT: [[START_5:%.*]] = or i8 [[START]], 5 496; CHECK-NEXT: [[C_5:%.*]] = icmp ule i8 [[START_5]], [[HIGH]] 497; CHECK-NEXT: call void @use(i1 [[C_5]]) 498; CHECK-NEXT: ret void 499; 500entry: 501 %start = shl nuw nsw i8 %init_val, 2 502 %start.plus.3 = add nuw i8 %start, 3 503 %c.1 = icmp uge i8 %start.plus.3, %high 504 br i1 %c.1, label %then, label %end 505 506then: ; preds = %entry 507 %f.0 = icmp ule i8 %start, %high 508 call void @use(i1 %f.0) 509 %i.1 = or disjoint i8 %start, 1 510 %f.1 = icmp ule i8 %i.1, %high 511 call void @use(i1 %f.1) 512 %i.2 = or disjoint i8 %start, 2 513 %f.2 = icmp ule i8 %i.2, %high 514 call void @use(i1 %f.2) 515 ret void 516 517end: ; preds = %entry 518 %t.0 = icmp ule i8 %start, %high 519 call void @use(i1 %t.0) 520 %start.1 = or disjoint i8 %start, 1 521 %t.1 = icmp ule i8 %start.1, %high 522 call void @use(i1 %t.1) 523 %start.2 = or disjoint i8 %start, 2 524 %t.2 = icmp ule i8 %start.2, %high 525 call void @use(i1 %t.2) 526 %start.3 = or disjoint i8 %start, 3 527 %t.3 = icmp ule i8 %start.3, %high 528 call void @use(i1 %t.3) 529 %start.4 = or i8 %start, 4 530 %t.4 = icmp ule i8 %start.4, %high 531 call void @use(i1 %t.4) 532 %start.5 = or i8 %start, 5 533 %c.5 = icmp ule i8 %start.5, %high 534 call void @use(i1 %c.5) 535 536 ret void 537} 538 539define void @test_or_as_add_ugt(i8 %init_val, i8 %high) { 540; CHECK-LABEL: @test_or_as_add_ugt( 541; CHECK-NEXT: entry: 542; CHECK-NEXT: [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2 543; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3 544; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]] 545; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]] 546; CHECK: then: 547; CHECK-NEXT: [[T_0:%.*]] = icmp ugt i8 [[START]], [[HIGH]] 548; CHECK-NEXT: call void @use(i1 [[T_0]]) 549; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1 550; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[I_1]], [[HIGH]] 551; CHECK-NEXT: call void @use(i1 [[T_1]]) 552; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2 553; CHECK-NEXT: [[T_2:%.*]] = icmp ugt i8 [[I_2]], [[HIGH]] 554; CHECK-NEXT: call void @use(i1 [[T_2]]) 555; CHECK-NEXT: ret void 556; CHECK: end: 557; CHECK-NEXT: call void @use(i1 false) 558; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1 559; CHECK-NEXT: call void @use(i1 false) 560; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2 561; CHECK-NEXT: call void @use(i1 false) 562; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3 563; CHECK-NEXT: call void @use(i1 false) 564; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4 565; CHECK-NEXT: [[F_4:%.*]] = icmp ugt i8 [[START_4]], [[HIGH]] 566; CHECK-NEXT: call void @use(i1 [[F_4]]) 567; CHECK-NEXT: [[START_5:%.*]] = or i8 [[START]], 5 568; CHECK-NEXT: [[C_5:%.*]] = icmp ugt i8 [[START_5]], [[HIGH]] 569; CHECK-NEXT: call void @use(i1 [[C_5]]) 570; CHECK-NEXT: ret void 571; 572entry: 573 %start = shl nuw nsw i8 %init_val, 2 574 %start.plus.3 = add nuw i8 %start, 3 575 %c.1 = icmp uge i8 %start.plus.3, %high 576 br i1 %c.1, label %then, label %end 577 578then: ; preds = %entry 579 %t.0 = icmp ugt i8 %start, %high 580 call void @use(i1 %t.0) 581 %i.1 = or disjoint i8 %start, 1 582 %t.1 = icmp ugt i8 %i.1, %high 583 call void @use(i1 %t.1) 584 %i.2 = or disjoint i8 %start, 2 585 %t.2 = icmp ugt i8 %i.2, %high 586 call void @use(i1 %t.2) 587 ret void 588 589end: ; preds = %entry 590 %f.0 = icmp ugt i8 %start, %high 591 call void @use(i1 %f.0) 592 %start.1 = or disjoint i8 %start, 1 593 %f.1 = icmp ugt i8 %start.1, %high 594 call void @use(i1 %f.1) 595 %start.2 = or disjoint i8 %start, 2 596 %f.2 = icmp ugt i8 %start.2, %high 597 call void @use(i1 %f.2) 598 %start.3 = or disjoint i8 %start, 3 599 %f.3 = icmp ugt i8 %start.3, %high 600 call void @use(i1 %f.3) 601 %start.4 = or i8 %start, 4 602 %f.4 = icmp ugt i8 %start.4, %high 603 call void @use(i1 %f.4) 604 %start.5 = or i8 %start, 5 605 %c.5 = icmp ugt i8 %start.5, %high 606 call void @use(i1 %c.5) 607 ret void 608} 609 610define void @test_or_as_add_uge(i8 %init_val, i8 %high) { 611; CHECK-LABEL: @test_or_as_add_uge( 612; CHECK-NEXT: entry: 613; CHECK-NEXT: [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2 614; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3 615; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]] 616; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]] 617; CHECK: then: 618; CHECK-NEXT: [[T_0:%.*]] = icmp ugt i8 [[START]], [[HIGH]] 619; CHECK-NEXT: call void @use(i1 [[T_0]]) 620; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1 621; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]] 622; CHECK-NEXT: call void @use(i1 [[T_1]]) 623; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2 624; CHECK-NEXT: [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]] 625; CHECK-NEXT: call void @use(i1 [[T_2]]) 626; CHECK-NEXT: ret void 627; CHECK: end: 628; CHECK-NEXT: call void @use(i1 false) 629; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1 630; CHECK-NEXT: call void @use(i1 false) 631; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2 632; CHECK-NEXT: call void @use(i1 false) 633; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3 634; CHECK-NEXT: call void @use(i1 false) 635; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4 636; CHECK-NEXT: [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]] 637; CHECK-NEXT: call void @use(i1 [[C_4]]) 638; CHECK-NEXT: [[START_5:%.*]] = or i8 [[START]], 5 639; CHECK-NEXT: [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]] 640; CHECK-NEXT: call void @use(i1 [[C_5]]) 641; CHECK-NEXT: ret void 642; 643entry: 644 %start = shl nuw nsw i8 %init_val, 2 645 %start.plus.3 = add nuw i8 %start, 3 646 %c.1 = icmp uge i8 %start.plus.3, %high 647 br i1 %c.1, label %then, label %end 648 649then: ; preds = %entry 650 %t.0 = icmp ugt i8 %start, %high 651 call void @use(i1 %t.0) 652 %i.1 = or disjoint i8 %start, 1 653 %t.1 = icmp uge i8 %i.1, %high 654 call void @use(i1 %t.1) 655 %i.2 = or disjoint i8 %start, 2 656 %t.2 = icmp uge i8 %i.2, %high 657 call void @use(i1 %t.2) 658 ret void 659 660end: ; preds = %entry 661 %f.0 = icmp ugt i8 %start, %high 662 call void @use(i1 %f.0) 663 %start.1 = or disjoint i8 %start, 1 664 %f.1 = icmp uge i8 %start.1, %high 665 call void @use(i1 %f.1) 666 %start.2 = or disjoint i8 %start, 2 667 %f.2 = icmp uge i8 %start.2, %high 668 call void @use(i1 %f.2) 669 %start.3 = or disjoint i8 %start, 3 670 %f.3 = icmp uge i8 %start.3, %high 671 call void @use(i1 %f.3) 672 %start.4 = or i8 %start, 4 673 %c.4 = icmp uge i8 %start.4, %high 674 call void @use(i1 %c.4) 675 %start.5 = or i8 %start, 5 676 %c.5 = icmp uge i8 %start.5, %high 677 call void @use(i1 %c.5) 678 ret void 679} 680 681define void @test_not_decompose(i8 %start, i8 %high) { 682; CHECK-LABEL: @test_not_decompose( 683; CHECK-NEXT: entry: 684; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START:%.*]], 3 685; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]] 686; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]] 687; CHECK: then: 688; CHECK-NEXT: [[I_1:%.*]] = or i8 [[START]], 1 689; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]] 690; CHECK-NEXT: call void @use(i1 [[T_1]]) 691; CHECK-NEXT: [[I_2:%.*]] = or i8 [[START]], 2 692; CHECK-NEXT: [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]] 693; CHECK-NEXT: call void @use(i1 [[T_2]]) 694; CHECK-NEXT: ret void 695; CHECK: end: 696; CHECK-NEXT: [[START_1:%.*]] = or i8 [[START]], 1 697; CHECK-NEXT: [[F_1:%.*]] = icmp uge i8 [[START_1]], [[HIGH]] 698; CHECK-NEXT: call void @use(i1 [[F_1]]) 699; CHECK-NEXT: [[START_2:%.*]] = or i8 [[START]], 2 700; CHECK-NEXT: [[F_2:%.*]] = icmp uge i8 [[START_2]], [[HIGH]] 701; CHECK-NEXT: call void @use(i1 [[F_2]]) 702; CHECK-NEXT: [[START_3:%.*]] = or i8 [[START]], 3 703; CHECK-NEXT: [[F_3:%.*]] = icmp uge i8 [[START_3]], [[HIGH]] 704; CHECK-NEXT: call void @use(i1 [[F_3]]) 705; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4 706; CHECK-NEXT: [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]] 707; CHECK-NEXT: call void @use(i1 [[C_4]]) 708; CHECK-NEXT: [[START_5:%.*]] = or i8 [[START]], 5 709; CHECK-NEXT: [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]] 710; CHECK-NEXT: call void @use(i1 [[C_5]]) 711; CHECK-NEXT: ret void 712; 713entry: 714 %start.plus.3 = add nuw i8 %start, 3 715 %c.1 = icmp uge i8 %start.plus.3, %high 716 br i1 %c.1, label %then, label %end 717 718then: ; preds = %entry 719 %i.1 = or i8 %start, 1 720 %t.1 = icmp uge i8 %i.1, %high 721 call void @use(i1 %t.1) 722 %i.2 = or i8 %start, 2 723 %t.2 = icmp uge i8 %i.2, %high 724 call void @use(i1 %t.2) 725 ret void 726 727end: ; preds = %entry 728 %start.1 = or i8 %start, 1 729 %f.1 = icmp uge i8 %start.1, %high 730 call void @use(i1 %f.1) 731 %start.2 = or i8 %start, 2 732 %f.2 = icmp uge i8 %start.2, %high 733 call void @use(i1 %f.2) 734 %start.3 = or i8 %start, 3 735 %f.3 = icmp uge i8 %start.3, %high 736 call void @use(i1 %f.3) 737 %start.4 = or i8 %start, 4 738 %c.4 = icmp uge i8 %start.4, %high 739 call void @use(i1 %c.4) 740 %start.5 = or i8 %start, 5 741 %c.5 = icmp uge i8 %start.5, %high 742 call void @use(i1 %c.5) 743 744 ret void 745} 746 747; Nothing in the IR implies the disjoint flag, but we can still use it 748; to decompose into an add. 749define void @test_decompose_explicit_disjoint(i8 %start, i8 %high) { 750; CHECK-LABEL: @test_decompose_explicit_disjoint( 751; CHECK-NEXT: entry: 752; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START:%.*]], 3 753; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]] 754; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]] 755; CHECK: then: 756; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1 757; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]] 758; CHECK-NEXT: call void @use(i1 [[T_1]]) 759; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2 760; CHECK-NEXT: [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]] 761; CHECK-NEXT: call void @use(i1 [[T_2]]) 762; CHECK-NEXT: ret void 763; CHECK: end: 764; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1 765; CHECK-NEXT: call void @use(i1 false) 766; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2 767; CHECK-NEXT: call void @use(i1 false) 768; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3 769; CHECK-NEXT: call void @use(i1 false) 770; CHECK-NEXT: [[START_4:%.*]] = or disjoint i8 [[START]], 4 771; CHECK-NEXT: [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]] 772; CHECK-NEXT: call void @use(i1 [[C_4]]) 773; CHECK-NEXT: [[START_5:%.*]] = or disjoint i8 [[START]], 5 774; CHECK-NEXT: [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]] 775; CHECK-NEXT: call void @use(i1 [[C_5]]) 776; CHECK-NEXT: ret void 777; 778entry: 779 %start.plus.3 = add nuw i8 %start, 3 780 %c.1 = icmp uge i8 %start.plus.3, %high 781 br i1 %c.1, label %then, label %end 782 783then: ; preds = %entry 784 %i.1 = or disjoint i8 %start, 1 785 %t.1 = icmp uge i8 %i.1, %high 786 call void @use(i1 %t.1) 787 %i.2 = or disjoint i8 %start, 2 788 %t.2 = icmp uge i8 %i.2, %high 789 call void @use(i1 %t.2) 790 ret void 791 792end: ; preds = %entry 793 %start.1 = or disjoint i8 %start, 1 794 %f.1 = icmp uge i8 %start.1, %high 795 call void @use(i1 %f.1) 796 %start.2 = or disjoint i8 %start, 2 797 %f.2 = icmp uge i8 %start.2, %high 798 call void @use(i1 %f.2) 799 %start.3 = or disjoint i8 %start, 3 800 %f.3 = icmp uge i8 %start.3, %high 801 call void @use(i1 %f.3) 802 %start.4 = or disjoint i8 %start, 4 803 %c.4 = icmp uge i8 %start.4, %high 804 call void @use(i1 %c.4) 805 %start.5 = or disjoint i8 %start, 5 806 %c.5 = icmp uge i8 %start.5, %high 807 call void @use(i1 %c.5) 808 809 ret void 810} 811