1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s 2>&1 | FileCheck %s 3 4declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) 5 6declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) 7 8declare void @cold_use(i8*) cold 9 10declare void @use(i8*) 11 12; In this CFG, splitting will extract the blocks extract{1,2}. I.e., it will 13; extract a lifetime.start marker, but not the corresponding lifetime.end 14; marker. Make sure that a lifetime.start marker is emitted before the call to 15; the split function, and *only* that marker. 16; 17; entry 18; / \ 19; extract1 no-extract1 20; (lt.start) | 21; / | 22; extract2 | 23; \_____ | 24; \ / 25; exit 26; (lt.end) 27; 28; After splitting, we should see: 29; 30; entry 31; / \ 32; codeRepl no-extract1 33; (lt.start) | 34; \ / 35; exit 36; (lt.end) 37define void @only_lifetime_start_is_cold() { 38; CHECK-LABEL: @only_lifetime_start_is_cold( 39; CHECK-NEXT: entry: 40; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256 41; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8* 42; CHECK-NEXT: br i1 undef, label [[CODEREPL:%.*]], label [[NO_EXTRACT1:%.*]] 43; CHECK: codeRepl: 44; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8* 45; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]]) 46; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @only_lifetime_start_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3 47; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[NO_EXTRACT1]], label [[EXIT:%.*]] 48; CHECK: no-extract1: 49; CHECK-NEXT: br label [[EXIT]] 50; CHECK: exit: 51; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]]) 52; CHECK-NEXT: ret void 53; 54entry: 55 %local1 = alloca i256 56 %local1_cast = bitcast i256* %local1 to i8* 57 br i1 undef, label %extract1, label %no-extract1 58 59extract1: 60 ; lt.start 61 call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast) 62 call void @cold_use(i8* %local1_cast) 63 br i1 undef, label %extract2, label %no-extract1 64 65extract2: 66 br label %exit 67 68no-extract1: 69 br label %exit 70 71exit: 72 ; lt.end 73 call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast) 74 ret void 75} 76 77; In this CFG, splitting will extract the block extract1. I.e., it will extract 78; a lifetime.end marker, but not the corresponding lifetime.start marker. Do 79; not emit a lifetime.end marker after the call to the split function. 80; 81; entry 82; (lt.start) 83; / \ 84; no-extract1 extract1 85; (lt.end) (lt.end) 86; \ / 87; exit 88; 89; After splitting, we should see: 90; 91; entry 92; (lt.start) 93; / \ 94; no-extract1 codeRepl 95; (lt.end) 96; \ / 97; exit 98define void @only_lifetime_end_is_cold() { 99; CHECK-LABEL: @only_lifetime_end_is_cold( 100; CHECK-NEXT: entry: 101; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256 102; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8* 103; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]]) 104; CHECK-NEXT: br i1 undef, label [[NO_EXTRACT1:%.*]], label [[CODEREPL:%.*]] 105; CHECK: no-extract1: 106; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]]) 107; CHECK-NEXT: br label [[EXIT:%.*]] 108; CHECK: codeRepl: 109; CHECK-NEXT: call void @only_lifetime_end_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3 110; CHECK-NEXT: br label [[EXIT]] 111; CHECK: exit: 112; CHECK-NEXT: ret void 113; 114entry: 115 ; lt.start 116 %local1 = alloca i256 117 %local1_cast = bitcast i256* %local1 to i8* 118 call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast) 119 br i1 undef, label %no-extract1, label %extract1 120 121no-extract1: 122 ; lt.end 123 call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast) 124 br label %exit 125 126extract1: 127 ; lt.end 128 call void @cold_use(i8* %local1_cast) 129 call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast) 130 br label %exit 131 132exit: 133 ret void 134} 135 136; In this CFG, splitting will extract the blocks extract{1,2,3}. Lifting the 137; lifetime.end marker would be a miscompile. 138define void @do_not_lift_lifetime_end() { 139; CHECK-LABEL: @do_not_lift_lifetime_end( 140; CHECK-NEXT: entry: 141; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256 142; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8* 143; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]]) 144; CHECK-NEXT: br label [[HEADER:%.*]] 145; CHECK: header: 146; CHECK-NEXT: call void @use(i8* [[LOCAL1_CAST]]) 147; CHECK-NEXT: br i1 undef, label [[EXIT:%.*]], label [[CODEREPL:%.*]] 148; CHECK: codeRepl: 149; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @do_not_lift_lifetime_end.cold.1(i8* [[LOCAL1_CAST]]) #3 150; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[HEADER]], label [[EXIT]] 151; CHECK: exit: 152; CHECK-NEXT: ret void 153; 154entry: 155 ; lt.start 156 %local1 = alloca i256 157 %local1_cast = bitcast i256* %local1 to i8* 158 call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast) 159 br label %header 160 161header: 162 ; If the lifetime.end marker is lifted, this use becomes dead the second time 163 ; the header block is executed. 164 call void @use(i8* %local1_cast) 165 br i1 undef, label %exit, label %extract1 166 167extract1: 168 call void @cold_use(i8* %local1_cast) 169 br i1 undef, label %extract2, label %extract3 170 171extract2: 172 ; Backedge. 173 br label %header 174 175extract3: 176 ; lt.end 177 call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast) 178 br label %exit 179 180exit: 181 ret void 182} 183