mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[ObjC][ARC] Delete ARC runtime calls that take inert phi values
This improves on the following patch, which removed ARC runtime calls taking inert global variables: https://reviews.llvm.org/D62433 rdar://problem/59137105
This commit is contained in:
parent
f21a88cbf6
commit
5bf34bef20
@ -877,23 +877,43 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
|
||||
optimizeDelayedAutoreleaseRV();
|
||||
}
|
||||
|
||||
/// This function returns true if the value is inert. An ObjC ARC runtime call
|
||||
/// taking an inert operand can be safely deleted.
|
||||
static bool isInertARCValue(Value *V) {
|
||||
V = V->stripPointerCasts();
|
||||
|
||||
if (IsNullOrUndef(V))
|
||||
return true;
|
||||
|
||||
// See if this is a global attribute annotated with an 'objc_arc_inert'.
|
||||
if (auto *GV = dyn_cast<GlobalVariable>(V))
|
||||
if (GV->hasAttribute("objc_arc_inert"))
|
||||
return true;
|
||||
|
||||
if (auto PN = dyn_cast<PHINode>(V)) {
|
||||
// Look through phis's operands.
|
||||
for (Value *Opnd : PN->incoming_values())
|
||||
if (!isInertARCValue(Opnd))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjCARCOpt::OptimizeIndividualCallImpl(
|
||||
Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,
|
||||
Instruction *Inst, ARCInstKind Class, const Value *Arg) {
|
||||
LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n");
|
||||
|
||||
// Some of the ARC calls can be deleted if their arguments are global
|
||||
// variables that are inert in ARC.
|
||||
if (IsNoopOnGlobal(Class)) {
|
||||
Value *Opnd = Inst->getOperand(0);
|
||||
if (auto *GV = dyn_cast<GlobalVariable>(Opnd->stripPointerCasts()))
|
||||
if (GV->hasAttribute("objc_arc_inert")) {
|
||||
if (!Inst->getType()->isVoidTy())
|
||||
Inst->replaceAllUsesWith(Opnd);
|
||||
Inst->eraseFromParent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// We can delete this call if it takes an inert value.
|
||||
if (IsNoopOnGlobal(Class))
|
||||
if (isInertARCValue(Inst->getOperand(0))) {
|
||||
if (!Inst->getType()->isVoidTy())
|
||||
Inst->replaceAllUsesWith(Inst->getOperand(0));
|
||||
Inst->eraseFromParent();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Class) {
|
||||
default:
|
||||
|
@ -54,6 +54,39 @@ define internal void @__globalBlock_block_invoke(i8* nocapture readnone) {
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define %[[V0:.*]]* @test_conditional0(
|
||||
; CHECK: %[[PHI0:.*]] = phi %[[V0]]* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %[[V0]]*), %{{.*}} ], [ null, %{{.*}} ]
|
||||
|
||||
; CHECK: %[[PHI1:.*]] = phi %[[V0]]* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %[[V0]]*), %{{.*}} ], [ %[[PHI0]], %{{.*}} ]
|
||||
; CHECK-NEXT: %[[PHI2:.*]] = phi %[[V0]]* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %[[V0]]*), %{{.*}} ], [ %{{.*}}, %{{.*}} ]
|
||||
; CHECK-NEXT: %[[V2:.*]] = bitcast %[[V0]]* %[[PHI1]] to i8*
|
||||
; CHECK-NEXT: %[[V4:.*]] = bitcast %[[V0]]* %[[PHI2]] to i8*
|
||||
; CHECK-NEXT: %[[V5:.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[V4]])
|
||||
; CHECK-NEXT: ret %[[V0]]* %[[PHI2]]
|
||||
|
||||
define %0* @test_conditional0(i32 %i, %0* %b) {
|
||||
entry:
|
||||
%v0 = icmp eq i32 %i, 1
|
||||
br i1 %v0, label %bb2, label %bb1
|
||||
|
||||
bb1:
|
||||
%v1 = icmp eq i32 %i, 2
|
||||
br i1 %v1, label %bb2, label %return
|
||||
|
||||
bb2:
|
||||
%phi0 = phi %0* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %0*), %entry ], [ null, %bb1 ]
|
||||
br label %return
|
||||
|
||||
return:
|
||||
%phi1 = phi %0* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %0*), %bb1 ], [ %phi0, %bb2 ]
|
||||
%phi2 = phi %0* [ bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to %0*), %bb1 ], [ %b, %bb2 ]
|
||||
%v2 = bitcast %0* %phi1 to i8*
|
||||
%v3 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %v2)
|
||||
%v4 = bitcast %0* %phi2 to i8*
|
||||
%v5 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %v4)
|
||||
ret %0* %phi2
|
||||
}
|
||||
|
||||
declare void @foo()
|
||||
|
||||
declare i8* @llvm.objc.retain(i8*) local_unnamed_addr
|
||||
|
Loading…
x
Reference in New Issue
Block a user