llvm.org GIT mirror llvm / c26f76b
[CodeExtractor] Do not lift lifetime.end markers for region inputs If a lifetime.end marker occurs along one path through the extraction region, but not another, then it's still incorrect to lift the marker, because there is some path through the extracted function which would ordinarily not reach the marker. If the call to the extracted function is in a loop, unrolling can cause inputs to the function to become optimized out as undef after the first iteration. To prevent incorrect stack slot merging in the calling function, it should be sufficient to lift lifetime.start markers for region inputs. I've tested this theory out by doing a stage2 check-all with randomized splitting enabled. This is a follow-up to r353973, and there's additional context for this change in https://reviews.llvm.org/D57834. rdar://47896986 Differential Revision: https://reviews.llvm.org/D58253 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354159 91177308-0d34-0410-b5e6-96231b3b80d8 Vedant Kumar 6 months ago
4 changed file(s) with 60 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
885885 }
886886
887887 /// Erase lifetime.start markers which reference inputs to the extraction
888 /// region, and insert the referenced memory into \p LifetimesStart. Do the same
889 /// with lifetime.end markers (but insert them into \p LifetimesEnd).
888 /// region, and insert the referenced memory into \p LifetimesStart.
890889 ///
891890 /// The extraction region is defined by a set of blocks (\p Blocks), and a set
892891 /// of allocas which will be moved from the caller function into the extracted
893892 /// function (\p SunkAllocas).
894893 static void eraseLifetimeMarkersOnInputs(const SetVector &Blocks,
895894 const SetVector &SunkAllocas,
896 SetVector &LifetimesStart,
897 SetVector &LifetimesEnd) {
895 SetVector &LifetimesStart) {
898896 for (BasicBlock *BB : Blocks) {
899897 for (auto It = BB->begin(), End = BB->end(); It != End;) {
900898 auto *II = dyn_cast(&*It);
911909
912910 if (II->getIntrinsicID() == Intrinsic::lifetime_start)
913911 LifetimesStart.insert(Mem);
914 else
915 LifetimesEnd.insert(Mem);
916912 II->eraseFromParent();
917913 }
918914 }
14201416 }
14211417
14221418 // Collect objects which are inputs to the extraction region and also
1423 // referenced by lifetime start/end markers within it. The effects of these
1419 // referenced by lifetime start markers within it. The effects of these
14241420 // markers must be replicated in the calling function to prevent the stack
14251421 // coloring pass from merging slots which store input objects.
1426 ValueSet LifetimesStart, LifetimesEnd;
1427 eraseLifetimeMarkersOnInputs(Blocks, SinkingCands, LifetimesStart,
1428 LifetimesEnd);
1422 ValueSet LifetimesStart;
1423 eraseLifetimeMarkersOnInputs(Blocks, SinkingCands, LifetimesStart);
14291424
14301425 // Construct new function based on inputs/outputs & add allocas for all defs.
14311426 Function *newFunction =
14481443
14491444 // Replicate the effects of any lifetime start/end markers which referenced
14501445 // input objects in the extraction region by placing markers around the call.
1451 insertLifetimeMarkersSurroundingCall(oldFunction->getParent(),
1452 LifetimesStart.getArrayRef(),
1453 LifetimesEnd.getArrayRef(), TheCall);
1446 insertLifetimeMarkersSurroundingCall(
1447 oldFunction->getParent(), LifetimesStart.getArrayRef(), {}, TheCall);
14541448
14551449 // Propagate personality info to the new function if there is one.
14561450 if (oldFunction->hasPersonalityFn())
88 ; CHECK-LABEL: define{{.*}}@caller(
99 ; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %tmp.i)
1010 ; CHECK-NEXT: call void @callee_unknown_use1.{{.*}}(i8* %tmp.i
11 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %tmp.i)
1211
1312 define i32 @callee_unknown_use1(i32 %arg) local_unnamed_addr #0 {
1413 ; CHECK-LABEL:define{{.*}}@callee_unknown_use1.{{[0-9]}}
3333 ; CHECK-NEXT: [[local2_cast:%.*]] = bitcast i256* %local2 to i8*
3434 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[local2_cast]])
3535 ; CHECK-NEXT: call i1 @foo.cold.1(i8* %local1_cast, i8* %local2_cast)
36 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[local1_cast]])
37 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[local2_cast]])
3836 ; CHECK-NEXT: br i1
3937
4038 outlinedPath:
55 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
66
77 declare void @cold_use(i8*) cold
8
9 declare void @use(i8*)
810
911 ; In this CFG, splitting will extract the blocks extract{1,2}. I.e., it will
1012 ; extract a lifetime.start marker, but not the corresponding lifetime.end
7274 }
7375
7476 ; In this CFG, splitting will extract the block extract1. I.e., it will extract
75 ; a lifetime.end marker, but not the corresponding lifetime.start marker. Make
76 ; sure that a lifetime.end marker is emitted after the call to the split
77 ; function, and *only* that marker.
77 ; a lifetime.end marker, but not the corresponding lifetime.start marker. Do
78 ; not emit a lifetime.end marker after the call to the split function.
7879 ;
7980 ; entry
8081 ; (lt.start)
9091 ; (lt.start)
9192 ; / \
9293 ; no-extract1 codeRepl
93 ; (lt.end) (lt.end)
94 ; (lt.end)
9495 ; \ /
9596 ; exit
9697 define void @only_lifetime_end_is_cold() {
104105 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]])
105106 ; CHECK-NEXT: br label [[EXIT:%.*]]
106107 ; CHECK: codeRepl:
107 ; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
108108 ; CHECK-NEXT: call void @only_lifetime_end_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
109 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]])
110109 ; CHECK-NEXT: br label [[EXIT]]
111110 ; CHECK: exit:
112111 ; CHECK-NEXT: ret void
132131 exit:
133132 ret void
134133 }
134
135 ; In this CFG, splitting will extract the blocks extract{1,2,3}. Lifting the
136 ; lifetime.end marker would be a miscompile.
137 define void @do_not_lift_lifetime_end() {
138 ; CHECK-LABEL: @do_not_lift_lifetime_end(
139 ; CHECK-NEXT: entry:
140 ; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256
141 ; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
142 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
143 ; CHECK-NEXT: br label [[HEADER:%.*]]
144 ; CHECK: header:
145 ; CHECK-NEXT: call void @use(i8* [[LOCAL1_CAST]])
146 ; CHECK-NEXT: br i1 undef, label [[EXIT:%.*]], label [[CODEREPL:%.*]]
147 ; CHECK: codeRepl:
148 ; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @do_not_lift_lifetime_end.cold.1(i8* [[LOCAL1_CAST]]) #3
149 ; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[HEADER]], label [[EXIT]]
150 ; CHECK: exit:
151 ; CHECK-NEXT: ret void
152 ;
153 entry:
154 ; lt.start
155 %local1 = alloca i256
156 %local1_cast = bitcast i256* %local1 to i8*
157 call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
158 br label %header
159
160 header:
161 ; If the lifetime.end marker is lifted, this use becomes dead the second time
162 ; the header block is executed.
163 call void @use(i8* %local1_cast)
164 br i1 undef, label %exit, label %extract1
165
166 extract1:
167 call void @cold_use(i8* %local1_cast)
168 br i1 undef, label %extract2, label %extract3
169
170 extract2:
171 ; Backedge.
172 br label %header
173
174 extract3:
175 ; lt.end
176 call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
177 br label %exit
178
179 exit:
180 ret void
181 }