forked from OSchip/llvm-project
[ObjC][ARC] Keep track of phis that have been discovered to avoid an
infinite loop
This fixes a bug introduced in 6770fbb314
.
rdar://problem/59137105
This commit is contained in:
parent
caeb6cfbc2
commit
4dcc029edb
|
@ -879,7 +879,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
|
||||||
|
|
||||||
/// This function returns true if the value is inert. An ObjC ARC runtime call
|
/// This function returns true if the value is inert. An ObjC ARC runtime call
|
||||||
/// taking an inert operand can be safely deleted.
|
/// taking an inert operand can be safely deleted.
|
||||||
static bool isInertARCValue(Value *V) {
|
static bool isInertARCValue(Value *V, SmallPtrSet<Value *, 1> &VisitedPhis) {
|
||||||
V = V->stripPointerCasts();
|
V = V->stripPointerCasts();
|
||||||
|
|
||||||
if (IsNullOrUndef(V))
|
if (IsNullOrUndef(V))
|
||||||
|
@ -891,9 +891,12 @@ static bool isInertARCValue(Value *V) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (auto PN = dyn_cast<PHINode>(V)) {
|
if (auto PN = dyn_cast<PHINode>(V)) {
|
||||||
|
// Ignore this phi if it has already been discovered.
|
||||||
|
if (!VisitedPhis.insert(PN).second)
|
||||||
|
return true;
|
||||||
// Look through phis's operands.
|
// Look through phis's operands.
|
||||||
for (Value *Opnd : PN->incoming_values())
|
for (Value *Opnd : PN->incoming_values())
|
||||||
if (!isInertARCValue(Opnd))
|
if (!isInertARCValue(Opnd, VisitedPhis))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -907,8 +910,10 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(
|
||||||
LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n");
|
LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n");
|
||||||
|
|
||||||
// We can delete this call if it takes an inert value.
|
// We can delete this call if it takes an inert value.
|
||||||
|
SmallPtrSet<Value *, 1> VisitedPhis;
|
||||||
|
|
||||||
if (IsNoopOnGlobal(Class))
|
if (IsNoopOnGlobal(Class))
|
||||||
if (isInertARCValue(Inst->getOperand(0))) {
|
if (isInertARCValue(Inst->getOperand(0), VisitedPhis)) {
|
||||||
if (!Inst->getType()->isVoidTy())
|
if (!Inst->getType()->isVoidTy())
|
||||||
Inst->replaceAllUsesWith(Inst->getOperand(0));
|
Inst->replaceAllUsesWith(Inst->getOperand(0));
|
||||||
Inst->eraseFromParent();
|
Inst->eraseFromParent();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
@.str = private unnamed_addr constant [4 x i8] c"abc\00", section "__TEXT,__cstring,cstring_literals", align 1
|
@.str = private unnamed_addr constant [4 x i8] c"abc\00", section "__TEXT,__cstring,cstring_literals", align 1
|
||||||
@.str1 = private unnamed_addr constant [4 x i8] c"def\00", section "__TEXT,__cstring,cstring_literals", align 1
|
@.str1 = private unnamed_addr constant [4 x i8] c"def\00", section "__TEXT,__cstring,cstring_literals", align 1
|
||||||
@_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8 #0
|
@_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8 #0
|
||||||
|
@_unnamed_cfstring_.1 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8 #0
|
||||||
@_unnamed_cfstring_wo_attr = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8
|
@_unnamed_cfstring_wo_attr = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8
|
||||||
@_NSConcreteGlobalBlock = external global i8*
|
@_NSConcreteGlobalBlock = external global i8*
|
||||||
@.str.1 = private unnamed_addr constant [6 x i8] c"v8@?0\00", align 1
|
@.str.1 = private unnamed_addr constant [6 x i8] c"v8@?0\00", align 1
|
||||||
|
@ -87,6 +88,40 @@ return:
|
||||||
ret %0* %phi2
|
ret %0* %phi2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: define void @test_conditional1(
|
||||||
|
; CHECK-NOT: @llvm.objc
|
||||||
|
; CHECK: ret void
|
||||||
|
|
||||||
|
define void @test_conditional1(i32 %i) {
|
||||||
|
entry:
|
||||||
|
%v0 = add nsw i32 %i, -1
|
||||||
|
%c1 = icmp eq i32 %v0, 0
|
||||||
|
br i1 %c1, label %while.end, label %while.body
|
||||||
|
|
||||||
|
while.body:
|
||||||
|
%v1 = phi i32 [ %v5, %if.end ], [ %v0, %entry ]
|
||||||
|
%v2 = phi i8* [ %v4, %if.end ], [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_.1 to i8*), %entry ]
|
||||||
|
%v3 = tail call i8* @llvm.objc.retain(i8* %v2)
|
||||||
|
%cmp = icmp eq i32 %v1, 2
|
||||||
|
br i1 %cmp, label %if.then, label %if.end
|
||||||
|
|
||||||
|
if.then:
|
||||||
|
call void @llvm.objc.release(i8* %v2)
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end:
|
||||||
|
%v4 = phi i8* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to i8*), %if.then ], [ %v2, %while.body ]
|
||||||
|
call void @llvm.objc.release(i8* %v2)
|
||||||
|
%v5 = add nsw i32 %v1, -1
|
||||||
|
%tobool = icmp eq i32 %v5, 0
|
||||||
|
br i1 %tobool, label %while.end, label %while.body
|
||||||
|
|
||||||
|
while.end:
|
||||||
|
%v6 = phi i8* [ null, %entry ], [ %v4, %if.end ]
|
||||||
|
call void @llvm.objc.release(i8* %v6)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
declare void @foo()
|
declare void @foo()
|
||||||
|
|
||||||
declare i8* @llvm.objc.retain(i8*) local_unnamed_addr
|
declare i8* @llvm.objc.retain(i8*) local_unnamed_addr
|
||||||
|
|
Loading…
Reference in New Issue