1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=sroa -S | FileCheck %s 3 4declare void @callee(ptr nocapture readonly %p) 5 6define i32 @simple() { 7; CHECK-LABEL: @simple( 8; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 9; CHECK-NEXT: store i32 0, ptr [[A]], align 4 10; CHECK-NEXT: call void @callee(ptr [[A]]) 11; CHECK-NEXT: ret i32 0 12; 13 %a = alloca i32 14 store i32 0, ptr %a 15 call void @callee(ptr %a) 16 %l1 = load i32, ptr %a 17 ret i32 %l1 18} 19 20define i32 @smallbig() { 21; CHECK-LABEL: @smallbig( 22; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 23; CHECK-NEXT: store i8 0, ptr [[A]], align 1 24; CHECK-NEXT: call void @callee(ptr [[A]]) 25; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4 26; CHECK-NEXT: ret i32 [[L1]] 27; 28 %a = alloca i32 29 store i8 0, ptr %a 30 call void @callee(ptr %a) 31 %l1 = load i32, ptr %a 32 ret i32 %l1 33} 34 35define i32 @twoalloc() { 36; CHECK-LABEL: @twoalloc( 37; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8 38; CHECK-NEXT: store i32 0, ptr [[A]], align 4 39; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 40; CHECK-NEXT: store i32 1, ptr [[B]], align 4 41; CHECK-NEXT: call void @callee(ptr [[A]]) 42; CHECK-NEXT: [[R:%.*]] = add i32 0, 1 43; CHECK-NEXT: ret i32 [[R]] 44; 45 %a = alloca {i32, i32} 46 store i32 0, ptr %a 47 %b = getelementptr i32, ptr %a, i32 1 48 store i32 1, ptr %b 49 call void @callee(ptr %a) 50 %l1 = load i32, ptr %a 51 %l2 = load i32, ptr %b 52 %r = add i32 %l1, %l2 53 ret i32 %r 54} 55 56define i32 @twostore() { 57; CHECK-LABEL: @twostore( 58; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 59; CHECK-NEXT: store i32 1, ptr [[A]], align 4 60; CHECK-NEXT: call void @callee(ptr [[A]]) 61; CHECK-NEXT: store i32 2, ptr [[A]], align 4 62; CHECK-NEXT: ret i32 2 63; 64 %a = alloca i32 65 store i32 1, ptr %a 66 call void @callee(ptr %a) 67 store i32 2, ptr %a 68 %l = load i32, ptr %a 69 ret i32 %l 70} 71 72define float @differenttype() { 73; CHECK-LABEL: @differenttype( 74; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8 75; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 76; CHECK-NEXT: store i32 1, ptr [[B]], align 4 77; CHECK-NEXT: call void @callee(ptr [[A]]) 78; CHECK-NEXT: [[L2:%.*]] = load float, ptr [[B]], align 4 79; CHECK-NEXT: ret float [[L2]] 80; 81 %a = alloca {i32, i32} 82 %b = getelementptr i32, ptr %a, i32 1 83 store i32 1, ptr %b 84 call void @callee(ptr %a) 85 %l2 = load float, ptr %b 86 ret float %l2 87} 88 89define i32 @twoalloc_store64(i64 %x) { 90; CHECK-LABEL: @twoalloc_store64( 91; CHECK-NEXT: [[A:%.*]] = alloca i64, align 8 92; CHECK-NEXT: store i64 [[X:%.*]], ptr [[A]], align 4 93; CHECK-NEXT: call void @callee(ptr [[A]]) 94; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4 95; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 96; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4 97; CHECK-NEXT: ret i32 [[L2]] 98; 99 %a = alloca i64 100 store i64 %x, ptr %a 101 call void @callee(ptr %a) 102 %l1 = load i32, ptr %a 103 %b = getelementptr i32, ptr %a, i32 1 104 %l2 = load i32, ptr %b 105 ret i32 %l2 106} 107 108define i32 @twocalls() { 109; CHECK-LABEL: @twocalls( 110; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8 111; CHECK-NEXT: store i32 0, ptr [[A]], align 4 112; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 113; CHECK-NEXT: store i32 1, ptr [[B]], align 4 114; CHECK-NEXT: call void @callee(ptr [[A]]) 115; CHECK-NEXT: call void @callee(ptr [[A]]) 116; CHECK-NEXT: [[R:%.*]] = add i32 0, 1 117; CHECK-NEXT: ret i32 [[R]] 118; 119 %a = alloca {i32, i32} 120 store i32 0, ptr %a 121 %b = getelementptr i32, ptr %a, i32 1 122 store i32 1, ptr %b 123 call void @callee(ptr %a) 124 %l1 = load i32, ptr %a 125 call void @callee(ptr %a) 126 %l2 = load i32, ptr %b 127 %r = add i32 %l1, %l2 128 ret i32 %r 129} 130 131define i32 @volatile() { 132; CHECK-LABEL: @volatile( 133; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8 134; CHECK-NEXT: store i32 0, ptr [[A]], align 4 135; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 136; CHECK-NEXT: store volatile i32 1, ptr [[B]], align 4 137; CHECK-NEXT: call void @callee(ptr [[A]]) 138; CHECK-NEXT: [[L1:%.*]] = load volatile i32, ptr [[A]], align 4 139; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4 140; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]] 141; CHECK-NEXT: ret i32 [[R]] 142; 143 %a = alloca {i32, i32} 144 store i32 0, ptr %a 145 %b = getelementptr i32, ptr %a, i32 1 146 store volatile i32 1, ptr %b 147 call void @callee(ptr %a) 148 %l1 = load volatile i32, ptr %a 149 %l2 = load i32, ptr %b 150 %r = add i32 %l1, %l2 151 ret i32 %r 152} 153 154define i32 @atomic() { 155; CHECK-LABEL: @atomic( 156; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8 157; CHECK-NEXT: store i32 0, ptr [[A]], align 4 158; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 159; CHECK-NEXT: store i32 1, ptr [[B]], align 4 160; CHECK-NEXT: call void @callee(ptr [[A]]) 161; CHECK-NEXT: [[L1:%.*]] = load atomic i32, ptr [[A]] seq_cst, align 4 162; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], 1 163; CHECK-NEXT: ret i32 [[R]] 164; 165 %a = alloca {i32, i32} 166 store i32 0, ptr %a 167 %b = getelementptr i32, ptr %a, i32 1 168 store i32 1, ptr %b 169 call void @callee(ptr %a) 170 %l1 = load atomic i32, ptr %a seq_cst, align 4 171 %l2 = load i32, ptr %b 172 %r = add i32 %l1, %l2 173 ret i32 %r 174} 175 176define i32 @notdominating() { 177; CHECK-LABEL: @notdominating( 178; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8 179; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 180; CHECK-NEXT: store i32 0, ptr [[A]], align 4 181; CHECK-NEXT: store i32 1, ptr [[B]], align 4 182; CHECK-NEXT: call void @callee(ptr [[A]]) 183; CHECK-NEXT: [[R:%.*]] = add i32 undef, undef 184; CHECK-NEXT: ret i32 [[R]] 185; 186 %a = alloca {i32, i32} 187 %b = getelementptr i32, ptr %a, i32 1 188 %l1 = load i32, ptr %a 189 %l2 = load i32, ptr %b 190 store i32 0, ptr %a 191 store i32 1, ptr %b 192 call void @callee(ptr %a) 193 %r = add i32 %l1, %l2 194 ret i32 %r 195} 196 197declare void @callee_notreadonly(ptr %p) 198define i32 @notreadonly() { 199; CHECK-LABEL: @notreadonly( 200; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8 201; CHECK-NEXT: store i32 0, ptr [[A]], align 4 202; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 203; CHECK-NEXT: store i32 1, ptr [[B]], align 4 204; CHECK-NEXT: call void @callee_notreadonly(ptr [[A]]) 205; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4 206; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4 207; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]] 208; CHECK-NEXT: ret i32 [[R]] 209; 210 %a = alloca {i32, i32} 211 store i32 0, ptr %a 212 %b = getelementptr i32, ptr %a, i32 1 213 store i32 1, ptr %b 214 call void @callee_notreadonly(ptr %a) 215 %l1 = load i32, ptr %a 216 %l2 = load i32, ptr %b 217 %r = add i32 %l1, %l2 218 ret i32 %r 219} 220 221declare void @callee_multiuse(ptr nocapture readonly %p, ptr nocapture readonly %q) 222define i32 @multiuse() { 223; CHECK-LABEL: @multiuse( 224; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8 225; CHECK-NEXT: store i32 0, ptr [[A]], align 4 226; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1 227; CHECK-NEXT: store i32 1, ptr [[B]], align 4 228; CHECK-NEXT: call void @callee_multiuse(ptr [[A]], ptr [[A]]) 229; CHECK-NEXT: [[R:%.*]] = add i32 0, 1 230; CHECK-NEXT: ret i32 [[R]] 231; 232 %a = alloca {i32, i32} 233 store i32 0, ptr %a 234 %b = getelementptr i32, ptr %a, i32 1 235 store i32 1, ptr %b 236 call void @callee_multiuse(ptr %a, ptr %a) 237 %l1 = load i32, ptr %a 238 %l2 = load i32, ptr %b 239 %r = add i32 %l1, %l2 240 ret i32 %r 241} 242 243define i32 @memcpyed(ptr %src) { 244; CHECK-LABEL: @memcpyed( 245; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 246; CHECK-NEXT: store i32 0, ptr [[A]], align 4 247; CHECK-NEXT: call void @callee(ptr [[A]]) 248; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[A]], ptr [[SRC:%.*]], i64 4, i1 false) 249; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4 250; CHECK-NEXT: ret i32 [[L1]] 251; 252 %a = alloca i32 253 store i32 0, ptr %a 254 call void @callee(ptr %a) 255 call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %src, i64 4, i1 false) 256 %l1 = load i32, ptr %a 257 ret i32 %l1 258} 259 260define ptr @memcpyedsplit(ptr %src) { 261; CHECK-LABEL: @memcpyedsplit( 262; CHECK-NEXT: [[A:%.*]] = alloca { i64, i64 }, align 8 263; CHECK-NEXT: store i8 1, ptr [[A]], align 1 264; CHECK-NEXT: [[B:%.*]] = getelementptr i64, ptr [[A]], i32 1 265; CHECK-NEXT: store ptr null, ptr [[B]], align 8 266; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[A]], ptr [[SRC:%.*]], i64 16, i1 false) 267; CHECK-NEXT: call void @callee(ptr [[A]]) 268; CHECK-NEXT: [[L1:%.*]] = load ptr, ptr [[B]], align 8 269; CHECK-NEXT: ret ptr [[L1]] 270; 271 %a = alloca { i64, i64 } 272 store i8 1, ptr %a 273 %b = getelementptr i64, ptr %a, i32 1 274 store ptr null, ptr %b 275 call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %src, i64 16, i1 false) 276 call void @callee(ptr %a) 277 %l1 = load ptr, ptr %b 278 ret ptr %l1 279} 280 281; This struct contains padding bits. The load should not be replaced by poison. 282%struct.LoadImmediateInfo = type { i32 } 283define void @incompletestruct(i1 %b, i1 %c) { 284; CHECK-LABEL: @incompletestruct( 285; CHECK-NEXT: entry: 286; CHECK-NEXT: [[LII:%.*]] = alloca [[STRUCT_LOADIMMEDIATEINFO:%.*]], align 4 287; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[LII]]) 288; CHECK-NEXT: [[BF_CLEAR4:%.*]] = and i32 undef, -262144 289; CHECK-NEXT: [[BF_SET5:%.*]] = select i1 [[B:%.*]], i32 196608, i32 131072 290; CHECK-NEXT: [[BF_SET12:%.*]] = or disjoint i32 [[BF_SET5]], [[BF_CLEAR4]] 291; CHECK-NEXT: store i32 [[BF_SET12]], ptr [[LII]], align 4 292; CHECK-NEXT: call void @callee(ptr [[LII]]) 293; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[LII]]) 294; CHECK-NEXT: ret void 295; 296entry: 297 %LII = alloca %struct.LoadImmediateInfo, align 4 298 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %LII) 299 %bf.load = load i32, ptr %LII, align 4 300 %bf.clear4 = and i32 %bf.load, -262144 301 %bf.set5 = select i1 %b, i32 196608, i32 131072 302 %bf.set12 = or disjoint i32 %bf.set5, %bf.clear4 303 store i32 %bf.set12, ptr %LII, align 4 304 call void @callee(ptr %LII) 305 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %LII) 306 ret void 307} 308 309define void @incompletestruct_bb(i1 %b, i1 %c) { 310; CHECK-LABEL: @incompletestruct_bb( 311; CHECK-NEXT: entry: 312; CHECK-NEXT: [[LII:%.*]] = alloca [[STRUCT_LOADIMMEDIATEINFO:%.*]], align 4 313; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 314; CHECK: if.then: 315; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[LII]]) 316; CHECK-NEXT: [[BF_CLEAR4:%.*]] = and i32 undef, -262144 317; CHECK-NEXT: [[BF_SET5:%.*]] = select i1 [[B:%.*]], i32 196608, i32 131072 318; CHECK-NEXT: [[BF_SET12:%.*]] = or disjoint i32 [[BF_SET5]], [[BF_CLEAR4]] 319; CHECK-NEXT: store i32 [[BF_SET12]], ptr [[LII]], align 4 320; CHECK-NEXT: call void @callee(ptr [[LII]]) 321; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[LII]]) 322; CHECK-NEXT: br label [[IF_END]] 323; CHECK: if.end: 324; CHECK-NEXT: ret void 325; 326entry: 327 %LII = alloca %struct.LoadImmediateInfo, align 4 328 br i1 %c, label %if.then, label %if.end 329 330if.then: ; preds = %entry 331 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %LII) 332 %bf.load = load i32, ptr %LII, align 4 333 %bf.clear4 = and i32 %bf.load, -262144 334 %bf.set5 = select i1 %b, i32 196608, i32 131072 335 %bf.set12 = or disjoint i32 %bf.set5, %bf.clear4 336 store i32 %bf.set12, ptr %LII, align 4 337 call void @callee(ptr %LII) 338 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %LII) 339 br label %if.end 340 341if.end: ; preds = %if.then, %entry 342 ret void 343} 344 345define i32 @sixteenload() { 346; CHECK-LABEL: @sixteenload( 347; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 348; CHECK-NEXT: store i32 0, ptr [[A]], align 4 349; CHECK-NEXT: call void @callee(ptr [[A]]) 350; CHECK-NEXT: [[A1:%.*]] = add i32 0, 0 351; CHECK-NEXT: [[A2:%.*]] = add i32 [[A1]], 0 352; CHECK-NEXT: ret i32 [[A2]] 353; 354 %a = alloca i32 355 store i32 0, ptr %a 356 call void @callee(ptr %a) 357 %l1 = load i32, ptr %a 358 %l2 = load i32, ptr %a 359 %l3 = load i32, ptr %a 360 %l4 = load i32, ptr %a 361 %l5 = load i32, ptr %a 362 %l6 = load i32, ptr %a 363 %l7 = load i32, ptr %a 364 %l8 = load i32, ptr %a 365 %l9 = load i32, ptr %a 366 %l10 = load i32, ptr %a 367 %l11 = load i32, ptr %a 368 %l12 = load i32, ptr %a 369 %l13 = load i32, ptr %a 370 %l14 = load i32, ptr %a 371 %l15 = load i32, ptr %a 372 %l16 = load i32, ptr %a 373 %a1 = add i32 %l1, %l2 374 %a2 = add i32 %a1, %l3 375 ret i32 %a2 376} 377 378define i32 @testcallalloca() { 379; CHECK-LABEL: @testcallalloca( 380; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 381; CHECK-NEXT: store i32 0, ptr [[A]], align 4 382; CHECK-NEXT: call void [[A]]() 383; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4 384; CHECK-NEXT: ret i32 [[L1]] 385; 386 %a = alloca i32 387 store i32 0, ptr %a 388 call void %a() 389 %l1 = load i32, ptr %a 390 ret i32 %l1 391} 392 393declare void @callee_byval(ptr byval(i32) %p) 394 395define i32 @simple_byval() { 396; CHECK-LABEL: @simple_byval( 397; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 398; CHECK-NEXT: store i32 0, ptr [[A]], align 4 399; CHECK-NEXT: call void @callee_byval(ptr [[A]]) 400; CHECK-NEXT: ret i32 0 401; 402 %a = alloca i32 403 store i32 0, ptr %a 404 call void @callee_byval(ptr %a) 405 %l1 = load i32, ptr %a 406 ret i32 %l1 407} 408 409declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1) 410