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