1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine,verify -S < %s | FileCheck %s --check-prefixes=ALL,INSTCOMBINE 3 4; Make sure GVN won't undo the transformation: 5; RUN: opt -passes=instcombine,gvn -S < %s | FileCheck %s --check-prefixes=ALL,INSTCOMBINEGVN 6 7declare ptr @get_ptr.i8() 8declare ptr @get_ptr.i32() 9declare void @foo.i8(ptr) 10declare void @foo.i32(ptr) 11 12define i32 @test_gep_and_bitcast(i1 %cond, i1 %cond2) { 13; ALL-LABEL: @test_gep_and_bitcast( 14; ALL-NEXT: entry: 15; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 16; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 17; ALL: bb1: 18; ALL-NEXT: br label [[EXIT:%.*]] 19; ALL: bb2: 20; ALL-NEXT: br label [[EXIT]] 21; ALL: exit: 22; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 23; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4 24; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 25; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 26; ALL-NEXT: ret i32 [[RES]] 27; 28entry: 29 %obj = call ptr @get_ptr.i8() 30 br i1 %cond, label %bb1, label %bb2 31 32bb1: 33 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 34 %res1 = load i32, ptr %ptr1 35 br label %exit 36 37bb2: 38 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 39 %res2 = load i32, ptr %ptr2 40 br label %exit 41 42exit: 43 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ] 44 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] 45 store i32 1, ptr %ptr.typed 46 %res.load = load i32, ptr %ptr.typed 47 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 48 ret i32 %res 49} 50 51define i32 @test_gep_and_bitcast_arg(ptr %obj, i1 %cond, i1 %cond2) { 52; ALL-LABEL: @test_gep_and_bitcast_arg( 53; ALL-NEXT: entry: 54; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 55; ALL: bb1: 56; ALL-NEXT: br label [[EXIT:%.*]] 57; ALL: bb2: 58; ALL-NEXT: br label [[EXIT]] 59; ALL: exit: 60; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ:%.*]], i64 16 61; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4 62; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 63; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 64; ALL-NEXT: ret i32 [[RES]] 65; 66entry: 67 br i1 %cond, label %bb1, label %bb2 68 69bb1: 70 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 71 %res1 = load i32, ptr %ptr1 72 br label %exit 73 74bb2: 75 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 76 %res2 = load i32, ptr %ptr2 77 br label %exit 78 79exit: 80 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ] 81 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] 82 store i32 1, ptr %ptr.typed 83 %res.load = load i32, ptr %ptr.typed 84 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 85 ret i32 %res 86} 87 88define i32 @test_gep_and_bitcast_phi(i1 %cond, i1 %cond2, i1 %cond3) { 89; ALL-LABEL: @test_gep_and_bitcast_phi( 90; ALL-NEXT: entry: 91; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 92; ALL: bb1: 93; ALL-NEXT: [[OBJ1:%.*]] = call ptr @get_ptr.i8() 94; ALL-NEXT: br label [[MERGE:%.*]] 95; ALL: bb2: 96; ALL-NEXT: [[OBJ2_TYPED:%.*]] = call ptr @get_ptr.i32() 97; ALL-NEXT: br label [[MERGE]] 98; ALL: merge: 99; ALL-NEXT: [[OBJ:%.*]] = phi ptr [ [[OBJ1]], [[BB1]] ], [ [[OBJ2_TYPED]], [[BB2]] ] 100; ALL-NEXT: [[ANOTHER_PHI:%.*]] = phi ptr [ [[OBJ1]], [[BB1]] ], [ null, [[BB2]] ] 101; ALL-NEXT: call void @foo.i8(ptr [[ANOTHER_PHI]]) 102; ALL-NEXT: br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]] 103; ALL: bb3: 104; ALL-NEXT: br label [[EXIT:%.*]] 105; ALL: bb4: 106; ALL-NEXT: br label [[EXIT]] 107; ALL: exit: 108; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 109; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4 110; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 111; ALL-NEXT: [[RES:%.*]] = select i1 [[COND3:%.*]], i32 [[RES_PHI]], i32 1 112; ALL-NEXT: ret i32 [[RES]] 113; 114entry: 115 br i1 %cond, label %bb1, label %bb2 116 117bb1: 118 %obj1 = call ptr @get_ptr.i8() 119 br label %merge 120 121bb2: 122 %obj2.typed = call ptr @get_ptr.i32() 123 br label %merge 124 125merge: 126 %obj = phi ptr [ %obj1, %bb1 ], [ %obj2.typed, %bb2 ] 127 %another_phi = phi ptr [ %obj1, %bb1 ], [ null, %bb2 ] 128 call void @foo.i8(ptr %another_phi) 129 br i1 %cond2, label %bb3, label %bb4 130 131bb3: 132 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 133 %res1 = load i32, ptr %ptr1 134 br label %exit 135 136bb4: 137 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 138 %res2 = load i32, ptr %ptr2 139 br label %exit 140 141exit: 142 %ptr.typed = phi ptr [ %ptr1, %bb3 ], [ %ptr2, %bb4 ] 143 %res.phi = phi i32 [ %res1, %bb3 ], [ %res2, %bb4 ] 144 store i32 1, ptr %ptr.typed 145 %res.load = load i32, ptr %ptr.typed 146 %res = select i1 %cond3, i32 %res.phi, i32 %res.load 147 ret i32 %res 148} 149 150define i32 @test_gep_i32ptr(i1 %cond, i1 %cond2) { 151; ALL-LABEL: @test_gep_i32ptr( 152; ALL-NEXT: entry: 153; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i32() 154; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 155; ALL: bb1: 156; ALL-NEXT: br label [[EXIT:%.*]] 157; ALL: bb2: 158; ALL-NEXT: br label [[EXIT]] 159; ALL: exit: 160; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 64 161; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4 162; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 163; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 164; ALL-NEXT: ret i32 [[RES]] 165; 166entry: 167 %obj = call ptr @get_ptr.i32() 168 br i1 %cond, label %bb1, label %bb2 169 170bb1: 171 %ptr1.typed = getelementptr inbounds i32, ptr %obj, i64 16 172 %res1 = load i32, ptr %ptr1.typed 173 br label %exit 174 175bb2: 176 %ptr2.typed = getelementptr inbounds i32, ptr %obj, i64 16 177 %res2 = load i32, ptr %ptr2.typed 178 br label %exit 179 180exit: 181 %ptr.typed = phi ptr [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ] 182 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] 183 store i32 1, ptr %ptr.typed 184 %res.load = load i32, ptr %ptr.typed 185 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 186 ret i32 %res 187} 188 189define i32 @test_gep_and_bitcast_gep_base_ptr(i1 %cond, i1 %cond2) { 190; ALL-LABEL: @test_gep_and_bitcast_gep_base_ptr( 191; ALL-NEXT: entry: 192; ALL-NEXT: [[OBJ0:%.*]] = call ptr @get_ptr.i8() 193; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 194; ALL: bb1: 195; ALL-NEXT: br label [[EXIT:%.*]] 196; ALL: bb2: 197; ALL-NEXT: br label [[EXIT]] 198; ALL: exit: 199; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ0]], i64 32 200; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4 201; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 202; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 203; ALL-NEXT: ret i32 [[RES]] 204; 205entry: 206 %obj0 = call ptr @get_ptr.i8() 207 %obj = getelementptr inbounds i8, ptr %obj0, i64 16 208 br i1 %cond, label %bb1, label %bb2 209 210bb1: 211 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 212 %res1 = load i32, ptr %ptr1 213 br label %exit 214 215bb2: 216 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 217 %res2 = load i32, ptr %ptr2 218 br label %exit 219 220exit: 221 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ] 222 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] 223 store i32 1, ptr %ptr.typed 224 %res.load = load i32, ptr %ptr.typed 225 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 226 ret i32 %res 227} 228 229define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) { 230; ALL-LABEL: @test_gep_and_bitcast_same_bb( 231; ALL-NEXT: entry: 232; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 233; ALL-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] 234; ALL: bb2: 235; ALL-NEXT: br label [[EXIT]] 236; ALL: exit: 237; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 238; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4 239; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 240; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 241; ALL-NEXT: ret i32 [[RES]] 242; 243entry: 244 %obj = call ptr @get_ptr.i8() 245 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 246 %res1 = load i32, ptr %ptr1 247 br i1 %cond, label %exit, label %bb2 248 249bb2: 250 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 251 %res2 = load i32, ptr %ptr2 252 br label %exit 253 254exit: 255 %ptr.typed = phi ptr [ %ptr1, %entry ], [ %ptr2, %bb2 ] 256 %res.phi = phi i32 [ %res1, %entry ], [ %res2, %bb2 ] 257 store i32 1, ptr %ptr.typed 258 %res.load = load i32, ptr %ptr.typed 259 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 260 ret i32 %res 261} 262 263define i32 @test_gep_and_bitcast_same_bb_and_extra_use(i1 %cond, i1 %cond2) { 264; INSTCOMBINE-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use( 265; INSTCOMBINE-NEXT: entry: 266; INSTCOMBINE-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 267; INSTCOMBINE-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 268; INSTCOMBINE-NEXT: call void @foo.i32(ptr nonnull [[PTR1]]) 269; INSTCOMBINE-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] 270; INSTCOMBINE: bb2: 271; INSTCOMBINE-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 272; INSTCOMBINE-NEXT: br label [[EXIT]] 273; INSTCOMBINE: exit: 274; INSTCOMBINE-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[ENTRY:%.*]] ], [ [[PTR2]], [[BB2]] ] 275; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4 276; INSTCOMBINE-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 277; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 278; INSTCOMBINE-NEXT: ret i32 [[RES]] 279; 280; INSTCOMBINEGVN-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use( 281; INSTCOMBINEGVN-NEXT: entry: 282; INSTCOMBINEGVN-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 283; INSTCOMBINEGVN-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 284; INSTCOMBINEGVN-NEXT: call void @foo.i32(ptr nonnull [[PTR1]]) 285; INSTCOMBINEGVN-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]] 286; INSTCOMBINEGVN: bb2: 287; INSTCOMBINEGVN-NEXT: br label [[EXIT]] 288; INSTCOMBINEGVN: exit: 289; INSTCOMBINEGVN-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR1]], align 4 290; INSTCOMBINEGVN-NEXT: store i32 1, ptr [[PTR1]], align 4 291; INSTCOMBINEGVN-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 292; INSTCOMBINEGVN-NEXT: ret i32 [[RES]] 293; 294entry: 295 %obj = call ptr @get_ptr.i8() 296 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 297 call void @foo.i32(ptr %ptr1) 298 %res1 = load i32, ptr %ptr1 299 br i1 %cond, label %exit, label %bb2 300 301bb2: 302 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 303 %res2 = load i32, ptr %ptr2 304 br label %exit 305 306exit: 307 %ptr.typed = phi ptr [ %ptr1, %entry ], [ %ptr2, %bb2 ] 308 %res.phi = phi i32 [ %res1, %entry ], [ %res2, %bb2 ] 309 store i32 1, ptr %ptr.typed 310 %res.load = load i32, ptr %ptr.typed 311 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 312 ret i32 %res 313} 314 315define i8 @test_gep(i1 %cond, i1 %cond2) { 316; ALL-LABEL: @test_gep( 317; ALL-NEXT: entry: 318; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 319; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 320; ALL: bb1: 321; ALL-NEXT: br label [[EXIT:%.*]] 322; ALL: bb2: 323; ALL-NEXT: br label [[EXIT]] 324; ALL: exit: 325; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 326; ALL-NEXT: [[RES_PHI:%.*]] = load i8, ptr [[PTR_TYPED]], align 1 327; ALL-NEXT: store i8 1, ptr [[PTR_TYPED]], align 1 328; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1 329; ALL-NEXT: ret i8 [[RES]] 330; 331entry: 332 %obj = call ptr @get_ptr.i8() 333 br i1 %cond, label %bb1, label %bb2 334 335bb1: 336 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 337 %res1 = load i8, ptr %ptr1 338 br label %exit 339 340bb2: 341 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 342 %res2 = load i8, ptr %ptr2 343 br label %exit 344 345exit: 346 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ] 347 %res.phi = phi i8 [ %res1, %bb1 ], [ %res2, %bb2 ] 348 store i8 1, ptr %ptr.typed 349 %res.load = load i8, ptr %ptr.typed 350 %res = select i1 %cond2, i8 %res.phi, i8 %res.load 351 ret i8 %res 352} 353 354define i32 @test_extra_uses(i1 %cond, i1 %cond2) { 355; ALL-LABEL: @test_extra_uses( 356; ALL-NEXT: entry: 357; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 358; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 359; ALL: bb1: 360; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 361; ALL-NEXT: [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4 362; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR1]]) 363; ALL-NEXT: br label [[EXIT:%.*]] 364; ALL: bb2: 365; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 366; ALL-NEXT: [[RES2:%.*]] = load i32, ptr [[PTR2]], align 4 367; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR2]]) 368; ALL-NEXT: br label [[EXIT]] 369; ALL: exit: 370; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ] 371; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] 372; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 373; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 374; ALL-NEXT: ret i32 [[RES]] 375; 376entry: 377 %obj = call ptr @get_ptr.i8() 378 br i1 %cond, label %bb1, label %bb2 379 380bb1: 381 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 382 %res1 = load i32, ptr %ptr1 383 call void @foo.i32(ptr %ptr1) 384 br label %exit 385 386bb2: 387 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 388 %res2 = load i32, ptr %ptr2 389 call void @foo.i32(ptr %ptr2) 390 br label %exit 391 392exit: 393 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ] 394 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] 395 store i32 1, ptr %ptr.typed 396 %res.load = load i32, ptr %ptr.typed 397 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 398 ret i32 %res 399} 400 401define i32 @test_extra_uses_non_inbounds(i1 %cond, i1 %cond2) { 402; ALL-LABEL: @test_extra_uses_non_inbounds( 403; ALL-NEXT: entry: 404; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 405; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 406; ALL: bb1: 407; ALL-NEXT: [[PTR1:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16 408; ALL-NEXT: [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4 409; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR1]]) 410; ALL-NEXT: br label [[EXIT:%.*]] 411; ALL: bb2: 412; ALL-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16 413; ALL-NEXT: [[RES2:%.*]] = load i32, ptr [[PTR2]], align 4 414; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR2]]) 415; ALL-NEXT: br label [[EXIT]] 416; ALL: exit: 417; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ] 418; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] 419; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 420; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 421; ALL-NEXT: ret i32 [[RES]] 422; 423entry: 424 %obj = call ptr @get_ptr.i8() 425 br i1 %cond, label %bb1, label %bb2 426 427bb1: 428 %ptr1 = getelementptr i8, ptr %obj, i64 16 429 %res1 = load i32, ptr %ptr1 430 call void @foo.i32(ptr %ptr1) 431 br label %exit 432 433bb2: 434 %ptr2 = getelementptr i8, ptr %obj, i64 16 435 %res2 = load i32, ptr %ptr2 436 call void @foo.i32(ptr %ptr2) 437 br label %exit 438 439exit: 440 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ] 441 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] 442 store i32 1, ptr %ptr.typed 443 %res.load = load i32, ptr %ptr.typed 444 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 445 ret i32 %res 446} 447 448define i32 @test_extra_uses_multiple_geps(i1 %cond, i1 %cond2) { 449; ALL-LABEL: @test_extra_uses_multiple_geps( 450; ALL-NEXT: entry: 451; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 452; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 453; ALL: bb1: 454; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 455; ALL-NEXT: [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4 456; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR1]]) 457; ALL-NEXT: br label [[EXIT:%.*]] 458; ALL: bb2: 459; ALL-NEXT: [[PTR2_1:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16 460; ALL-NEXT: [[RES2:%.*]] = load i32, ptr [[PTR2_1]], align 4 461; ALL-NEXT: call void @foo.i32(ptr nonnull [[PTR2_1]]) 462; ALL-NEXT: br label [[EXIT]] 463; ALL: exit: 464; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2_1]], [[BB2]] ] 465; ALL-NEXT: [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] 466; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4 467; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1 468; ALL-NEXT: ret i32 [[RES]] 469; 470entry: 471 %obj = call ptr @get_ptr.i8() 472 br i1 %cond, label %bb1, label %bb2 473 474bb1: 475 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 476 %res1 = load i32, ptr %ptr1 477 call void @foo.i32(ptr %ptr1) 478 br label %exit 479 480bb2: 481 %ptr2.0 = getelementptr i8, ptr %obj, i64 8 482 %ptr2.1 = getelementptr inbounds i8, ptr %ptr2.0, i64 8 483 %res2 = load i32, ptr %ptr2.1 484 call void @foo.i32(ptr %ptr2.1) 485 br label %exit 486 487exit: 488 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2.1, %bb2 ] 489 %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ] 490 store i32 1, ptr %ptr.typed 491 %res.load = load i32, ptr %ptr.typed 492 %res = select i1 %cond2, i32 %res.phi, i32 %res.load 493 ret i32 %res 494} 495 496define i8 @test_gep_extra_uses(i1 %cond, i1 %cond2) { 497; ALL-LABEL: @test_gep_extra_uses( 498; ALL-NEXT: entry: 499; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8() 500; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 501; ALL: bb1: 502; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 503; ALL-NEXT: [[RES1:%.*]] = load i8, ptr [[PTR1]], align 1 504; ALL-NEXT: call void @foo.i8(ptr nonnull [[PTR1]]) 505; ALL-NEXT: br label [[EXIT:%.*]] 506; ALL: bb2: 507; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[OBJ]], i64 16 508; ALL-NEXT: [[RES2:%.*]] = load i8, ptr [[PTR2]], align 1 509; ALL-NEXT: call void @foo.i8(ptr nonnull [[PTR2]]) 510; ALL-NEXT: br label [[EXIT]] 511; ALL: exit: 512; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ] 513; ALL-NEXT: [[RES_PHI:%.*]] = phi i8 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] 514; ALL-NEXT: store i8 1, ptr [[PTR_TYPED]], align 1 515; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1 516; ALL-NEXT: ret i8 [[RES]] 517; 518entry: 519 %obj = call ptr @get_ptr.i8() 520 br i1 %cond, label %bb1, label %bb2 521 522bb1: 523 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16 524 %res1 = load i8, ptr %ptr1 525 call void @foo.i8(ptr %ptr1) 526 br label %exit 527 528bb2: 529 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16 530 %res2 = load i8, ptr %ptr2 531 call void @foo.i8(ptr %ptr2) 532 br label %exit 533 534exit: 535 %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ] 536 %res.phi = phi i8 [ %res1, %bb1 ], [ %res2, %bb2 ] 537 store i8 1, ptr %ptr.typed 538 %res.load = load i8, ptr %ptr.typed 539 %res = select i1 %cond2, i8 %res.phi, i8 %res.load 540 ret i8 %res 541} 542 543; `swifterror` addresses are restricted to load and stores and call arguments. 544declare void @takeAddress(ptr swifterror) 545 546define ptr @test_dont_optimize_swifterror(i1 %cond, i1 %cond2, ptr %ptr) { 547; INSTCOMBINE-LABEL: @test_dont_optimize_swifterror( 548; INSTCOMBINE-NEXT: entry: 549; INSTCOMBINE-NEXT: [[OBJ:%.*]] = alloca swifterror ptr, align 8 550; INSTCOMBINE-NEXT: [[OBJ2:%.*]] = alloca swifterror ptr, align 8 551; INSTCOMBINE-NEXT: call void @takeAddress(ptr nonnull swifterror [[OBJ]]) 552; INSTCOMBINE-NEXT: call void @takeAddress(ptr nonnull swifterror [[OBJ2]]) 553; INSTCOMBINE-NEXT: store ptr [[PTR:%.*]], ptr [[OBJ]], align 8 554; INSTCOMBINE-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 555; INSTCOMBINE: bb1: 556; INSTCOMBINE-NEXT: [[RES1:%.*]] = load ptr, ptr [[OBJ]], align 8 557; INSTCOMBINE-NEXT: br label [[EXIT:%.*]] 558; INSTCOMBINE: bb2: 559; INSTCOMBINE-NEXT: [[RES2:%.*]] = load ptr, ptr [[OBJ2]], align 8 560; INSTCOMBINE-NEXT: br label [[EXIT]] 561; INSTCOMBINE: exit: 562; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = phi ptr [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ] 563; INSTCOMBINE-NEXT: store ptr null, ptr [[OBJ]], align 8 564; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], ptr [[RES_PHI]], ptr null 565; INSTCOMBINE-NEXT: ret ptr [[RES]] 566; 567; INSTCOMBINEGVN-LABEL: @test_dont_optimize_swifterror( 568; INSTCOMBINEGVN-NEXT: entry: 569; INSTCOMBINEGVN-NEXT: [[OBJ:%.*]] = alloca swifterror ptr, align 8 570; INSTCOMBINEGVN-NEXT: [[OBJ2:%.*]] = alloca swifterror ptr, align 8 571; INSTCOMBINEGVN-NEXT: call void @takeAddress(ptr nonnull swifterror [[OBJ]]) 572; INSTCOMBINEGVN-NEXT: call void @takeAddress(ptr nonnull swifterror [[OBJ2]]) 573; INSTCOMBINEGVN-NEXT: store ptr [[PTR:%.*]], ptr [[OBJ]], align 8 574; INSTCOMBINEGVN-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 575; INSTCOMBINEGVN: bb1: 576; INSTCOMBINEGVN-NEXT: br label [[EXIT:%.*]] 577; INSTCOMBINEGVN: bb2: 578; INSTCOMBINEGVN-NEXT: [[RES2:%.*]] = load ptr, ptr [[OBJ2]], align 8 579; INSTCOMBINEGVN-NEXT: br label [[EXIT]] 580; INSTCOMBINEGVN: exit: 581; INSTCOMBINEGVN-NEXT: [[RES_PHI:%.*]] = phi ptr [ [[PTR]], [[BB1]] ], [ [[RES2]], [[BB2]] ] 582; INSTCOMBINEGVN-NEXT: store ptr null, ptr [[OBJ]], align 8 583; INSTCOMBINEGVN-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], ptr [[RES_PHI]], ptr null 584; INSTCOMBINEGVN-NEXT: ret ptr [[RES]] 585; 586entry: 587 %obj = alloca swifterror ptr, align 8 588 %obj2 = alloca swifterror ptr, align 8 589 call void @takeAddress(ptr swifterror %obj) 590 call void @takeAddress(ptr swifterror %obj2) 591 store ptr %ptr, ptr %obj, align 8 592 br i1 %cond, label %bb1, label %bb2 593 594bb1: ; preds = %entry 595 %res1 = load ptr, ptr %obj, align 8 596 br label %exit 597 598bb2: ; preds = %entry 599 %res2 = load ptr, ptr %obj2, align 8 600 br label %exit 601 602exit: ; preds = %bb2, %bb1 603 %res.phi = phi ptr [ %res1, %bb1 ], [ %res2, %bb2 ] 604 store ptr null, ptr %obj, align 8 605 %res = select i1 %cond2, ptr %res.phi, ptr null 606 ret ptr %res 607} 608