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