aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--test/CodeGen/arm-arguments.c28
-rw-r--r--test/CodeGen/arm-vector-arguments.c6
-rw-r--r--test/CodeGen/blocks.c4
-rw-r--r--test/CodeGen/x86_32-arguments-darwin.c18
-rw-r--r--test/CodeGen/x86_64-arguments.c6
-rw-r--r--test/CodeGenCXX/temporaries.cpp6
-rw-r--r--test/CodeGenCXX/x86_32-arguments.cpp8
17 files changed, 108 insertions, 71 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.
diff --git a/test/CodeGen/arm-arguments.c b/test/CodeGen/arm-arguments.c
index 081bc89dcd..3ae3b8ecd2 100644
--- a/test/CodeGen/arm-arguments.c
+++ b/test/CodeGen/arm-arguments.c
@@ -28,13 +28,13 @@ struct s4 { struct s4_0 { int f0; } f0; };
struct s4 f4(void) {}
// APCS-GNU: define void @f5(
-// APCS-GNU: struct.s5* sret
+// APCS-GNU: struct.s5* noalias sret
// AAPCS: define arm_aapcscc i32 @f5()
struct s5 { struct { } f0; int f1; };
struct s5 f5(void) {}
// APCS-GNU: define void @f6(
-// APCS-GNU: struct.s6* sret
+// APCS-GNU: struct.s6* noalias sret
// AAPCS: define arm_aapcscc i32 @f6()
struct s6 { int f0[1]; };
struct s6 f6(void) {}
@@ -45,7 +45,7 @@ struct s7 { struct { int : 0; } f0; };
struct s7 f7(void) {}
// APCS-GNU: define void @f8(
-// APCS-GNU: struct.s8* sret
+// APCS-GNU: struct.s8* noalias sret
// AAPCS: define arm_aapcscc void @f8()
struct s8 { struct { int : 0; } f0[1]; };
struct s8 f8(void) {}
@@ -61,7 +61,7 @@ struct s10 { int f0; int : 0; int : 0; };
struct s10 f10(void) {}
// APCS-GNU: define void @f11(
-// APCS-GNU: struct.s11* sret
+// APCS-GNU: struct.s11* noalias sret
// AAPCS: define arm_aapcscc i32 @f11()
struct s11 { int : 0; int f0; };
struct s11 f11(void) {}
@@ -72,7 +72,7 @@ union u12 { char f0; short f1; int f2; };
union u12 f12(void) {}
// APCS-GNU: define void @f13(
-// APCS-GNU: struct.s13* sret
+// APCS-GNU: struct.s13* noalias sret
// FIXME: This should return a float.
// AAPCS-FIXME: darm_aapcscc efine float @f13()
@@ -80,7 +80,7 @@ struct s13 { float f0; };
struct s13 f13(void) {}
// APCS-GNU: define void @f14(
-// APCS-GNU: union.u14* sret
+// APCS-GNU: union.u14* noalias sret
// AAPCS: define arm_aapcscc i32 @f14()
union u14 { float f0; };
union u14 f14(void) {}
@@ -104,13 +104,13 @@ struct s18 { short f0; char f1 : 4; };
struct s18 f18(void) {}
// APCS-GNU: define void @f19(
-// APCS-GNU: struct.s19* sret
+// APCS-GNU: struct.s19* noalias sret
// AAPCS: define arm_aapcscc i32 @f19()
struct s19 { int f0; struct s8 f1; };
struct s19 f19(void) {}
// APCS-GNU: define void @f20(
-// APCS-GNU: struct.s20* sret
+// APCS-GNU: struct.s20* noalias sret
// AAPCS: define arm_aapcscc i32 @f20()
struct s20 { struct s8 f1; int f0; };
struct s20 f20(void) {}
@@ -128,10 +128,10 @@ struct s21 f21(void) {}
// APCS-GNU: define i128 @f27()
// AAPCS: define arm_aapcscc i16 @f22()
// AAPCS: define arm_aapcscc i32 @f23()
-// AAPCS: define arm_aapcscc void @f24({{.*}} sret
-// AAPCS: define arm_aapcscc void @f25({{.*}} sret
-// AAPCS: define arm_aapcscc void @f26({{.*}} sret
-// AAPCS: define arm_aapcscc void @f27({{.*}} sret
+// AAPCS: define arm_aapcscc void @f24({{.*}} noalias sret
+// AAPCS: define arm_aapcscc void @f25({{.*}} noalias sret
+// AAPCS: define arm_aapcscc void @f26({{.*}} noalias sret
+// AAPCS: define arm_aapcscc void @f27({{.*}} noalias sret
_Complex char f22(void) {}
_Complex short f23(void) {}
_Complex int f24(void) {}
@@ -149,7 +149,7 @@ struct s28 f28() {}
struct s29 { _Complex short f0; };
struct s29 f29() {}
-// APCS-GNU: define void @f30({{.*}} sret
-// AAPCS: define arm_aapcscc void @f30({{.*}} sret
+// APCS-GNU: define void @f30({{.*}} noalias sret
+// AAPCS: define arm_aapcscc void @f30({{.*}} noalias sret
struct s30 { _Complex int f0; };
struct s30 f30() {}
diff --git a/test/CodeGen/arm-vector-arguments.c b/test/CodeGen/arm-vector-arguments.c
index c5ac0a7ad1..6bfb2f48a7 100644
--- a/test/CodeGen/arm-vector-arguments.c
+++ b/test/CodeGen/arm-vector-arguments.c
@@ -8,7 +8,7 @@
#include <arm_neon.h>
-// CHECK: define void @f0(%struct.int8x16x2_t* sret %agg.result, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+// CHECK: define void @f0(%struct.int8x16x2_t* noalias sret %agg.result, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
int8x16x2_t f0(int8x16_t a0, int8x16_t a1) {
return vzipq_s8(a0, a1);
}
@@ -24,7 +24,7 @@ typedef float T_float32x16 __attribute__ ((__vector_size__ (64)));
T_float32x2 f1_0(T_float32x2 a0) { return a0; }
// CHECK: define <4 x float> @f1_1(<4 x float> %{{.*}})
T_float32x4 f1_1(T_float32x4 a0) { return a0; }
-// CHECK: define void @f1_2(<8 x float>* sret %{{.*}}, <8 x float> %{{.*}})
+// CHECK: define void @f1_2(<8 x float>* noalias sret %{{.*}}, <8 x float> %{{.*}})
T_float32x8 f1_2(T_float32x8 a0) { return a0; }
-// CHECK: define void @f1_3(<16 x float>* sret %{{.*}}, <16 x float> %{{.*}})
+// CHECK: define void @f1_3(<16 x float>* noalias sret %{{.*}}, <16 x float> %{{.*}})
T_float32x16 f1_3(T_float32x16 a0) { return a0; }
diff --git a/test/CodeGen/blocks.c b/test/CodeGen/blocks.c
index b7b6a2d505..bef44c3690 100644
--- a/test/CodeGen/blocks.c
+++ b/test/CodeGen/blocks.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o %t -fblocks
+// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - -fblocks | FileCheck %s
void (^f)(void) = ^{};
// rdar://6768379
@@ -12,7 +12,7 @@ struct s0 {
int a[64];
};
-// RUN: grep 'internal void @__f2_block_invoke_0(.struct.s0\* sret .*, .*, .* byval .*)' %t
+// CHECK: define internal void @__f2_block_invoke_0(%struct.s0* noalias sret {{%.*}}, i8* {{%.*}}, %struct.s0* byval align 4 {{.*}})
struct s0 f2(struct s0 a0) {
return ^(struct s0 a1){ return a1; }(a0);
}
diff --git a/test/CodeGen/x86_32-arguments-darwin.c b/test/CodeGen/x86_32-arguments-darwin.c
index 731d4f613f..7727c43f6e 100644
--- a/test/CodeGen/x86_32-arguments-darwin.c
+++ b/test/CodeGen/x86_32-arguments-darwin.c
@@ -71,7 +71,7 @@ struct s10 {
// Small vectors and 1 x {i64,double} are returned in registers
// CHECK: i32 @f11()
-// CHECK: void @f12(<2 x i32>* sret %agg.result)
+// CHECK: void @f12(<2 x i32>* noalias sret %agg.result)
// CHECK: i64 @f13()
// CHECK: i64 @f14()
// CHECK: <2 x i64> @f15()
@@ -93,11 +93,11 @@ T16 f16(void) { while (1) {} }
// 128-bits).
// CHECK: i32 @f17()
-// CHECK: void @f18(%{{.*}}* sret %agg.result)
-// CHECK: void @f19(%{{.*}}* sret %agg.result)
-// CHECK: void @f20(%{{.*}}* sret %agg.result)
-// CHECK: void @f21(%{{.*}}* sret %agg.result)
-// CHECK: void @f22(%{{.*}}* sret %agg.result)
+// CHECK: void @f18(%{{.*}}* noalias sret %agg.result)
+// CHECK: void @f19(%{{.*}}* noalias sret %agg.result)
+// CHECK: void @f20(%{{.*}}* noalias sret %agg.result)
+// CHECK: void @f21(%{{.*}}* noalias sret %agg.result)
+// CHECK: void @f22(%{{.*}}* noalias sret %agg.result)
struct { T11 a; } f17(void) { while (1) {} }
struct { T12 a; } f18(void) { while (1) {} }
struct { T13 a; } f19(void) { while (1) {} }
@@ -116,11 +116,11 @@ struct { struct {} a; struct { float a[1]; } b; } f25(void) { while (1) {} }
// Small structures are handled recursively
// CHECK: i32 @f26()
-// CHECK: void @f27(%struct.s27* sret %agg.result)
+// CHECK: void @f27(%struct.s27* noalias sret %agg.result)
struct s26 { struct { char a, b; } a; struct { char a, b; } b; } f26(void) { while (1) {} }
struct s27 { struct { char a, b, c; } a; struct { char a; } b; } f27(void) { while (1) {} }
-// CHECK: void @f28(%struct.s28* sret %agg.result)
+// CHECK: void @f28(%struct.s28* noalias sret %agg.result)
struct s28 { int a; int b[]; } f28(void) { while (1) {} }
// CHECK: define i16 @f29()
@@ -150,7 +150,7 @@ struct s36 { struct { int : 0; } a[2][10]; char b; char c; } f36(void) { while (
// CHECK: define float @f37()
struct s37 { float c[1][1]; } f37(void) { while (1) {} }
-// CHECK: define void @f38(%struct.s38* sret %agg.result)
+// CHECK: define void @f38(%struct.s38* noalias sret %agg.result)
struct s38 { char a[3]; short b; } f38(void) { while (1) {} }
// CHECK: define void @f39(%struct.s39* byval align 16 %x)
diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c
index 221c7d38a7..8571ac9655 100644
--- a/test/CodeGen/x86_64-arguments.c
+++ b/test/CodeGen/x86_64-arguments.c
@@ -42,7 +42,7 @@ void f7(e7 a0) {
// Test merging/passing of upper eightbyte with X87 class.
//
-// CHECK: define void @f8_1(%union.u8* sret %agg.result)
+// CHECK: define void @f8_1(%union.u8* noalias sret %agg.result)
// CHECK: define void @f8_2(%union.u8* byval align 16 %a0)
union u8 {
long double a;
@@ -58,7 +58,7 @@ struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} }
struct s10 { int a; int b; int : 0; };
void f10(struct s10 a0) {}
-// CHECK: define void @f11(%union.anon* sret %agg.result)
+// CHECK: define void @f11(%union.anon* noalias sret %agg.result)
union { long double a; float b; } f11() { while (1) {} }
// CHECK: define i32 @f12_0()
@@ -69,7 +69,7 @@ void f12_1(struct s12 a0) {}
// Check that sret parameter is accounted for when checking available integer
// registers.
-// CHECK: define void @f13(%struct.s13_0* sret %agg.result, i32 %a, i32 %b, i32 %c, i32 %d, {{.*}}* byval align 8 %e, i32 %f)
+// CHECK: define void @f13(%struct.s13_0* noalias sret %agg.result, i32 %a, i32 %b, i32 %c, i32 %d, {{.*}}* byval align 8 %e, i32 %f)
struct s13_0 { long long f0[3]; };
struct s13_1 { long long f0[2]; };
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index 8aeca653da..98e5ae3e6e 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -395,7 +395,7 @@ namespace Elision {
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]])
}
- // CHECK: define void @_ZN7Elision5test2Ev([[A]]* sret
+ // CHECK: define void @_ZN7Elision5test2Ev([[A]]* noalias sret
A test2() {
// CHECK: call void @_ZN7Elision3fooEv()
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
@@ -403,7 +403,7 @@ namespace Elision {
return (foo(), A());
}
- // CHECK: define void @_ZN7Elision5test3EiNS_1AE([[A]]* sret
+ // CHECK: define void @_ZN7Elision5test3EiNS_1AE([[A]]* noalias sret
A test3(int v, A x) {
if (v < 5)
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
@@ -444,7 +444,7 @@ namespace Elision {
}
// rdar://problem/8433352
- // CHECK: define void @_ZN7Elision5test5Ev([[A]]* sret
+ // CHECK: define void @_ZN7Elision5test5Ev([[A]]* noalias sret
struct B { A a; B(); };
A test5() {
// CHECK: [[AT0:%.*]] = alloca [[A]], align 8
diff --git a/test/CodeGenCXX/x86_32-arguments.cpp b/test/CodeGenCXX/x86_32-arguments.cpp
index 4d4339381d..1cbeb71b22 100644
--- a/test/CodeGenCXX/x86_32-arguments.cpp
+++ b/test/CodeGenCXX/x86_32-arguments.cpp
@@ -6,7 +6,7 @@ struct S {
short s;
};
-// CHECK: define void @_Z1fv(%struct.S* sret %
+// CHECK: define void @_Z1fv(%struct.S* noalias sret %
S f() { return S(); }
// CHECK: define void @_Z1f1S(%struct.S*)
void f(S) { }
@@ -18,7 +18,7 @@ public:
double c;
};
-// CHECK: define void @_Z1gv(%class.C* sret %
+// CHECK: define void @_Z1gv(%class.C* noalias sret %
C g() { return C(); }
// CHECK: define void @_Z1f1C(%class.C*)
@@ -103,13 +103,13 @@ struct s7_1 { double x; };
struct s7 : s7_0, s7_1 { };
s7 f7() { return s7(); }
-// CHECK: define void @_Z2f8v(%struct.s8* sret %agg.result)
+// CHECK: define void @_Z2f8v(%struct.s8* noalias sret %agg.result)
struct s8_0 { };
struct s8_1 { double x; };
struct s8 { s8_0 a; s8_1 b; };
s8 f8() { return s8(); }
-// CHECK: define void @_Z2f9v(%struct.s9* sret %agg.result)
+// CHECK: define void @_Z2f9v(%struct.s9* noalias sret %agg.result)
struct s9_0 { unsigned : 0; };
struct s9_1 { double x; };
struct s9 { s9_0 a; s9_1 b; };