brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.8 KiB · 355b939 Raw
318 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=dse -S | FileCheck %s3 4target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"5 6declare noalias ptr @malloc(i64)7 8declare void @foo()9declare void @capture(ptr)10 11; Check that we do not remove the second store, as %m is returned.12define ptr @test_return_captures_1() {13; CHECK-LABEL: @test_return_captures_1(14; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)15; CHECK-NEXT:    store i8 1, ptr [[M]], align 116; CHECK-NEXT:    ret ptr [[M]]17;18  %m = call ptr @malloc(i64 24)19  store i8 0, ptr %m20  store i8 1, ptr %m21  ret ptr %m22}23 24; Same as @test_return_captures_1, but across BBs.25define ptr @test_return_captures_2() {26; CHECK-LABEL: @test_return_captures_2(27; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)28; CHECK-NEXT:    br label [[EXIT:%.*]]29; CHECK:       exit:30; CHECK-NEXT:    store i8 1, ptr [[M]], align 131; CHECK-NEXT:    ret ptr [[M]]32;33  %m = call ptr @malloc(i64 24)34  store i8 0, ptr %m35  br label %exit36 37exit:38  store i8 1, ptr %m39  ret ptr %m40}41 42 43%S1 = type { ptr }44 45; We cannot remove the last store to %m, because it escapes by storing it to %E.46define void @test_malloc_capture_1(ptr %E) {47; CHECK-LABEL: @test_malloc_capture_1(48; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)49; CHECK-NEXT:    br label [[EXIT:%.*]]50; CHECK:       exit:51; CHECK-NEXT:    store ptr [[M]], ptr [[E:%.*]], align 452; CHECK-NEXT:    store i8 1, ptr [[M]], align 153; CHECK-NEXT:    ret void54;55  %m = call ptr @malloc(i64 24)56  br label %exit57 58exit:59  store ptr %m, ptr %E60  store i8 1, ptr %m61  ret void62}63 64; Check we do not eliminate either store. The first one cannot be eliminated,65; due to the call of @capture. The second one because %m escapes.66define ptr @test_malloc_capture_2() {67; CHECK-LABEL: @test_malloc_capture_2(68; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)69; CHECK-NEXT:    store i8 0, ptr [[M]], align 170; CHECK-NEXT:    call void @capture(ptr [[M]])71; CHECK-NEXT:    br label [[EXIT:%.*]]72; CHECK:       exit:73; CHECK-NEXT:    store i8 1, ptr [[M]], align 174; CHECK-NEXT:    ret ptr [[M]]75;76  %m = call ptr @malloc(i64 24)77  store i8 0, ptr %m78  call void @capture(ptr %m)79  br label %exit80 81exit:82  store i8 1, ptr %m83  ret ptr %m84}85 86; We can remove the first store store i8 0, ptr %m because there are no throwing87; instructions between the 2 stores and also %m escapes after the killing store.88define ptr @test_malloc_capture_3() {89; CHECK-LABEL: @test_malloc_capture_3(90; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)91; CHECK-NEXT:    br label [[EXIT:%.*]]92; CHECK:       exit:93; CHECK-NEXT:    store i8 1, ptr [[M]], align 194; CHECK-NEXT:    call void @capture(ptr [[M]])95; CHECK-NEXT:    ret ptr [[M]]96;97  %m = call ptr @malloc(i64 24)98  store i8 0, ptr %m99  br label %exit100 101exit:102  store i8 1, ptr %m103  call void @capture(ptr %m)104  ret ptr %m105}106 107; TODO: We could remove the first store store i8 0, ptr %m because %m escapes108; after the killing store.109define ptr @test_malloc_capture_4() {110; CHECK-LABEL: @test_malloc_capture_4(111; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)112; CHECK-NEXT:    store i8 0, ptr [[M]], align 1113; CHECK-NEXT:    call void @may_throw_readnone()114; CHECK-NEXT:    br label [[EXIT:%.*]]115; CHECK:       exit:116; CHECK-NEXT:    store i8 1, ptr [[M]], align 1117; CHECK-NEXT:    call void @capture(ptr [[M]])118; CHECK-NEXT:    ret ptr [[M]]119;120 121  %m = call ptr @malloc(i64 24)122  store i8 0, ptr %m123  call void @may_throw_readnone()124  br label %exit125 126exit:127  store i8 1, ptr %m128  call void @capture(ptr %m)129  ret ptr %m130}131 132 133; We cannot remove the first store store i8 0, ptr %m because %m escapes134; before the killing store and we may throw in between.135define ptr @test_malloc_capture_5() {136; CHECK-LABEL: @test_malloc_capture_5(137; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)138; CHECK-NEXT:    call void @capture(ptr [[M]])139; CHECK-NEXT:    store i8 0, ptr [[M]], align 1140; CHECK-NEXT:    call void @may_throw_readnone()141; CHECK-NEXT:    br label [[EXIT:%.*]]142; CHECK:       exit:143; CHECK-NEXT:    store i8 1, ptr [[M]], align 1144; CHECK-NEXT:    ret ptr [[M]]145;146 147  %m = call ptr @malloc(i64 24)148  call void @capture(ptr %m)149  store i8 0, ptr %m150  call void @may_throw_readnone()151  br label %exit152 153exit:154  store i8 1, ptr %m155  ret ptr %m156}157 158 159; TODO: We could remove the first store 'store i8 0, ptr %m' even though there160; is a throwing instruction between them, because %m escapes after the killing161; store.162define ptr @test_malloc_capture_6() {163; CHECK-LABEL: @test_malloc_capture_6(164; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)165; CHECK-NEXT:    store i8 0, ptr [[M]], align 1166; CHECK-NEXT:    call void @may_throw_readnone()167; CHECK-NEXT:    br label [[EXIT:%.*]]168; CHECK:       exit:169; CHECK-NEXT:    store i8 1, ptr [[M]], align 1170; CHECK-NEXT:    call void @capture(ptr [[M]])171; CHECK-NEXT:    ret ptr [[M]]172;173 174  %m = call ptr @malloc(i64 24)175  store i8 0, ptr %m176  call void @may_throw_readnone()177  br label %exit178 179exit:180  store i8 1, ptr %m181  call void @capture(ptr %m)182  ret ptr %m183}184 185; We *could* remove the first store 'store i8 0, ptr %m' even though there is a186; throwing instruction between them, because %m escapes after the killing store.187; But this would require using PointerMayBeCapturedBefore in188; isInvisibleToCallerBeforeRet, which we currently do not do to limit189; compile-time, as this appears to hardly ever lead to more stores eliminated190; in practice.191define ptr @test_malloc_capture_7() {192; CHECK-LABEL: @test_malloc_capture_7(193; CHECK-NEXT:    [[M:%.*]] = call ptr @malloc(i64 24)194; CHECK-NEXT:    store i8 0, ptr [[M]], align 1195; CHECK-NEXT:    call void @may_throw()196; CHECK-NEXT:    br label [[EXIT:%.*]]197; CHECK:       exit:198; CHECK-NEXT:    store i8 1, ptr [[M]], align 1199; CHECK-NEXT:    call void @capture(ptr [[M]])200; CHECK-NEXT:    ret ptr [[M]]201;202 203  %m = call ptr @malloc(i64 24)204  store i8 0, ptr %m205  call void @may_throw()206  br label %exit207 208exit:209  store i8 1, ptr %m210  call void @capture(ptr %m)211  ret ptr %m212}213 214; Stores to stack objects can be eliminated if they are not captured inside the function.215define void @test_alloca_nocapture_1() {216; CHECK-LABEL: @test_alloca_nocapture_1(217; CHECK-NEXT:    call void @foo()218; CHECK-NEXT:    br label [[EXIT:%.*]]219; CHECK:       exit:220; CHECK-NEXT:    ret void221;222  %m = alloca i8223  store i8 0, ptr %m224  call void @foo()225  br label %exit226 227exit:228  store i8 1, ptr %m229  ret void230}231 232; Cannot remove first store i8 0, ptr %m, as the call to @capture captures the object.233define void @test_alloca_capture_1() {234; CHECK-LABEL: @test_alloca_capture_1(235; CHECK-NEXT:    [[M:%.*]] = alloca i8, align 1236; CHECK-NEXT:    store i8 0, ptr [[M]], align 1237; CHECK-NEXT:    call void @capture(ptr [[M]])238; CHECK-NEXT:    br label [[EXIT:%.*]]239; CHECK:       exit:240; CHECK-NEXT:    ret void241;242  %m = alloca i8243  store i8 0, ptr %m244  call void @capture(ptr %m)245  br label %exit246 247exit:248  store i8 1, ptr %m249  ret void250}251 252; We can remove the last store to %m, even though it escapes because the alloca253; becomes invalid after the function returns.254define void @test_alloca_capture_2(ptr %E) {255; CHECK-LABEL: @test_alloca_capture_2(256; CHECK-NEXT:    [[M:%.*]] = alloca i8, align 1257; CHECK-NEXT:    br label [[EXIT:%.*]]258; CHECK:       exit:259; CHECK-NEXT:    store ptr [[M]], ptr [[E:%.*]], align 4260; CHECK-NEXT:    ret void261;262  %m = alloca i8263  br label %exit264 265exit:266  store ptr %m, ptr %E267  store i8 1, ptr %m268  ret void269}270 271; Readnone functions are not modeled in MemorySSA, but could throw.272; Make sure we do not eliminate the first store 'store i8 2, ptr %call'273define void @malloc_capture_throw_1() {274; CHECK-LABEL: @malloc_capture_throw_1(275; CHECK-NEXT:    [[CALL:%.*]] = call ptr @malloc(i64 1)276; CHECK-NEXT:    call void @may_capture(ptr [[CALL]])277; CHECK-NEXT:    store i8 2, ptr [[CALL]], align 1278; CHECK-NEXT:    call void @may_throw_readnone()279; CHECK-NEXT:    store i8 3, ptr [[CALL]], align 1280; CHECK-NEXT:    ret void281;282  %call = call ptr @malloc(i64 1)283  call void @may_capture(ptr %call)284  store i8 2, ptr %call, align 1285  call void @may_throw_readnone()286  store i8 3, ptr %call, align 1287  ret void288}289 290; Readnone functions are not modeled in MemorySSA, but could throw.291; Make sure we do not eliminate the first store 'store i8 2, ptr %call'292define void @malloc_capture_throw_2() {293; CHECK-LABEL: @malloc_capture_throw_2(294; CHECK-NEXT:    [[CALL:%.*]] = call ptr @malloc(i64 1)295; CHECK-NEXT:    call void @may_capture(ptr [[CALL]])296; CHECK-NEXT:    store i8 2, ptr [[CALL]], align 1297; CHECK-NEXT:    br label [[BB:%.*]]298; CHECK:       bb:299; CHECK-NEXT:    call void @may_throw_readnone()300; CHECK-NEXT:    store i8 3, ptr [[CALL]], align 1301; CHECK-NEXT:    ret void302;303  %call = call ptr @malloc(i64 1)304  call void @may_capture(ptr %call)305  store i8 2, ptr %call, align 1306  br label %bb307 308bb:309  call void @may_throw_readnone()310  store i8 3, ptr %call, align 1311  ret void312}313 314 315declare void @may_capture(ptr)316declare void @may_throw_readnone() readnone317declare void @may_throw()318