diff options
-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 | ||||
-rw-r--r-- | test/CodeGen/arm-arguments.c | 28 | ||||
-rw-r--r-- | test/CodeGen/arm-vector-arguments.c | 6 | ||||
-rw-r--r-- | test/CodeGen/blocks.c | 4 | ||||
-rw-r--r-- | test/CodeGen/x86_32-arguments-darwin.c | 18 | ||||
-rw-r--r-- | test/CodeGen/x86_64-arguments.c | 6 | ||||
-rw-r--r-- | test/CodeGenCXX/temporaries.cpp | 6 | ||||
-rw-r--r-- | test/CodeGenCXX/x86_32-arguments.cpp | 8 |
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; }; |