Skip to content

Commit 87cde88

Browse files
authored
Fix for a crash due to performLocalReleaseMotion and performLocalRetainMotion (swiftlang#38150)
In low level LLVMARCOptimizer, during canonicalization we don't rauw the result of RT_Retain with its arg similarly to RT_ObjCRetain and RT_BridgeRetain. And during performLocalReleaseMotion, we assert that we have canonicalized RT_Retain. In a release compiler, if we optimize such an RT_Retain with a RT_Release, then this can result in a compiler crash Similarly not rauw'ing, can cause a crash due to performLocalRetainMotion Fixes rdar://79238115
1 parent fb293cb commit 87cde88

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

lib/LLVMPasses/LLVMARCOpts.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ static bool canonicalizeInputFunction(Function &F, ARCEntryPointBuilder &B,
116116
++NumNoopDeleted;
117117
continue;
118118
}
119+
if (!CI.use_empty()) {
120+
// Do not get RC identical value here, could end up with a
121+
// crash in replaceAllUsesWith as the type maybe different.
122+
CI.replaceAllUsesWith(CI.getArgOperand(0));
123+
Changed = true;
124+
}
119125
// Rewrite unknown retains into swift_retains.
120126
NativeRefs.insert(ArgVal);
121127
for (auto &X : UnknownObjectRetains[ArgVal]) {
@@ -138,7 +144,12 @@ static bool canonicalizeInputFunction(Function &F, ARCEntryPointBuilder &B,
138144
++NumNoopDeleted;
139145
continue;
140146
}
141-
147+
if (!CI.use_empty()) {
148+
// Do not get RC identical value here, could end up with a
149+
// crash in replaceAllUsesWith as the type maybe different.
150+
CI.replaceAllUsesWith(CI.getArgOperand(0));
151+
Changed = true;
152+
}
142153
// Have not encountered a strong retain/release. keep it in the
143154
// unknown retain/release list for now. It might get replaced
144155
// later.

test/LLVMPasses/basic.ll

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,59 @@ bb1:
369369
ret void
370370
}
371371

372+
; CHECK-LABEL: @releasemotion_forwarding
373+
; CHECK-NOT: swift_retain
374+
; CHECK-NOT: swift_release
375+
; CHECK: call void @user(%swift.refcounted* %P)
376+
; CHECK: ret
377+
define void @releasemotion_forwarding(%swift.refcounted* %P, i8* %O, %swift.bridge* %B) {
378+
entry:
379+
%res = tail call %swift.refcounted* @swift_retain(%swift.refcounted* %P)
380+
tail call void @swift_release(%swift.refcounted* %res) nounwind
381+
call void @user(%swift.refcounted* %res) nounwind
382+
ret void
383+
}
384+
385+
; CHECK-LABEL: @retainmotion_forwarding
386+
; CHECK: store %swift.refcounted* %P, %swift.refcounted** %R, align 4
387+
; CHECK-NOT: swift_retain
388+
; CHECK-NOT: swift_release
389+
; CHECK: ret
390+
define void @retainmotion_forwarding(%swift.refcounted* %P, %swift.refcounted** %R, %swift.bridge* %B) {
391+
entry:
392+
%res = tail call %swift.refcounted* @swift_retain(%swift.refcounted* %P)
393+
store %swift.refcounted* %res, %swift.refcounted** %R, align 4
394+
call void @swift_bridgeObjectRelease(%swift.bridge* %B)
395+
tail call void @swift_release(%swift.refcounted* %res) nounwind
396+
ret void
397+
}
398+
399+
; CHECK-LABEL: @unknownreleasemotion_forwarding
400+
; CHECK-NOT: swift_unknownObjectRetain
401+
; CHECK-NOT: swift_unknownObjectRelease
402+
; CHECK: call void @user(%swift.refcounted* %P)
403+
; CHECK: ret
404+
define void @unknownreleasemotion_forwarding(%swift.refcounted* %P, i8* %O, %swift.bridge* %B) {
405+
entry:
406+
%res = tail call %swift.refcounted* @swift_unknownObjectRetain(%swift.refcounted* %P)
407+
tail call void @swift_unknownObjectRelease(%swift.refcounted* %res) nounwind
408+
call void @user(%swift.refcounted* %res) nounwind
409+
ret void
410+
}
411+
412+
; CHECK-LABEL: @unknownretainmotion_forwarding
413+
; CHECK: store %swift.refcounted* %P, %swift.refcounted** %R, align 4
414+
; CHECK-NOT: swift_unknownObjectRetain
415+
; CHECK-NOT: swift_unknownObjectRelease
416+
; CHECK: ret
417+
define void @unknownretainmotion_forwarding(%swift.refcounted* %P, %swift.refcounted** %R, %swift.bridge* %B) {
418+
entry:
419+
%res = tail call %swift.refcounted* @swift_unknownObjectRetain(%swift.refcounted* %P)
420+
store %swift.refcounted* %res, %swift.refcounted** %R, align 4
421+
call void @swift_bridgeObjectRelease(%swift.bridge* %B)
422+
tail call void @swift_unknownObjectRelease(%swift.refcounted* %res) nounwind
423+
ret void
424+
}
372425

373426
!llvm.dbg.cu = !{!1}
374427
!llvm.module.flags = !{!4}

0 commit comments

Comments
 (0)