aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/CGCall.cpp1
-rw-r--r--lib/CodeGen/CGClass.cpp9
-rw-r--r--lib/CodeGen/CGDecl.cpp3
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp3
-rw-r--r--lib/CodeGen/CGExpr.cpp3
-rw-r--r--lib/CodeGen/CGExprAgg.cpp54
-rw-r--r--lib/CodeGen/CGObjC.cpp3
-rw-r--r--lib/CodeGen/CGStmt.cpp3
-rw-r--r--lib/CodeGen/CGValue.h21
-rw-r--r--lib/CodeGen/CodeGenFunction.h3
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.