1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -basic-aa -dse -S | FileCheck %s 3 4target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 5declare void @unknown_func() 6declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind 7declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind 8 9; Tests where the pointer/object is accessible after the function returns. 10 11; Overwriting store along one path to the exit. 12define void @accessible_after_return_1(i32* noalias %P, i1 %c) { 13; CHECK-LABEL: @accessible_after_return_1( 14; CHECK-NEXT: entry: 15; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 16; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 17; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i1 false) 18; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 19; CHECK: bb1: 20; CHECK-NEXT: br label [[BB3:%.*]] 21; CHECK: bb2: 22; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 23; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX1]], align 4 24; CHECK-NEXT: br label [[BB3]] 25; CHECK: bb3: 26; CHECK-NEXT: ret void 27; 28entry: 29 %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1 30 %p3 = bitcast i32* %arrayidx0 to i8* 31 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false) 32 br i1 %c, label %bb1, label %bb2 33bb1: 34 br label %bb3 35bb2: 36 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1 37 store i32 1, i32* %arrayidx1, align 4 38 br label %bb3 39bb3: 40 ret void 41} 42 43; Post-dominating store. 44; TODO: The memset can be shortened. 45define void @accessible_after_return_2(i32* noalias %P, i1 %c) { 46; CHECK-LABEL: @accessible_after_return_2( 47; CHECK-NEXT: entry: 48; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 49; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 50; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i1 false) 51; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 52; CHECK: bb1: 53; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 54; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX1]], align 4 55; CHECK-NEXT: br label [[BB3:%.*]] 56; CHECK: bb2: 57; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 58; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX2]], align 4 59; CHECK-NEXT: br label [[BB3]] 60; CHECK: bb3: 61; CHECK-NEXT: ret void 62; 63entry: 64 %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1 65 %p3 = bitcast i32* %arrayidx0 to i8* 66 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false) 67 br i1 %c, label %bb1, label %bb2 68 69bb1: 70 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1 71 store i32 1, i32* %arrayidx1, align 4 72 br label %bb3 73 74bb2: 75 %arrayidx2 = getelementptr inbounds i32, i32* %P, i64 1 76 store i32 1, i32* %arrayidx2, align 4 77 br label %bb3 78 79bb3: 80 ret void 81} 82 83; Stores along both exit paths. 84define void @accessible_after_return_3(i32* noalias %P, i1 %c) { 85; CHECK-LABEL: @accessible_after_return_3( 86; CHECK-NEXT: entry: 87; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 88; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 89; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4 90; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false) 91; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 92; CHECK: bb1: 93; CHECK-NEXT: br label [[BB3:%.*]] 94; CHECK: bb2: 95; CHECK-NEXT: br label [[BB3]] 96; CHECK: bb3: 97; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 98; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX1]], align 4 99; CHECK-NEXT: ret void 100; 101entry: 102 %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1 103 %p3 = bitcast i32* %arrayidx0 to i8* 104 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false) 105 br i1 %c, label %bb1, label %bb2 106 107bb1: 108 br label %bb3 109 110bb2: 111 br label %bb3 112 113bb3: 114 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1 115 store i32 1, i32* %arrayidx1, align 4 116 ret void 117} 118 119 120; Tests where the pointer/object is *NOT* accessible after the function returns. 121 122; Overwriting store along one path to the exit. 123define void @alloca_1(i1 %c) { 124; CHECK-LABEL: @alloca_1( 125; CHECK-NEXT: entry: 126; CHECK-NEXT: [[P_ALLOCA:%.*]] = alloca [32 x i32], align 4 127; CHECK-NEXT: [[P:%.*]] = bitcast [32 x i32]* [[P_ALLOCA]] to i32* 128; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 129; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 130; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4 131; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false) 132; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 133; CHECK: bb1: 134; CHECK-NEXT: br label [[BB3:%.*]] 135; CHECK: bb2: 136; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 137; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX1]], align 4 138; CHECK-NEXT: br label [[BB3]] 139; CHECK: bb3: 140; CHECK-NEXT: ret void 141; 142entry: 143 %P.alloca = alloca [32 x i32] 144 %P = bitcast [32 x i32]* %P.alloca to i32* 145 %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1 146 %p3 = bitcast i32* %arrayidx0 to i8* 147 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false) 148 br i1 %c, label %bb1, label %bb2 149bb1: 150 br label %bb3 151bb2: 152 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1 153 store i32 1, i32* %arrayidx1, align 4 154 br label %bb3 155bb3: 156 ret void 157} 158 159; Post-dominating store. 160define void @alloca_2(i1 %c) { 161; CHECK-LABEL: @alloca_2( 162; CHECK-NEXT: entry: 163; CHECK-NEXT: [[P_ALLOCA:%.*]] = alloca [32 x i32], align 4 164; CHECK-NEXT: [[P:%.*]] = bitcast [32 x i32]* [[P_ALLOCA]] to i32* 165; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 166; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 167; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4 168; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false) 169; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 170; CHECK: bb1: 171; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 172; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX1]], align 4 173; CHECK-NEXT: br label [[BB3:%.*]] 174; CHECK: bb2: 175; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 176; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX2]], align 4 177; CHECK-NEXT: br label [[BB3]] 178; CHECK: bb3: 179; CHECK-NEXT: ret void 180; 181entry: 182 %P.alloca = alloca [32 x i32] 183 %P = bitcast [32 x i32]* %P.alloca to i32* 184 %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1 185 %p3 = bitcast i32* %arrayidx0 to i8* 186 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false) 187 br i1 %c, label %bb1, label %bb2 188 189bb1: 190 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1 191 store i32 1, i32* %arrayidx1, align 4 192 br label %bb3 193 194bb2: 195 %arrayidx2 = getelementptr inbounds i32, i32* %P, i64 1 196 store i32 1, i32* %arrayidx2, align 4 197 br label %bb3 198 199bb3: 200 ret void 201} 202 203; Stores along both exit paths. 204define void @alloca_3(i1 %c) { 205; CHECK-LABEL: @alloca_3( 206; CHECK-NEXT: entry: 207; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 208; CHECK: bb1: 209; CHECK-NEXT: br label [[BB3:%.*]] 210; CHECK: bb2: 211; CHECK-NEXT: br label [[BB3]] 212; CHECK: bb3: 213; CHECK-NEXT: ret void 214; 215entry: 216 %P.alloca = alloca [32 x i32] 217 %P = bitcast [32 x i32]* %P.alloca to i32* 218 %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1 219 %p3 = bitcast i32* %arrayidx0 to i8* 220 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false) 221 br i1 %c, label %bb1, label %bb2 222 223bb1: 224 br label %bb3 225 226bb2: 227 br label %bb3 228 229bb3: 230 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1 231 store i32 1, i32* %arrayidx1, align 4 232 ret void 233} 234