Skip to content

Commit

Permalink
[ObjC][ARC] Don't move a retain call living outside a loop into the loop
Browse files Browse the repository at this point in the history
body

We started seeing cases where ARC optimizer would move retain calls into
loop bodies, causing imbalance in the number of retain and release
calls, after changes were made to delete inert ARC calls since the inert
calls that used to block code motion are gone.

Fix the bug by setting the CFG hazard flag when visiting a loop header.

rdar://problem/56908836
  • Loading branch information
ahatanaka committed Feb 25, 2020
1 parent 63cef62 commit 430512e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
9 changes: 9 additions & 0 deletions llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,15 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
}
}

// Check that BB and MyStates have the same number of predecessors. This
// prevents retain calls that live outside a loop from being moved into the
// loop.
if (!BB->hasNPredecessors(MyStates.pred_end() - MyStates.pred_begin()))
for (auto I = MyStates.top_down_ptr_begin(),
E = MyStates.top_down_ptr_end();
I != E; ++I)
I->second.SetCFGHazardAfflicted(true);

LLVM_DEBUG(dbgs() << "Before:\n"
<< BBStates[BB] << "\n"
<< "Performing Dataflow:\n");
Expand Down
42 changes: 42 additions & 0 deletions llvm/test/Transforms/ObjCARC/cfg-hazards.ll
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,48 @@ exit:
ret void
}

; The retain call in the entry block shouldn't be moved to the loop body.

; CHECK: define void @test14(i8* %[[VAL0:.*]],
; CHECK: %[[V1:.*]] = tail call i8* @llvm.objc.retain(i8* %[[VAL0]])
; CHECK: %[[CMP:.*]] = icmp eq i8* %[[VAL0]], null
; CHECK: br i1 %[[CMP]], label %{{.*}}, label %{{.*}}

define void @test14(i8* %val0, i8 %val1) {
entry:
%v1 = tail call i8* @llvm.objc.retain(i8* %val0)
%cmp = icmp eq i8* %val0, null
br i1 %cmp, label %if.end27, label %if.then

if.then:
%tobool = icmp eq i8 %val1, 1
br label %for.body

for.cond:
%cmp6 = icmp eq i8 %val1, 2
br i1 %cmp6, label %for.body, label %for.end.loopexit

for.body:
call void @callee()
%tobool9 = icmp eq i8 %val1, 0
br i1 %tobool9, label %for.cond, label %if.then10

if.then10:
br label %for.end

for.end.loopexit:
br label %for.end

for.end:
call void @callee()
call void @use_pointer(i8* %v1)
br label %if.end27

if.end27:
call void @llvm.objc.release(i8* %v1) #0, !clang.imprecise_release !0
ret void
}

; CHECK: attributes [[NUW]] = { nounwind }

!0 = !{}

0 comments on commit 430512e

Please sign in to comment.