1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -correlated-propagation %s | FileCheck %s 3 4; Test case for PR44949. 5 6declare void @use(i1) 7 8; We can remove `%res = and i64 %p, 255`, because %r = 0 and we can eliminate 9; %p as well. 10define i64 @constant_and_undef(i1 %c1, i64 %a) { 11; CHECK-LABEL: @constant_and_undef( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 14; CHECK: bb1: 15; CHECK-NEXT: br label [[BB3:%.*]] 16; CHECK: bb2: 17; CHECK-NEXT: [[R:%.*]] = and i64 [[A:%.*]], 0 18; CHECK-NEXT: br label [[BB3]] 19; CHECK: bb3: 20; CHECK-NEXT: call void @use(i1 false) 21; CHECK-NEXT: call void @use(i1 true) 22; CHECK-NEXT: ret i64 0 23; 24entry: 25 br i1 %c1, label %bb1, label %bb2 26 27bb1: 28 br label %bb3 29 30bb2: 31 %r = and i64 %a, 0 32 br label %bb3 33 34bb3: 35 %p = phi i64 [ undef, %bb1 ], [ %r, %bb2 ] 36 %res = and i64 %p, 255 37 %f.1 = icmp eq i64 %p, 1 38 call void @use(i1 %f.1) 39 %t.1 = icmp eq i64 %p, 0 40 call void @use(i1 %t.1) 41 ret i64 %res 42} 43 44; Check that we go to overdefined when merging a constant range with undef. We 45; cannot remove '%res = and i64 %p, 255'. 46define i64 @constant_range_and_undef(i1 %cond, i64 %a) { 47; CHECK-LABEL: @constant_range_and_undef( 48; CHECK-NEXT: entry: 49; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 50; CHECK: bb1: 51; CHECK-NEXT: br label [[BB3:%.*]] 52; CHECK: bb2: 53; CHECK-NEXT: [[R:%.*]] = and i64 [[A:%.*]], 255 54; CHECK-NEXT: br label [[BB3]] 55; CHECK: bb3: 56; CHECK-NEXT: [[P:%.*]] = phi i64 [ undef, [[BB1]] ], [ [[R]], [[BB2]] ] 57; CHECK-NEXT: [[RES:%.*]] = and i64 [[P]], 255 58; CHECK-NEXT: br label [[EXIT:%.*]] 59; CHECK: exit: 60; CHECK-NEXT: call void @use(i1 false) 61; CHECK-NEXT: call void @use(i1 true) 62; CHECK-NEXT: ret i64 [[RES]] 63; 64entry: 65 br i1 %cond, label %bb1, label %bb2 66 67bb1: 68 br label %bb3 69 70bb2: 71 %r = and i64 %a, 255 72 br label %bb3 73 74bb3: 75 %p = phi i64 [ undef, %bb1 ], [ %r, %bb2 ] 76 %res = and i64 %p, 255 77 br label %exit 78 79exit: ; CVP only simplifies based on ranges for non-local conditions. 80 %f.1 = icmp eq i64 %p, 256 81 call void @use(i1 %f.1) 82 %t.1 = icmp ne i64 %p, 256 83 call void @use(i1 %t.1) 84 ret i64 %res 85} 86 87define i64 @constant_range_and_undef2(i1 %c1, i1 %c2, i64 %a) { 88; CHECK-LABEL: @constant_range_and_undef2( 89; CHECK-NEXT: entry: 90; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 91; CHECK: bb1: 92; CHECK-NEXT: [[V1:%.*]] = add i64 undef, undef 93; CHECK-NEXT: br label [[BB3:%.*]] 94; CHECK: bb2: 95; CHECK-NEXT: [[V2:%.*]] = and i64 [[A:%.*]], 255 96; CHECK-NEXT: br label [[BB3]] 97; CHECK: bb3: 98; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[V1]], [[BB1]] ], [ [[V2]], [[BB2]] ] 99; CHECK-NEXT: br i1 [[C2:%.*]], label [[BB4:%.*]], label [[BB5:%.*]] 100; CHECK: bb4: 101; CHECK-NEXT: br label [[BB6:%.*]] 102; CHECK: bb5: 103; CHECK-NEXT: [[V3:%.*]] = and i64 [[A]], 255 104; CHECK-NEXT: br label [[BB6]] 105; CHECK: bb6: 106; CHECK-NEXT: [[P2:%.*]] = phi i64 [ [[P]], [[BB4]] ], [ [[V3]], [[BB5]] ] 107; CHECK-NEXT: [[RES:%.*]] = and i64 [[P2]], 255 108; CHECK-NEXT: br label [[EXIT:%.*]] 109; CHECK: exit: 110; CHECK-NEXT: [[F_1:%.*]] = icmp eq i64 [[P]], 256 111; CHECK-NEXT: call void @use(i1 [[F_1]]) 112; CHECK-NEXT: [[T_1:%.*]] = icmp ne i64 [[P]], 256 113; CHECK-NEXT: call void @use(i1 [[T_1]]) 114; CHECK-NEXT: ret i64 [[RES]] 115; 116entry: 117 br i1 %c1, label %bb1, label %bb2 118 119bb1: 120 %v1 = add i64 undef, undef 121 br label %bb3 122 123bb2: 124 %v2 = and i64 %a, 255 125 br label %bb3 126 127bb3: 128 %p = phi i64 [ %v1, %bb1 ], [ %v2, %bb2 ] 129 br i1 %c2, label %bb4, label %bb5 130 131bb4: 132 br label %bb6 133 134bb5: 135 %v3 = and i64 %a, 255 136 br label %bb6 137 138bb6: 139 %p2 = phi i64 [ %p, %bb4 ], [ %v3, %bb5 ] 140 %res = and i64 %p2, 255 141 br label %exit 142 143exit: ; CVP only simplifies based on ranges for non-local conditions. 144 %f.1 = icmp eq i64 %p, 256 145 call void @use(i1 %f.1) 146 %t.1 = icmp ne i64 %p, 256 147 call void @use(i1 %t.1) 148 ret i64 %res 149} 150 151define i1 @constant_range_and_undef_3(i1 %cond, i64 %a) { 152; CHECK-LABEL: @constant_range_and_undef_3( 153; CHECK-NEXT: entry: 154; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 155; CHECK: bb1: 156; CHECK-NEXT: br label [[BB3:%.*]] 157; CHECK: bb2: 158; CHECK-NEXT: [[R:%.*]] = and i64 [[A:%.*]], 255 159; CHECK-NEXT: br label [[BB3]] 160; CHECK: bb3: 161; CHECK-NEXT: [[P:%.*]] = phi i64 [ undef, [[BB1]] ], [ [[R]], [[BB2]] ] 162; CHECK-NEXT: br label [[EXIT:%.*]] 163; CHECK: exit: 164; CHECK-NEXT: call void @use(i1 false) 165; CHECK-NEXT: call void @use(i1 true) 166; CHECK-NEXT: ret i1 true 167; 168entry: 169 br i1 %cond, label %bb1, label %bb2 170 171bb1: 172 br label %bb3 173 174bb2: 175 %r = and i64 %a, 255 176 br label %bb3 177 178bb3: 179 %p = phi i64 [ undef, %bb1 ], [ %r, %bb2 ] 180 br label %exit 181 182exit: ; CVP only simplifies based on ranges for non-local conditions. 183 %c = icmp ult i64 %p, 256 184 %f.1 = icmp eq i64 %p, 256 185 call void @use(i1 %f.1) 186 %t.1 = icmp ne i64 %p, 256 187 call void @use(i1 %t.1) 188 ret i1 %c 189} 190 191; Same as @constant_range_and_undef, but with 3 incoming 192; values: undef, a constant and a constant range. 193define i64 @constant_range_and_undef_3_incoming_v1(i1 %c1, i1 %c2, i64 %a) { 194; CHECK-LABEL: @constant_range_and_undef_3_incoming_v1( 195; CHECK-NEXT: entry: 196; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 197; CHECK: bb1: 198; CHECK-NEXT: [[R:%.*]] = and i64 [[A:%.*]], 255 199; CHECK-NEXT: br label [[BB4:%.*]] 200; CHECK: bb2: 201; CHECK-NEXT: br i1 [[C2:%.*]], label [[BB3:%.*]], label [[BB4]] 202; CHECK: bb3: 203; CHECK-NEXT: br label [[BB4]] 204; CHECK: bb4: 205; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[R]], [[BB1]] ], [ 10, [[BB2]] ], [ undef, [[BB3]] ] 206; CHECK-NEXT: [[RES:%.*]] = and i64 [[P]], 255 207; CHECK-NEXT: br label [[EXIT:%.*]] 208; CHECK: exit: 209; CHECK-NEXT: call void @use(i1 false) 210; CHECK-NEXT: call void @use(i1 true) 211; CHECK-NEXT: ret i64 [[RES]] 212; 213entry: 214 br i1 %c1, label %bb1, label %bb2 215 216bb1: 217 %r = and i64 %a, 255 218 br label %bb4 219 220bb2: 221 br i1 %c2, label %bb3, label %bb4 222 223bb3: 224 br label %bb4 225 226bb4: 227 %p = phi i64 [ %r, %bb1 ], [ 10, %bb2], [ undef, %bb3 ] 228 %res = and i64 %p, 255 229 br label %exit 230 231exit: ; CVP only simplifies based on ranges for non-local conditions. 232 %f.1 = icmp eq i64 %p, 256 233 call void @use(i1 %f.1) 234 %t.1 = icmp ne i64 %p, 256 235 call void @use(i1 %t.1) 236 ret i64 %res 237} 238 239; Same as @constant_range_and_undef_3_incoming_v1, but with different order of 240; incoming values. 241define i64 @constant_range_and_undef_3_incoming_v2(i1 %c1, i1 %c2, i64 %a) { 242; CHECK-LABEL: @constant_range_and_undef_3_incoming_v2( 243; CHECK-NEXT: entry: 244; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 245; CHECK: bb1: 246; CHECK-NEXT: br label [[BB4:%.*]] 247; CHECK: bb2: 248; CHECK-NEXT: br i1 [[C2:%.*]], label [[BB3:%.*]], label [[BB4]] 249; CHECK: bb3: 250; CHECK-NEXT: [[R:%.*]] = and i64 [[A:%.*]], 255 251; CHECK-NEXT: br label [[BB4]] 252; CHECK: bb4: 253; CHECK-NEXT: [[P:%.*]] = phi i64 [ undef, [[BB1]] ], [ 10, [[BB2]] ], [ [[R]], [[BB3]] ] 254; CHECK-NEXT: [[RES:%.*]] = and i64 [[P]], 255 255; CHECK-NEXT: br label [[EXIT:%.*]] 256; CHECK: exit: 257; CHECK-NEXT: call void @use(i1 false) 258; CHECK-NEXT: call void @use(i1 true) 259; CHECK-NEXT: ret i64 [[RES]] 260; 261entry: 262 br i1 %c1, label %bb1, label %bb2 263 264bb1: 265 br label %bb4 266 267bb2: 268 br i1 %c2, label %bb3, label %bb4 269 270bb3: 271 %r = and i64 %a, 255 272 br label %bb4 273 274bb4: 275 %p = phi i64 [ undef, %bb1 ], [ 10, %bb2], [ %r, %bb3 ] 276 %res = and i64 %p, 255 277 br label %exit 278 279exit: ; CVP only simplifies based on ranges for non-local conditions. 280 %f.1 = icmp eq i64 %p, 256 281 call void @use(i1 %f.1) 282 %t.1 = icmp ne i64 %p, 256 283 call void @use(i1 %t.1) 284 ret i64 %res 285} 286 287; Same as @constant_range_and_undef_3_incoming_v1, but with different order of 288; incoming values. 289define i64 @constant_range_and_undef_3_incoming_v3(i1 %c1, i1 %c2, i64 %a) { 290; CHECK-LABEL: @constant_range_and_undef_3_incoming_v3( 291; CHECK-NEXT: entry: 292; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 293; CHECK: bb1: 294; CHECK-NEXT: [[R:%.*]] = and i64 [[A:%.*]], 255 295; CHECK-NEXT: br label [[BB4:%.*]] 296; CHECK: bb2: 297; CHECK-NEXT: br i1 [[C2:%.*]], label [[BB3:%.*]], label [[BB4]] 298; CHECK: bb3: 299; CHECK-NEXT: br label [[BB4]] 300; CHECK: bb4: 301; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[R]], [[BB1]] ], [ undef, [[BB2]] ], [ 10, [[BB3]] ] 302; CHECK-NEXT: [[RES:%.*]] = and i64 [[P]], 255 303; CHECK-NEXT: br label [[EXIT:%.*]] 304; CHECK: exit: 305; CHECK-NEXT: call void @use(i1 false) 306; CHECK-NEXT: call void @use(i1 true) 307; CHECK-NEXT: ret i64 [[RES]] 308; 309entry: 310 br i1 %c1, label %bb1, label %bb2 311 312bb1: 313 %r = and i64 %a, 255 314 br label %bb4 315 316bb2: 317 br i1 %c2, label %bb3, label %bb4 318 319bb3: 320 br label %bb4 321 322bb4: 323 %p = phi i64 [ %r, %bb1 ], [ undef, %bb2], [ 10, %bb3 ] 324 %res = and i64 %p, 255 325 br label %exit 326 327exit: ; CVP only simplifies based on ranges for non-local conditions. 328 %f.1 = icmp eq i64 %p, 256 329 call void @use(i1 %f.1) 330 %t.1 = icmp ne i64 %p, 256 331 call void @use(i1 %t.1) 332 ret i64 %res 333} 334 335define i64 @constant_range_and_phi_constant_undef(i1 %c1, i1 %c2, i64 %a) { 336; CHECK-LABEL: @constant_range_and_phi_constant_undef( 337; CHECK-NEXT: entry: 338; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 339; CHECK: bb1: 340; CHECK-NEXT: [[R:%.*]] = and i64 [[A:%.*]], 255 341; CHECK-NEXT: br label [[BB5:%.*]] 342; CHECK: bb2: 343; CHECK-NEXT: br i1 [[C2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]] 344; CHECK: bb3: 345; CHECK-NEXT: br label [[BB4]] 346; CHECK: bb4: 347; CHECK-NEXT: br label [[BB5]] 348; CHECK: bb5: 349; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[R]], [[BB1]] ], [ 10, [[BB4]] ] 350; CHECK-NEXT: br label [[EXIT:%.*]] 351; CHECK: exit: 352; CHECK-NEXT: call void @use(i1 false) 353; CHECK-NEXT: call void @use(i1 true) 354; CHECK-NEXT: ret i64 [[P]] 355; 356entry: 357 br i1 %c1, label %bb1, label %bb2 358 359bb1: 360 %r = and i64 %a, 255 361 br label %bb5 362 363bb2: 364 br i1 %c2, label %bb3, label %bb4 365 366bb3: 367 br label %bb4 368 369bb4: 370 %p.1 = phi i64 [ 10, %bb2 ], [ undef, %bb3] 371 br label %bb5 372 373bb5: 374 %p = phi i64 [ %r, %bb1 ], [ %p.1, %bb4] 375 %res = and i64 %p, 255 376 br label %exit 377 378exit: ; CVP only simplifies based on ranges for non-local conditions. 379 %f.1 = icmp eq i64 %p, 256 380 call void @use(i1 %f.1) 381 %t.1 = icmp ne i64 %p, 256 382 call void @use(i1 %t.1) 383 ret i64 %res 384} 385