diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 54 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGValue.h | 21 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 3 |
10 files changed, 70 insertions, 33 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index dc3e702d6a..846e1aa393 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -907,6 +907,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // Name the struct return argument. if (CGM.ReturnTypeUsesSRet(FI)) { AI->setName("agg.result"); + AI->addAttr(llvm::Attribute::NoAlias); ++AI; } diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 8e46fcd3ed..8bdfbf1231 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -401,7 +401,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, AggValueSlot AggSlot = AggValueSlot::forAddr(V, Qualifiers(), AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased); CGF.EmitAggExpr(BaseInit->getInit(), AggSlot); @@ -441,7 +442,8 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, AggValueSlot Slot = AggValueSlot::forAddr(Dest, LHS.getQuals(), AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased); CGF.EmitAggExpr(MemberInit->getInit(), Slot); } @@ -1330,7 +1332,8 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor AggValueSlot AggSlot = AggValueSlot::forAddr(ThisPtr, Qualifiers(), AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased); EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 609542c9c6..5fa99a513a 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -1046,7 +1046,8 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init, // TODO: how can we delay here if D is captured by its initializer? EmitAggExpr(init, AggValueSlot::forLValue(lvalue, AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers)); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased)); } } diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index f4bed79527..e4c327b3ab 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -47,7 +47,8 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, CGF.EmitComplexExprIntoAddr(Init, DeclPtr, lv.isVolatile()); } else { CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers)); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased)); } } diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index da892c7715..1ed24ccd65 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -360,7 +360,8 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, = AggValueSlot::IsDestructed_t(InitializedDecl != 0); AggSlot = AggValueSlot::forAddr(ReferenceTemporary, Qualifiers(), isDestructed, - AggValueSlot::DoesNotNeedGCBarriers); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased); } if (InitializedDecl) { diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 4a151fcfb8..c42c87b1ac 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -35,11 +35,18 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { AggValueSlot Dest; bool IgnoreResult; + /// We want to use 'dest' as the return slot except under two + /// conditions: + /// - The destination slot requires garbage collection, so we + /// need to use the GC API. + /// - The destination slot is potentially aliased. + bool shouldUseDestForReturnSlot() const { + return !(Dest.requiresGCollection() || Dest.isPotentiallyAliased()); + } + ReturnValueSlot getReturnValueSlot() const { - // If the destination slot requires garbage collection, we can't - // use the real return value slot, because we have to use the GC - // API. - if (Dest.requiresGCollection()) return ReturnValueSlot(); + if (!shouldUseDestForReturnSlot()) + return ReturnValueSlot(); return ReturnValueSlot(Dest.getAddr(), Dest.isVolatile()); } @@ -69,7 +76,7 @@ public: void EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore = false); void EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore = false); - void EmitGCMove(const Expr *E, RValue Src); + void EmitMoveFromReturnSlot(const Expr *E, RValue Src); AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) { if (CGF.getLangOptions().getGCMode() && TypeRequiresGCollection(T)) @@ -179,23 +186,27 @@ bool AggExprEmitter::TypeRequiresGCollection(QualType T) { return Record->hasObjectMember(); } -/// \brief Perform the final move to DestPtr if RequiresGCollection is set. +/// \brief Perform the final move to DestPtr if for some reason +/// getReturnValueSlot() didn't use it directly. /// /// The idea is that you do something like this: /// RValue Result = EmitSomething(..., getReturnValueSlot()); -/// EmitGCMove(E, Result); -/// If GC doesn't interfere, this will cause the result to be emitted -/// directly into the return value slot. If GC does interfere, a final -/// move will be performed. -void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) { - if (Dest.requiresGCollection()) { - CharUnits size = CGF.getContext().getTypeSizeInChars(E->getType()); - llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); - llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size.getQuantity()); - CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, Dest.getAddr(), - Src.getAggregateAddr(), - SizeVal); +/// EmitMoveFromReturnSlot(E, Result); +/// +/// If nothing interferes, this will cause the result to be emitted +/// directly into the return value slot. Otherwise, a final move +/// will be performed. +void AggExprEmitter::EmitMoveFromReturnSlot(const Expr *E, RValue Src) { + if (shouldUseDestForReturnSlot()) { + // Logically, Dest.getAddr() should equal Src.getAggregateAddr(). + // The possibility of undef rvalues complicates that a lot, + // though, so we can't really assert. + return; } + + // Otherwise, do a final copy, + assert(Dest.getAddr() != Src.getAggregateAddr()); + EmitFinalDestCopy(E, Src, /*Ignore*/ true); } /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. @@ -316,7 +327,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { LValue LV = CGF.EmitLValue(E->getSubExpr()); assert(LV.isPropertyRef()); RValue RV = CGF.EmitLoadOfPropertyRefLValue(LV, getReturnValueSlot()); - EmitGCMove(E, RV); + EmitMoveFromReturnSlot(E, RV); break; } @@ -381,12 +392,12 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E) { } RValue RV = CGF.EmitCallExpr(E, getReturnValueSlot()); - EmitGCMove(E, RV); + EmitMoveFromReturnSlot(E, RV); } void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) { RValue RV = CGF.EmitObjCMessageExpr(E, getReturnValueSlot()); - EmitGCMove(E, RV); + EmitMoveFromReturnSlot(E, RV); } void AggExprEmitter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { @@ -600,6 +611,7 @@ AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) { CGF.EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, Dest.isZeroed())); } else if (LV.isSimple()) { CGF.EmitScalarInit(E, /*D=*/0, LV, /*Captured=*/false); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 83a42fb9c5..179dc75b31 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -820,7 +820,8 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, LoadObjCSelf(), Ivar, 0); EmitAggExpr(IvarInit->getInit(), AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers)); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased)); } // constructor returns 'self'. CodeGenTypes &Types = CGM.getTypes(); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index b7b127fc50..461a173f53 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -786,7 +786,8 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { } else { EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, Qualifiers(), AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers)); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased)); } EmitBranchThroughCleanup(ReturnBlock); diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index dda9693f42..c448949d13 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -347,9 +347,14 @@ class AggValueSlot { /// be set. bool ZeroedFlag : 1; + /// AliasedFlag - This generally defaults to false, but can be true + /// if the memory is known not to be aliased. + bool AliasedFlag : 1; + public: - enum IsZeroed_t { IsNotZeroed, IsZeroed }; + enum IsAliased_t { IsNotAliased, IsAliased }; enum IsDestructed_t { IsNotDestructed, IsDestructed }; + enum IsZeroed_t { IsNotZeroed, IsZeroed }; enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers }; /// ignored - Returns an aggregate value slot indicating that the @@ -358,7 +363,10 @@ public: AggValueSlot AV; AV.Addr = 0; AV.Quals = Qualifiers(); - AV.LifetimeFlag = AV.RequiresGCollection = AV.ZeroedFlag = 0; + AV.LifetimeFlag = AV.RequiresGCollection = AV.ZeroedFlag = false; + + // If there's ever an address here, it will be a temporary. + AV.AliasedFlag = false; return AV; } @@ -375,6 +383,7 @@ public: static AggValueSlot forAddr(llvm::Value *addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, + IsAliased_t isAliased = IsAliased, IsZeroed_t isZeroed = IsNotZeroed) { AggValueSlot AV; AV.Addr = addr; @@ -382,14 +391,16 @@ public: AV.LifetimeFlag = isDestructed; AV.RequiresGCollection = needsGC; AV.ZeroedFlag = isZeroed; + AV.AliasedFlag = isAliased; return AV; } static AggValueSlot forLValue(LValue LV, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, + IsAliased_t isAliased = IsAliased, IsZeroed_t isZeroed = IsNotZeroed) { return forAddr(LV.getAddress(), LV.getQuals(), - isDestructed, needsGC, isZeroed); + isDestructed, needsGC, isAliased, isZeroed); } IsDestructed_t isLifetimeExternallyManaged() const { @@ -421,6 +432,10 @@ public: return Addr == 0; } + IsAliased_t isPotentiallyAliased() const { + return IsAliased_t(AliasedFlag); + } + RValue asRValue() const { return RValue::getAggregate(getAddr(), isVolatile()); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 2d47301ec5..36dcffcd4c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1466,7 +1466,8 @@ public: AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp") { return AggValueSlot::forAddr(CreateMemTemp(T, Name), T.getQualifiers(), AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers); + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased); } /// Emit a cast to void* in the appropriate address space. |