brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.9 KiB · b6f7b1f Raw
587 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=sroa -S | FileCheck %s3 4declare void @callee(ptr nocapture readonly %p)5 6define i32 @simple() {7; CHECK-LABEL: @simple(8; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 49; CHECK-NEXT:    store i32 0, ptr [[A]], align 410; CHECK-NEXT:    call void @callee(ptr [[A]])11; CHECK-NEXT:    ret i32 012;13  %a = alloca i3214  store i32 0, ptr %a15  call void @callee(ptr %a)16  %l1 = load i32, ptr %a17  ret i32 %l118}19 20define i32 @smallbig() {21; CHECK-LABEL: @smallbig(22; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 423; CHECK-NEXT:    store i8 0, ptr [[A]], align 124; CHECK-NEXT:    call void @callee(ptr [[A]])25; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[A]], align 426; CHECK-NEXT:    ret i32 [[L1]]27;28  %a = alloca i3229  store i8 0, ptr %a30  call void @callee(ptr %a)31  %l1 = load i32, ptr %a32  ret i32 %l133}34 35define i32 @twoalloc() {36; CHECK-LABEL: @twoalloc(37; CHECK-NEXT:    [[A:%.*]] = alloca { i32, i32 }, align 838; CHECK-NEXT:    store i32 0, ptr [[A]], align 439; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 140; CHECK-NEXT:    store i32 1, ptr [[B]], align 441; CHECK-NEXT:    call void @callee(ptr [[A]])42; CHECK-NEXT:    [[R:%.*]] = add i32 0, 143; CHECK-NEXT:    ret i32 [[R]]44;45  %a = alloca {i32, i32}46  store i32 0, ptr %a47  %b = getelementptr i32, ptr %a, i32 148  store i32 1, ptr %b49  call void @callee(ptr %a)50  %l1 = load i32, ptr %a51  %l2 = load i32, ptr %b52  %r = add i32 %l1, %l253  ret i32 %r54}55 56define i32 @twostore() {57; CHECK-LABEL: @twostore(58; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 459; CHECK-NEXT:    store i32 1, ptr [[A]], align 460; CHECK-NEXT:    call void @callee(ptr [[A]])61; CHECK-NEXT:    store i32 2, ptr [[A]], align 462; CHECK-NEXT:    ret i32 263;64  %a = alloca i3265  store i32 1, ptr %a66  call void @callee(ptr %a)67  store i32 2, ptr %a68  %l = load i32, ptr %a69  ret i32 %l70}71 72define float @differenttype() {73; CHECK-LABEL: @differenttype(74; CHECK-NEXT:    [[A:%.*]] = alloca { i32, i32 }, align 875; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 176; CHECK-NEXT:    store i32 1, ptr [[B]], align 477; CHECK-NEXT:    call void @callee(ptr [[A]])78; CHECK-NEXT:    [[L2:%.*]] = load float, ptr [[B]], align 479; CHECK-NEXT:    ret float [[L2]]80;81  %a = alloca {i32, i32}82  %b = getelementptr i32, ptr %a, i32 183  store i32 1, ptr %b84  call void @callee(ptr %a)85  %l2 = load float, ptr %b86  ret float %l287}88 89define i32 @twoalloc_store64(i64 %x) {90; CHECK-LABEL: @twoalloc_store64(91; CHECK-NEXT:    [[A:%.*]] = alloca i64, align 892; CHECK-NEXT:    store i64 [[X:%.*]], ptr [[A]], align 493; CHECK-NEXT:    call void @callee(ptr [[A]])94; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[A]], align 495; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 196; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[B]], align 497; CHECK-NEXT:    ret i32 [[L2]]98;99  %a = alloca i64100  store i64 %x, ptr %a101  call void @callee(ptr %a)102  %l1 = load i32, ptr %a103  %b = getelementptr i32, ptr %a, i32 1104  %l2 = load i32, ptr %b105  ret i32 %l2106}107 108define i32 @twocalls() {109; CHECK-LABEL: @twocalls(110; CHECK-NEXT:    [[A:%.*]] = alloca { i32, i32 }, align 8111; CHECK-NEXT:    store i32 0, ptr [[A]], align 4112; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1113; CHECK-NEXT:    store i32 1, ptr [[B]], align 4114; CHECK-NEXT:    call void @callee(ptr [[A]])115; CHECK-NEXT:    call void @callee(ptr [[A]])116; CHECK-NEXT:    [[R:%.*]] = add i32 0, 1117; CHECK-NEXT:    ret i32 [[R]]118;119  %a = alloca {i32, i32}120  store i32 0, ptr %a121  %b = getelementptr i32, ptr %a, i32 1122  store i32 1, ptr %b123  call void @callee(ptr %a)124  %l1 = load i32, ptr %a125  call void @callee(ptr %a)126  %l2 = load i32, ptr %b127  %r = add i32 %l1, %l2128  ret i32 %r129}130 131define i32 @volatile() {132; CHECK-LABEL: @volatile(133; CHECK-NEXT:    [[A:%.*]] = alloca { i32, i32 }, align 8134; CHECK-NEXT:    store i32 0, ptr [[A]], align 4135; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1136; CHECK-NEXT:    store volatile i32 1, ptr [[B]], align 4137; CHECK-NEXT:    call void @callee(ptr [[A]])138; CHECK-NEXT:    [[L1:%.*]] = load volatile i32, ptr [[A]], align 4139; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[B]], align 4140; CHECK-NEXT:    [[R:%.*]] = add i32 [[L1]], [[L2]]141; CHECK-NEXT:    ret i32 [[R]]142;143  %a = alloca {i32, i32}144  store i32 0, ptr %a145  %b = getelementptr i32, ptr %a, i32 1146  store volatile i32 1, ptr %b147  call void @callee(ptr %a)148  %l1 = load volatile i32, ptr %a149  %l2 = load i32, ptr %b150  %r = add i32 %l1, %l2151  ret i32 %r152}153 154define i32 @atomic() {155; CHECK-LABEL: @atomic(156; CHECK-NEXT:    [[A:%.*]] = alloca { i32, i32 }, align 8157; CHECK-NEXT:    store i32 0, ptr [[A]], align 4158; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1159; CHECK-NEXT:    store i32 1, ptr [[B]], align 4160; CHECK-NEXT:    call void @callee(ptr [[A]])161; CHECK-NEXT:    [[L1:%.*]] = load atomic i32, ptr [[A]] seq_cst, align 4162; CHECK-NEXT:    [[R:%.*]] = add i32 [[L1]], 1163; CHECK-NEXT:    ret i32 [[R]]164;165  %a = alloca {i32, i32}166  store i32 0, ptr %a167  %b = getelementptr i32, ptr %a, i32 1168  store i32 1, ptr %b169  call void @callee(ptr %a)170  %l1 = load atomic i32, ptr %a seq_cst, align 4171  %l2 = load i32, ptr %b172  %r = add i32 %l1, %l2173  ret i32 %r174}175 176define i32 @notdominating() {177; CHECK-LABEL: @notdominating(178; CHECK-NEXT:    [[A:%.*]] = alloca { i32, i32 }, align 8179; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1180; CHECK-NEXT:    store i32 0, ptr [[A]], align 4181; CHECK-NEXT:    store i32 1, ptr [[B]], align 4182; CHECK-NEXT:    call void @callee(ptr [[A]])183; CHECK-NEXT:    [[R:%.*]] = add i32 undef, undef184; CHECK-NEXT:    ret i32 [[R]]185;186  %a = alloca {i32, i32}187  %b = getelementptr i32, ptr %a, i32 1188  %l1 = load i32, ptr %a189  %l2 = load i32, ptr %b190  store i32 0, ptr %a191  store i32 1, ptr %b192  call void @callee(ptr %a)193  %r = add i32 %l1, %l2194  ret i32 %r195}196 197declare void @callee_notreadonly(ptr %p)198define i32 @notreadonly() {199; CHECK-LABEL: @notreadonly(200; CHECK-NEXT:    [[A:%.*]] = alloca { i32, i32 }, align 8201; CHECK-NEXT:    store i32 0, ptr [[A]], align 4202; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1203; CHECK-NEXT:    store i32 1, ptr [[B]], align 4204; CHECK-NEXT:    call void @callee_notreadonly(ptr [[A]])205; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[A]], align 4206; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[B]], align 4207; CHECK-NEXT:    [[R:%.*]] = add i32 [[L1]], [[L2]]208; CHECK-NEXT:    ret i32 [[R]]209;210  %a = alloca {i32, i32}211  store i32 0, ptr %a212  %b = getelementptr i32, ptr %a, i32 1213  store i32 1, ptr %b214  call void @callee_notreadonly(ptr %a)215  %l1 = load i32, ptr %a216  %l2 = load i32, ptr %b217  %r = add i32 %l1, %l2218  ret i32 %r219}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 8225; CHECK-NEXT:    store i32 0, ptr [[A]], align 4226; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1227; CHECK-NEXT:    store i32 1, ptr [[B]], align 4228; CHECK-NEXT:    call void @callee_multiuse(ptr [[A]], ptr [[A]])229; CHECK-NEXT:    [[R:%.*]] = add i32 0, 1230; CHECK-NEXT:    ret i32 [[R]]231;232  %a = alloca {i32, i32}233  store i32 0, ptr %a234  %b = getelementptr i32, ptr %a, i32 1235  store i32 1, ptr %b236  call void @callee_multiuse(ptr %a, ptr %a)237  %l1 = load i32, ptr %a238  %l2 = load i32, ptr %b239  %r = add i32 %l1, %l2240  ret i32 %r241}242 243define i32 @memcpyed(ptr %src) {244; CHECK-LABEL: @memcpyed(245; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4246; CHECK-NEXT:    store i32 0, ptr [[A]], align 4247; 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 4250; CHECK-NEXT:    ret i32 [[L1]]251;252  %a = alloca i32253  store i32 0, ptr %a254  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 %a257  ret i32 %l1258}259 260define ptr @memcpyedsplit(ptr %src) {261; CHECK-LABEL: @memcpyedsplit(262; CHECK-NEXT:    [[A:%.*]] = alloca { i64, i64 }, align 8263; CHECK-NEXT:    store i8 1, ptr [[A]], align 1264; CHECK-NEXT:    [[B:%.*]] = getelementptr i64, ptr [[A]], i32 1265; CHECK-NEXT:    store ptr null, ptr [[B]], align 8266; 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 8269; CHECK-NEXT:    ret ptr [[L1]]270;271  %a = alloca { i64, i64 }272  store i8 1, ptr %a273  %b = getelementptr i64, ptr %a, i32 1274  store ptr null, ptr %b275  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 %b278  ret ptr %l1279}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 4287; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[LII]])288; CHECK-NEXT:    [[BF_CLEAR4:%.*]] = and i32 undef, -262144289; CHECK-NEXT:    [[BF_SET5:%.*]] = select i1 [[B:%.*]], i32 196608, i32 131072290; CHECK-NEXT:    [[BF_SET12:%.*]] = or disjoint i32 [[BF_SET5]], [[BF_CLEAR4]]291; CHECK-NEXT:    store i32 [[BF_SET12]], ptr [[LII]], align 4292; CHECK-NEXT:    call void @callee(ptr [[LII]])293; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[LII]])294; CHECK-NEXT:    ret void295;296entry:297  %LII = alloca %struct.LoadImmediateInfo, align 4298  call void @llvm.lifetime.start.p0(ptr nonnull %LII)299  %bf.load = load i32, ptr %LII, align 4300  %bf.clear4 = and i32 %bf.load, -262144301  %bf.set5 = select i1 %b, i32 196608, i32 131072302  %bf.set12 = or disjoint i32 %bf.set5, %bf.clear4303  store i32 %bf.set12, ptr %LII, align 4304  call void @callee(ptr %LII)305  call void @llvm.lifetime.end.p0(ptr nonnull %LII)306  ret void307}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 4313; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]314; CHECK:       if.then:315; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[LII]])316; CHECK-NEXT:    [[BF_CLEAR4:%.*]] = and i32 undef, -262144317; CHECK-NEXT:    [[BF_SET5:%.*]] = select i1 [[B:%.*]], i32 196608, i32 131072318; CHECK-NEXT:    [[BF_SET12:%.*]] = or disjoint i32 [[BF_SET5]], [[BF_CLEAR4]]319; CHECK-NEXT:    store i32 [[BF_SET12]], ptr [[LII]], align 4320; CHECK-NEXT:    call void @callee(ptr [[LII]])321; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[LII]])322; CHECK-NEXT:    br label [[IF_END]]323; CHECK:       if.end:324; CHECK-NEXT:    ret void325;326entry:327  %LII = alloca %struct.LoadImmediateInfo, align 4328  br i1 %c, label %if.then, label %if.end329 330if.then:                                          ; preds = %entry331  call void @llvm.lifetime.start.p0(ptr nonnull %LII)332  %bf.load = load i32, ptr %LII, align 4333  %bf.clear4 = and i32 %bf.load, -262144334  %bf.set5 = select i1 %b, i32 196608, i32 131072335  %bf.set12 = or disjoint i32 %bf.set5, %bf.clear4336  store i32 %bf.set12, ptr %LII, align 4337  call void @callee(ptr %LII)338  call void @llvm.lifetime.end.p0(ptr nonnull %LII)339  br label %if.end340 341if.end:                                           ; preds = %if.then, %entry342  ret void343}344 345define i32 @sixteenload() {346; CHECK-LABEL: @sixteenload(347; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4348; CHECK-NEXT:    store i32 0, ptr [[A]], align 4349; CHECK-NEXT:    call void @callee(ptr [[A]])350; CHECK-NEXT:    [[A1:%.*]] = add i32 0, 0351; CHECK-NEXT:    [[A2:%.*]] = add i32 [[A1]], 0352; CHECK-NEXT:    ret i32 [[A2]]353;354  %a = alloca i32355  store i32 0, ptr %a356  call void @callee(ptr %a)357  %l1 = load i32, ptr %a358  %l2 = load i32, ptr %a359  %l3 = load i32, ptr %a360  %l4 = load i32, ptr %a361  %l5 = load i32, ptr %a362  %l6 = load i32, ptr %a363  %l7 = load i32, ptr %a364  %l8 = load i32, ptr %a365  %l9 = load i32, ptr %a366  %l10 = load i32, ptr %a367  %l11 = load i32, ptr %a368  %l12 = load i32, ptr %a369  %l13 = load i32, ptr %a370  %l14 = load i32, ptr %a371  %l15 = load i32, ptr %a372  %l16 = load i32, ptr %a373  %a1 = add i32 %l1, %l2374  %a2 = add i32 %a1, %l3375  ret i32 %a2376}377 378define i32 @testcallalloca() {379; CHECK-LABEL: @testcallalloca(380; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4381; CHECK-NEXT:    store i32 0, ptr [[A]], align 4382; CHECK-NEXT:    call void [[A]]()383; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[A]], align 4384; CHECK-NEXT:    ret i32 [[L1]]385;386  %a = alloca i32387  store i32 0, ptr %a388  call void %a()389  %l1 = load i32, ptr %a390  ret i32 %l1391}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 4398; CHECK-NEXT:    store i32 0, ptr [[A]], align 4399; CHECK-NEXT:    call void @callee_byval(ptr [[A]])400; CHECK-NEXT:    ret i32 0401;402  %a = alloca i32403  store i32 0, ptr %a404  call void @callee_byval(ptr %a)405  %l1 = load i32, ptr %a406  ret i32 %l1407}408 409declare void @callee_address_only_capture(ptr readonly captures(address) %p)410 411define i32 @address_only_capture() {412; CHECK-LABEL: @address_only_capture(413; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4414; CHECK-NEXT:    store i32 0, ptr [[A]], align 4415; CHECK-NEXT:    call void @callee_address_only_capture(ptr [[A]])416; CHECK-NEXT:    ret i32 0417;418  %a = alloca i32419  store i32 0, ptr %a420  call void @callee_address_only_capture(ptr %a)421  %l1 = load i32, ptr %a422  ret i32 %l1423}424 425declare void @callee_read_only_capture(ptr readonly captures(address, read_provenance) %p)426 427define i32 @read_only_capture() {428; CHECK-LABEL: @read_only_capture(429; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4430; CHECK-NEXT:    store i32 0, ptr [[A]], align 4431; CHECK-NEXT:    call void @callee_read_only_capture(ptr [[A]])432; CHECK-NEXT:    ret i32 0433;434  %a = alloca i32435  store i32 0, ptr %a436  call void @callee_read_only_capture(ptr %a)437  %l1 = load i32, ptr %a438  ret i32 %l1439}440 441declare void @callee_provenance_only_capture(ptr readonly captures(provenance) %p)442 443; Should not be transformed, as write-provenance is captured.444define i32 @provenance_only_capture() {445; CHECK-LABEL: @provenance_only_capture(446; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4447; CHECK-NEXT:    store i32 0, ptr [[A]], align 4448; CHECK-NEXT:    call void @callee_provenance_only_capture(ptr [[A]])449; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[A]], align 4450; CHECK-NEXT:    ret i32 [[L1]]451;452  %a = alloca i32453  store i32 0, ptr %a454  call void @callee_provenance_only_capture(ptr %a)455  %l1 = load i32, ptr %a456  ret i32 %l1457}458 459define i32 @simple_with_lifetimes() {460; CHECK-LABEL: @simple_with_lifetimes(461; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4462; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr [[A]])463; CHECK-NEXT:    store i32 0, ptr [[A]], align 4464; CHECK-NEXT:    call void @callee(ptr [[A]])465; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr [[A]])466; CHECK-NEXT:    ret i32 0467;468  %a = alloca i32469  call void @llvm.lifetime.start(ptr %a)470  store i32 0, ptr %a471  call void @callee(ptr %a)472  %l1 = load i32, ptr %a473  call void @llvm.lifetime.end(ptr %a)474  ret i32 %l1475}476 477define i32 @twoalloc_with_lifetimes() {478; CHECK-LABEL: @twoalloc_with_lifetimes(479; CHECK-NEXT:    [[A:%.*]] = alloca { i32, i32 }, align 8480; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr [[A]])481; CHECK-NEXT:    store i32 0, ptr [[A]], align 4482; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1483; CHECK-NEXT:    store i32 1, ptr [[B]], align 4484; CHECK-NEXT:    call void @callee(ptr [[A]])485; CHECK-NEXT:    [[R:%.*]] = add i32 0, 1486; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr [[A]])487; CHECK-NEXT:    ret i32 [[R]]488;489  %a = alloca {i32, i32}490  call void @llvm.lifetime.start(ptr %a)491  store i32 0, ptr %a492  %b = getelementptr i32, ptr %a, i32 1493  store i32 1, ptr %b494  call void @callee(ptr %a)495  %l1 = load i32, ptr %a496  %l2 = load i32, ptr %b497  %r = add i32 %l1, %l2498  call void @llvm.lifetime.end(ptr %a)499  ret i32 %r500}501 502declare void @use.i32(i32)503 504; We can promote the %i load, even though there is an unknown offset load505; in the loop. It is sufficient that we know all stores.506define void @load_dyn_offset(ptr %ary) {507; CHECK-LABEL: @load_dyn_offset(508; CHECK-NEXT:    [[A:%.*]] = alloca { i64, [4 x i32] }, align 8509; CHECK-NEXT:    store i64 0, ptr [[A]], align 4510; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 8511; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[GEP]], ptr [[ARY:%.*]], i64 16, i1 false)512; CHECK-NEXT:    br label [[LOOP:%.*]]513; CHECK:       loop:514; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[TMP0:%.*]] ]515; CHECK-NEXT:    [[I_NEXT]] = add i64 [[I]], 1516; CHECK-NEXT:    store i64 [[I_NEXT]], ptr [[A]], align 4517; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr i32, ptr [[GEP]], i64 [[I]]518; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[GEP_I]], align 4519; CHECK-NEXT:    call void @use.i32(i32 [[VAL]])520; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[I_NEXT]], 6521; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]522; CHECK:       exit:523; CHECK-NEXT:    ret void524;525  %a = alloca {i64, [4 x i32]}526  store i64 0, ptr %a527  %gep = getelementptr i8, ptr %a, i64 8528  call void @llvm.memcpy(ptr %gep, ptr %ary, i64 16, i1 false)529  br label %loop530 531loop:532  %i = load i64, ptr %a533  %i.next = add i64 %i, 1534  store i64 %i.next, ptr %a535  %gep.i = getelementptr i32, ptr %gep, i64 %i536  %val = load i32, ptr %gep.i537  call void @use.i32(i32 %val)538  %cmp = icmp eq i64 %i.next, 6539  br i1 %cmp, label %exit, label %loop540 541exit:542  ret void543}544 545; Same as previous test, but with an unknown-offset store. We can't promote in546; that case.547define void @store_dyn_offset(ptr %ary) {548; CHECK-LABEL: @store_dyn_offset(549; CHECK-NEXT:    [[A:%.*]] = alloca { i64, [4 x i32] }, align 8550; CHECK-NEXT:    store i64 0, ptr [[A]], align 4551; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 8552; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[GEP]], ptr [[ARY:%.*]], i64 16, i1 false)553; CHECK-NEXT:    br label [[LOOP:%.*]]554; CHECK:       loop:555; CHECK-NEXT:    [[I:%.*]] = load i64, ptr [[A]], align 4556; CHECK-NEXT:    [[I_NEXT:%.*]] = add i64 [[I]], 1557; CHECK-NEXT:    store i64 [[I_NEXT]], ptr [[A]], align 4558; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr i32, ptr [[GEP]], i64 [[I]]559; CHECK-NEXT:    [[I_TRUNC:%.*]] = trunc i64 [[I]] to i32560; CHECK-NEXT:    store i32 [[I_TRUNC]], ptr [[GEP_I]], align 4561; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[I_NEXT]], 6562; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]563; CHECK:       exit:564; CHECK-NEXT:    ret void565;566  %a = alloca {i64, [4 x i32]}567  store i64 0, ptr %a568  %gep = getelementptr i8, ptr %a, i64 8569  call void @llvm.memcpy(ptr %gep, ptr %ary, i64 16, i1 false)570  br label %loop571 572loop:573  %i = load i64, ptr %a574  %i.next = add i64 %i, 1575  store i64 %i.next, ptr %a576  %gep.i = getelementptr i32, ptr %gep, i64 %i577  %i.trunc = trunc i64 %i to i32578  store i32 %i.trunc, ptr %gep.i579  %cmp = icmp eq i64 %i.next, 6580  br i1 %cmp, label %exit, label %loop581 582exit:583  ret void584}585 586declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)587