[llvm] 6770fbb - [ObjC][ARC] Delete ARC runtime calls that take inert phi values
Akira Hatanaka via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 7 16:31:54 PST 2020
Author: Akira Hatanaka
Date: 2020-02-07T16:31:36-08:00
New Revision: 6770fbb31450db15d8d4a2ac7f0ce70eaf2acc5f
URL: https://github.com/llvm/llvm-project/commit/6770fbb31450db15d8d4a2ac7f0ce70eaf2acc5f
DIFF: https://github.com/llvm/llvm-project/commit/6770fbb31450db15d8d4a2ac7f0ce70eaf2acc5f.diff
LOG: [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
Added:
Modified:
llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
llvm/test/Transforms/ObjCARC/inert-global.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
index b80c1675050b..7dbb95faaf85 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
@@ -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:
diff --git a/llvm/test/Transforms/ObjCARC/inert-global.ll b/llvm/test/Transforms/ObjCARC/inert-global.ll
index 4bb9a809a0f2..c23d2f98b949 100644
--- a/llvm/test/Transforms/ObjCARC/inert-global.ll
+++ b/llvm/test/Transforms/ObjCARC/inert-global.ll
@@ -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
More information about the llvm-commits
mailing list