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-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" 5 6declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind 7declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind 8declare void @llvm.memset.p0i8.i8(i8* nocapture, i8, i8, i1) nounwind 9 10define void @test1() { 11; CHECK-LABEL: @test1( 12; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 13; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[A]]) 14; CHECK-NEXT: ret void 15; 16 %A = alloca i8 17 18 store i8 0, i8* %A ;; Written to by memset 19 call void @llvm.lifetime.end.p0i8(i64 1, i8* %A) 20 21 call void @llvm.memset.p0i8.i8(i8* %A, i8 0, i8 -1, i1 false) 22 23 ret void 24} 25 26define void @test2(i32* %P) { 27; CHECK-LABEL: @test2( 28; CHECK-NEXT: [[Q:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 1 29; CHECK-NEXT: [[R:%.*]] = bitcast i32* [[Q]] to i8* 30; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[R]]) 31; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[R]]) 32; CHECK-NEXT: ret void 33; 34 %Q = getelementptr i32, i32* %P, i32 1 35 %R = bitcast i32* %Q to i8* 36 call void @llvm.lifetime.start.p0i8(i64 4, i8* %R) 37 store i32 0, i32* %Q ;; This store is dead. 38 call void @llvm.lifetime.end.p0i8(i64 4, i8* %R) 39 ret void 40} 41 42; lifetime.end only marks the first two bytes of %A as dead. Make sure 43; `store i8 20, i8* %A.2 is not removed. 44define void @test3_lifetime_end_partial() { 45; CHECK-LABEL: @test3_lifetime_end_partial( 46; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 47; CHECK-NEXT: [[A_0:%.*]] = bitcast i32* [[A]] to i8* 48; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 2, i8* [[A_0]]) 49; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, i8* [[A_0]], i64 1 50; CHECK-NEXT: [[A_2:%.*]] = getelementptr i8, i8* [[A_0]], i64 2 51; CHECK-NEXT: store i8 20, i8* [[A_2]], align 1 52; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 2, i8* [[A_0]]) 53; CHECK-NEXT: call void @use(i8* [[A_1]]) 54; CHECK-NEXT: ret void 55; 56 %A = alloca i32 57 58 %A.0 = bitcast i32 * %A to i8* 59 call void @llvm.lifetime.start.p0i8(i64 2, i8* %A.0) 60 %A.1 = getelementptr i8, i8* %A.0, i64 1 61 %A.2 = getelementptr i8, i8* %A.0, i64 2 62 63 store i8 0, i8* %A.0 64 store i8 10, i8* %A.1 65 store i8 20, i8* %A.2 66 67 call void @llvm.lifetime.end.p0i8(i64 2, i8* %A.0) 68 call void @use(i8* %A.1) 69 ret void 70} 71 72; lifetime.end only marks the first two bytes of %A as dead. Make sure 73; `store i8 20, i8* %A.2 is not removed. 74define void @test4_lifetime_end_partial_loop() { 75; CHECK-LABEL: @test4_lifetime_end_partial_loop( 76; CHECK-NEXT: entry: 77; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 78; CHECK-NEXT: [[A_0:%.*]] = bitcast i32* [[A]] to i8* 79; CHECK-NEXT: br label [[LOOP:%.*]] 80; CHECK: loop: 81; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 82; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 2, i8* [[A_0]]) 83; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, i8* [[A_0]], i64 1 84; CHECK-NEXT: [[A_2:%.*]] = getelementptr i8, i8* [[A_0]], i64 2 85; CHECK-NEXT: call void @use(i8* [[A_1]]) 86; CHECK-NEXT: store i8 20, i8* [[A_2]], align 1 87; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 2, i8* [[A_0]]) 88; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 10 89; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i8 [[IV_NEXT]], 10 90; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]] 91; CHECK: exit: 92; CHECK-NEXT: ret void 93; 94entry: 95 %A = alloca i32 96 97 %A.0 = bitcast i32 * %A to i8* 98 br label %loop 99 100loop: 101 %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ] 102 call void @llvm.lifetime.start.p0i8(i64 2, i8* %A.0) 103 %A.1 = getelementptr i8, i8* %A.0, i64 1 104 %A.2 = getelementptr i8, i8* %A.0, i64 2 105 106 call void @use(i8* %A.1) 107 108 store i8 20, i8* %A.2 109 store i8 10, i8* %A.1 110 store i8 0, i8* %A.0 111 call void @llvm.lifetime.end.p0i8(i64 2, i8* %A.0) 112 113 %iv.next = add i8 %iv, 10 114 %exitcond = icmp eq i8 %iv.next, 10 115 br i1 %exitcond, label %exit, label %loop 116 117exit: 118 ret void 119} 120 121; lifetime.end only marks the first two bytes of %A as dead. Make sure 122; `store i8 20, i8* %A.2 is not removed. 123define void @test5_lifetime_end_partial(i32* %A) { 124; CHECK-LABEL: @test5_lifetime_end_partial( 125; CHECK-NEXT: [[A_0:%.*]] = bitcast i32* [[A:%.*]] to i8* 126; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 2, i8* [[A_0]]) 127; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, i8* [[A_0]], i64 1 128; CHECK-NEXT: [[A_2:%.*]] = getelementptr i8, i8* [[A_0]], i64 2 129; CHECK-NEXT: store i8 20, i8* [[A_2]], align 1 130; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 2, i8* [[A_0]]) 131; CHECK-NEXT: call void @use(i8* [[A_1]]) 132; CHECK-NEXT: store i8 30, i8* [[A_1]], align 1 133; CHECK-NEXT: store i8 40, i8* [[A_2]], align 1 134; CHECK-NEXT: ret void 135; 136 137 %A.0 = bitcast i32 * %A to i8* 138 call void @llvm.lifetime.start.p0i8(i64 2, i8* %A.0) 139 %A.1 = getelementptr i8, i8* %A.0, i64 1 140 %A.2 = getelementptr i8, i8* %A.0, i64 2 141 142 store i8 0, i8* %A.0 143 store i8 10, i8* %A.1 144 store i8 20, i8* %A.2 145 146 call void @llvm.lifetime.end.p0i8(i64 2, i8* %A.0) 147 148 call void @use(i8* %A.1) 149 store i8 30, i8* %A.1 150 store i8 40, i8* %A.2 151 ret void 152} 153 154declare void @use(i8*) readonly 155