Author: rjmccall Date: Wed Oct 21 13:06:31 2015 New Revision: 250916 URL: http://llvm.org/viewvc/llvm-project?rev=250916&view=rev Log: In ARC, peephole the initialization of a __weak variable with a value loaded from a __weak variable into a call to objc_copyWeak or objc_moveWeak.
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/test/CodeGenObjC/arc-blocks.m cfe/trunk/test/CodeGenObjC/arc-foreach.m cfe/trunk/test/CodeGenObjCXX/arc.mm Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=250916&r1=250915&r2=250916&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Wed Oct 21 13:06:31 2015 @@ -597,6 +597,47 @@ static bool isAccessedBy(const ValueDecl return isAccessedBy(*var, e); } +static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, + const LValue &destLV, const Expr *init) { + while (auto castExpr = dyn_cast<CastExpr>(init->IgnoreParens())) { + switch (castExpr->getCastKind()) { + // Look through casts that don't require representation changes. + case CK_NoOp: + case CK_BitCast: + case CK_BlockPointerToObjCPointerCast: + break; + + // If we find an l-value to r-value cast from a __weak variable, + // emit this operation as a copy or move. + case CK_LValueToRValue: { + const Expr *srcExpr = castExpr->getSubExpr(); + if (srcExpr->getType().getObjCLifetime() != Qualifiers::OCL_Weak) + return false; + + // Emit the source l-value. + LValue srcLV = CGF.EmitLValue(srcExpr); + + // If it was an l-value, use objc_copyWeak. + if (srcExpr->getValueKind() == VK_LValue) { + CGF.EmitARCCopyWeak(destLV.getAddress(), srcLV.getAddress()); + } else { + assert(srcExpr->getValueKind() == VK_XValue); + CGF.EmitARCMoveWeak(destLV.getAddress(), srcLV.getAddress()); + } + return true; + } + + // Stop at anything else. + default: + return false; + } + + init = castExpr->getSubExpr(); + continue; + } + return false; +} + static void drillIntoBlockVariable(CodeGenFunction &CGF, LValue &lvalue, const VarDecl *var) { @@ -673,6 +714,12 @@ void CodeGenFunction::EmitScalarInit(con } case Qualifiers::OCL_Weak: { + // If it's not accessed by the initializer, try to emit the + // initialization with a copy or move. + if (!accessedByInit && tryEmitARCCopyWeakInit(*this, lvalue, init)) { + return; + } + // No way to optimize a producing initializer into this. It's not // worth optimizing for, because the value will immediately // disappear in the common case. Modified: cfe/trunk/test/CodeGenObjC/arc-blocks.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-blocks.m?rev=250916&r1=250915&r2=250916&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/arc-blocks.m (original) +++ cfe/trunk/test/CodeGenObjC/arc-blocks.m Wed Oct 21 13:06:31 2015 @@ -263,8 +263,7 @@ void test7(void) { // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT // CHECK: store i32 -1040187392, // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 - // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[VAR]]) - // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]]) + // CHECK-NEXT: call void @objc_copyWeak(i8** [[SLOT]], i8** [[VAR]]) // CHECK: call void @test7_helper( // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}}) // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]]) Modified: cfe/trunk/test/CodeGenObjC/arc-foreach.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-foreach.m?rev=250916&r1=250915&r2=250916&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/arc-foreach.m (original) +++ cfe/trunk/test/CodeGenObjC/arc-foreach.m Wed Oct 21 13:06:31 2015 @@ -110,9 +110,7 @@ void test1(NSArray *array) { // CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 -// CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[X]]) -// CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[T0]], i8* [[T1]]) -// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]]) +// CHECK-LP64-NEXT: call void @objc_copyWeak(i8** [[T0]], i8** [[X]]) // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to // CHECK-LP64: call void @use_block // CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[D0]]) Modified: cfe/trunk/test/CodeGenObjCXX/arc.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc.mm?rev=250916&r1=250915&r2=250916&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjCXX/arc.mm (original) +++ cfe/trunk/test/CodeGenObjCXX/arc.mm Wed Oct 21 13:06:31 2015 @@ -324,3 +324,13 @@ template void test40_helper<int>(); // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[TEMP]] // CHECK-NEXT: call i8* @objc_retain(i8* [[T0]]) +// Check that moves out of __weak variables are compiled to use objc_moveWeak. +void test41(__weak id &&x) { + __weak id y = static_cast<__weak id &&>(x); +} +// CHECK-LABEL: define void @_Z6test41OU6__weakP11objc_object +// CHECK: [[X:%.*]] = alloca i8** +// CHECK: [[Y:%.*]] = alloca i8* +// CHECK: [[T0:%.*]] = load i8**, i8*** [[X]] +// CHECK-NEXT: call void @objc_moveWeak(i8** [[Y]], i8** [[T0]]) +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Y]]) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits