mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-06 20:32:19 +00:00
Suppress partial retain+release elimination when there's a
possibility that it will span multiple CFG diamonds/triangles which could have different controlling predicates. rdar://10282956 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142222 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3c5e60994f
commit
90b8bcd33a
@ -1158,6 +1158,11 @@ namespace {
|
|||||||
/// with the "tail" keyword.
|
/// with the "tail" keyword.
|
||||||
bool IsTailCallRelease;
|
bool IsTailCallRelease;
|
||||||
|
|
||||||
|
/// Partial - True of we've seen an opportunity for partial RR elimination,
|
||||||
|
/// such as pushing calls into a CFG triangle or into one side of a
|
||||||
|
/// CFG diamond.
|
||||||
|
bool Partial;
|
||||||
|
|
||||||
/// ReleaseMetadata - If the Calls are objc_release calls and they all have
|
/// ReleaseMetadata - If the Calls are objc_release calls and they all have
|
||||||
/// a clang.imprecise_release tag, this is the metadata tag.
|
/// a clang.imprecise_release tag, this is the metadata tag.
|
||||||
MDNode *ReleaseMetadata;
|
MDNode *ReleaseMetadata;
|
||||||
@ -1172,6 +1177,7 @@ namespace {
|
|||||||
|
|
||||||
RRInfo() :
|
RRInfo() :
|
||||||
KnownSafe(false), IsRetainBlock(false), IsTailCallRelease(false),
|
KnownSafe(false), IsRetainBlock(false), IsTailCallRelease(false),
|
||||||
|
Partial(false),
|
||||||
ReleaseMetadata(0) {}
|
ReleaseMetadata(0) {}
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
@ -1182,6 +1188,7 @@ void RRInfo::clear() {
|
|||||||
KnownSafe = false;
|
KnownSafe = false;
|
||||||
IsRetainBlock = false;
|
IsRetainBlock = false;
|
||||||
IsTailCallRelease = false;
|
IsTailCallRelease = false;
|
||||||
|
Partial = false;
|
||||||
ReleaseMetadata = 0;
|
ReleaseMetadata = 0;
|
||||||
Calls.clear();
|
Calls.clear();
|
||||||
ReverseInsertPts.clear();
|
ReverseInsertPts.clear();
|
||||||
@ -1272,8 +1279,16 @@ PtrState::Merge(const PtrState &Other, bool TopDown) {
|
|||||||
if (RRI.IsRetainBlock != Other.RRI.IsRetainBlock)
|
if (RRI.IsRetainBlock != Other.RRI.IsRetainBlock)
|
||||||
Seq = S_None;
|
Seq = S_None;
|
||||||
|
|
||||||
|
// If we're not in a sequence (anymore), drop all associated state.
|
||||||
if (Seq == S_None) {
|
if (Seq == S_None) {
|
||||||
RRI.clear();
|
RRI.clear();
|
||||||
|
} else if (RRI.Partial || Other.RRI.Partial) {
|
||||||
|
// If we're doing a merge on a path that's previously seen a partial
|
||||||
|
// merge, conservatively drop the sequence, to avoid doing partial
|
||||||
|
// RR elimination. If the branch predicates for the two merge differ,
|
||||||
|
// mixing them is unsafe.
|
||||||
|
Seq = S_None;
|
||||||
|
RRI.clear();
|
||||||
} else {
|
} else {
|
||||||
// Conservatively merge the ReleaseMetadata information.
|
// Conservatively merge the ReleaseMetadata information.
|
||||||
if (RRI.ReleaseMetadata != Other.RRI.ReleaseMetadata)
|
if (RRI.ReleaseMetadata != Other.RRI.ReleaseMetadata)
|
||||||
@ -1282,8 +1297,15 @@ PtrState::Merge(const PtrState &Other, bool TopDown) {
|
|||||||
RRI.KnownSafe = RRI.KnownSafe && Other.RRI.KnownSafe;
|
RRI.KnownSafe = RRI.KnownSafe && Other.RRI.KnownSafe;
|
||||||
RRI.IsTailCallRelease = RRI.IsTailCallRelease && Other.RRI.IsTailCallRelease;
|
RRI.IsTailCallRelease = RRI.IsTailCallRelease && Other.RRI.IsTailCallRelease;
|
||||||
RRI.Calls.insert(Other.RRI.Calls.begin(), Other.RRI.Calls.end());
|
RRI.Calls.insert(Other.RRI.Calls.begin(), Other.RRI.Calls.end());
|
||||||
RRI.ReverseInsertPts.insert(Other.RRI.ReverseInsertPts.begin(),
|
|
||||||
Other.RRI.ReverseInsertPts.end());
|
// Merge the insert point sets. If there are any differences,
|
||||||
|
// that makes this a partial merge.
|
||||||
|
RRI.Partial = RRI.ReverseInsertPts.size() !=
|
||||||
|
Other.RRI.ReverseInsertPts.size();
|
||||||
|
for (SmallPtrSet<Instruction *, 2>::const_iterator
|
||||||
|
I = Other.RRI.ReverseInsertPts.begin(),
|
||||||
|
E = Other.RRI.ReverseInsertPts.end(); I != E; ++I)
|
||||||
|
RRI.Partial |= RRI.ReverseInsertPts.insert(*I);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,37 @@ alt_return:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Don't do partial elimination into two different CFG diamonds.
|
||||||
|
|
||||||
|
; CHECK: define void @test1b(
|
||||||
|
; CHECK: entry:
|
||||||
|
; CHECK: tail call i8* @objc_retain(i8* %x) nounwind
|
||||||
|
; CHECK-NOT: @objc_
|
||||||
|
; CHECK: if.end5:
|
||||||
|
; CHECK: tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0
|
||||||
|
; CHECK-NOT: @objc_
|
||||||
|
; CHECK: }
|
||||||
|
define void @test1b(i8* %x, i1 %p, i1 %q) {
|
||||||
|
entry:
|
||||||
|
tail call i8* @objc_retain(i8* %x) nounwind
|
||||||
|
br i1 %p, label %if.then, label %if.end
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
tail call void @callee()
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.then, %entry
|
||||||
|
br i1 %q, label %if.then3, label %if.end5
|
||||||
|
|
||||||
|
if.then3: ; preds = %if.end
|
||||||
|
tail call void @use_pointer(i8* %x)
|
||||||
|
br label %if.end5
|
||||||
|
|
||||||
|
if.end5: ; preds = %if.then3, %if.end
|
||||||
|
tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
; Like test0 but the pointer is passed to an intervening call,
|
; Like test0 but the pointer is passed to an intervening call,
|
||||||
; so the optimization is not safe.
|
; so the optimization is not safe.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user