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