[ObjCARC] Do not move a release that has the clang.imprecise_release tag

above PHI instructions.

ARC optimizer has an optimization that moves a call to an ObjC runtime
function above a phi instruction when the phi has a null operand and is
an argument passed to the function call. This optimization should not
kick in when the runtime function is an objc_release that releases an
object with precise lifetime semantics.

rdar://problem/34959669

llvm-svn: 315914
This commit is contained in:
Akira Hatanaka 2017-10-16 16:46:59 +00:00
parent a4b89ed0b7
commit e8c1a54c07
2 changed files with 28 additions and 3 deletions

View File

@ -808,9 +808,14 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
// If Arg is a PHI, and one or more incoming values to the // If Arg is a PHI, and one or more incoming values to the
// PHI are null, and the call is control-equivalent to the PHI, and there // PHI are null, and the call is control-equivalent to the PHI, and there
// are no relevant side effects between the PHI and the call, the call // are no relevant side effects between the PHI and the call, and the call
// could be pushed up to just those paths with non-null incoming values. // is not a release that doesn't have the clang.imprecise_release tag, the
// For now, don't bother splitting critical edges for this. // call could be pushed up to just those paths with non-null incoming
// values. For now, don't bother splitting critical edges for this.
if (Class == ARCInstKind::Release &&
!Inst->getMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease)))
continue;
SmallVector<std::pair<Instruction *, const Value *>, 4> Worklist; SmallVector<std::pair<Instruction *, const Value *>, 4> Worklist;
Worklist.push_back(std::make_pair(Inst, Arg)); Worklist.push_back(std::make_pair(Inst, Arg));
do { do {

View File

@ -1342,6 +1342,26 @@ A:
br label %C br label %C
B: B:
br label %C br label %C
C:
%h = phi double* [ null, %A ], [ %p, %B ]
%c = bitcast double* %h to i8*
call void @objc_release(i8* %c), !clang.imprecise_release !0
ret void
}
; Do not move an objc_release that doesn't have the clang.imprecise_release tag.
; CHECK-LABEL: define void @test22_precise(
; CHECK: %[[P0:.*]] = phi double*
; CHECK: %[[V0:.*]] = bitcast double* %[[P0]] to i8*
; CHECK: call void @objc_release(i8* %[[V0]])
; CHECK: ret void
define void @test22_precise(double* %p, i1 %a) {
br i1 %a, label %A, label %B
A:
br label %C
B:
br label %C
C: C:
%h = phi double* [ null, %A ], [ %p, %B ] %h = phi double* [ null, %A ], [ %p, %B ]
%c = bitcast double* %h to i8* %c = bitcast double* %h to i8*