Index: lib/CodeGen/CGAtomic.cpp =================================================================== --- lib/CodeGen/CGAtomic.cpp +++ lib/CodeGen/CGAtomic.cpp @@ -1508,11 +1508,12 @@ // which means that the caller is responsible for having zeroed // any padding. Just do an aggregate copy of that type. if (rvalue.isAggregate()) { - CGF.EmitAggregateCopy(getAtomicAddress(), - rvalue.getAggregateAddress(), - getAtomicType(), - (rvalue.isVolatileQualified() - || LVal.isVolatileQualified())); + LValue Dest = CGF.MakeAddrLValue(getAtomicAddress(), getAtomicType()); + LValue Src = CGF.MakeAddrLValue(rvalue.getAggregateAddress(), + getAtomicType()); + bool IsVolatile = rvalue.isVolatileQualified() || + LVal.isVolatileQualified(); + CGF.EmitAggregateCopy(Dest, Src, getAtomicType(), IsVolatile); return; } Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -3544,9 +3544,9 @@ } else { // We can't represent a misaligned lvalue in the CallArgList, so copy // to an aligned temporary now. - Address tmp = CreateMemTemp(type); - EmitAggregateCopy(tmp, L.getAddress(), type, L.isVolatile()); - args.add(RValue::getAggregate(tmp), type); + LValue Dest = MakeAddrLValue(CreateMemTemp(type), type); + EmitAggregateCopy(Dest, L, type, L.isVolatile()); + args.add(RValue::getAggregate(Dest.getAddress()), type); } return; } @@ -3884,7 +3884,9 @@ Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(), "byval-temp", false); IRCallArgs[FirstIRArg] = AI.getPointer(); - EmitAggregateCopy(AI, Addr, I->Ty, RV.isVolatileQualified()); + LValue Dest = MakeAddrLValue(AI, I->Ty); + LValue Src = MakeAddrLValue(Addr, I->Ty); + EmitAggregateCopy(Dest, Src, I->Ty, RV.isVolatileQualified()); } else { // Skip the extra memcpy call. IRCallArgs[FirstIRArg] = Addr.getPointer(); Index: lib/CodeGen/CGClass.cpp =================================================================== --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -640,8 +640,7 @@ LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field); // Copy the aggregate. - CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType, - LHS.isVolatileQualified()); + CGF.EmitAggregateCopy(LHS, Src, FieldType, LHS.isVolatileQualified()); // Ensure that we destroy the objects if an exception is thrown later in // the constructor. QualType::DestructionKind dtorKind = FieldType.isDestructedType(); @@ -2002,10 +2001,10 @@ assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor"); const Expr *Arg = E->getArg(0); - QualType SrcTy = Arg->getType(); - Address Src = EmitLValue(Arg).getAddress(); + LValue Src = EmitLValue(Arg); QualType DestTy = getContext().getTypeDeclType(D->getParent()); - EmitAggregateCopyCtor(This, Src, DestTy, SrcTy); + LValue Dest = MakeAddrLValue(This, DestTy); + EmitAggregateCopyCtor(Dest, Src); return; } @@ -2072,8 +2071,10 @@ QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); Address Src(Args[1].RV.getScalarVal(), getNaturalTypeAlignment(SrcTy)); + LValue SrcLVal = MakeAddrLValue(Src, SrcTy); QualType DestTy = getContext().getTypeDeclType(ClassDecl); - EmitAggregateCopyCtor(This, Src, DestTy, SrcTy); + LValue DestLVal = MakeAddrLValue(This, DestTy); + EmitAggregateCopyCtor(DestLVal, SrcLVal); return; } Index: lib/CodeGen/CGExprAgg.cpp =================================================================== --- lib/CodeGen/CGExprAgg.cpp +++ lib/CodeGen/CGExprAgg.cpp @@ -298,7 +298,9 @@ // If the result of the assignment is used, copy the LHS there also. // It's volatile if either side is. Use the minimum alignment of // the two sides. - CGF.EmitAggregateCopy(dest.getAddress(), src.getAddress(), type, + LValue DestLV = CGF.MakeAddrLValue(dest.getAddress(), type); + LValue SrcLV = CGF.MakeAddrLValue(src.getAddress(), type); + CGF.EmitAggregateCopy(DestLV, SrcLV, type, dest.isVolatile() || src.isVolatile()); } @@ -1541,12 +1543,14 @@ return LV; } -void CodeGenFunction::EmitAggregateCopy(Address DestPtr, - Address SrcPtr, QualType Ty, - bool isVolatile, +void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, + QualType Ty, bool isVolatile, bool isAssignment) { assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); + Address DestPtr = Dest.getAddress(); + Address SrcPtr = Src.getAddress(); + if (getLangOpts().CPlusPlus) { if (const RecordType *RT = Ty->getAs()) { CXXRecordDecl *Record = cast(RT->getDecl()); @@ -1562,7 +1566,7 @@ return; } } - + // Aggregate assignment turns into llvm.memcpy. This is almost valid per // C99 6.5.16.1p3, which states "If the value being stored in an object is // read from another object that overlaps in anyway the storage of the first @@ -1657,4 +1661,10 @@ // the optimizer wishes to expand it in to scalar memory operations. if (llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty)) Inst->setMetadata(llvm::LLVMContext::MD_tbaa_struct, TBAAStructTag); + + if (CGM.getCodeGenOpts().NewStructPathTBAA) { + TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForMemoryTransfer( + Dest.getTBAAInfo(), Src.getTBAAInfo()); + CGM.DecorateInstructionWithTBAA(Inst, TBAAInfo); + } } Index: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -242,11 +242,15 @@ } } - Address This = Address::invalid(); - if (IsArrow) - This = EmitPointerWithAlignment(Base); - else - This = EmitLValue(Base).getAddress(); + LValue This; + if (IsArrow) { + LValueBaseInfo BaseInfo; + TBAAAccessInfo TBAAInfo; + Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); + This = MakeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo); + } else { + This = EmitLValue(Base); + } if (MD->isTrivial() || (MD->isDefaulted() && MD->getParent()->isUnion())) { @@ -264,7 +268,7 @@ (*RtlArgs)[0].RV.getScalarVal(), (*(CE->arg_begin() + 1))->getType()) : EmitLValue(*CE->arg_begin()); - EmitAggregateAssign(This, RHS.getAddress(), CE->getType()); + EmitAggregateAssign(This, RHS, CE->getType()); return RValue::get(This.getPointer()); } @@ -272,8 +276,10 @@ cast(MD)->isCopyOrMoveConstructor()) { // Trivial move and copy ctor are the same. assert(CE->getNumArgs() == 1 && "unexpected argcount for trivial ctor"); - Address RHS = EmitLValue(*CE->arg_begin()).getAddress(); - EmitAggregateCopy(This, RHS, (*CE->arg_begin())->getType()); + const Expr *Arg = *CE->arg_begin(); + LValue RHS = EmitLValue(Arg); + LValue Dest = MakeAddrLValue(This.getAddress(), Arg->getType()); + EmitAggregateCopy(Dest, RHS, Arg->getType()); return RValue::get(This.getPointer()); } llvm_unreachable("unknown trivial member function"); @@ -335,7 +341,8 @@ assert(ReturnValue.isNull() && "Destructor shouldn't have return value"); if (UseVirtualCall) { CGM.getCXXABI().EmitVirtualDestructorCall( - *this, Dtor, Dtor_Complete, This, cast(CE)); + *this, Dtor, Dtor_Complete, This.getAddress(), + cast(CE)); } else { CGCallee Callee; if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) @@ -364,7 +371,8 @@ CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty), Ctor); } else if (UseVirtualCall) { - Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty, + Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, + This.getAddress(), Ty, CE->getLocStart()); } else { if (SanOpts.has(SanitizerKind::CFINVCall) && @@ -372,7 +380,8 @@ llvm::Value *VTable; const CXXRecordDecl *RD; std::tie(VTable, RD) = - CGM.getCXXABI().LoadVTablePtr(*this, This, MD->getParent()); + CGM.getCXXABI().LoadVTablePtr(*this, This.getAddress(), + MD->getParent()); EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getLocStart()); } @@ -388,8 +397,10 @@ } if (MD->isVirtual()) { - This = CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall( - *this, CalleeDecl, This, UseVirtualCall); + Address NewThisAddr = + CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall( + *this, CalleeDecl, This.getAddress(), UseVirtualCall); + This.setAddress(NewThisAddr); } return EmitCXXMemberOrOperatorCall( Index: lib/CodeGen/CGObjC.cpp =================================================================== --- lib/CodeGen/CGObjC.cpp +++ lib/CodeGen/CGObjC.cpp @@ -1008,12 +1008,13 @@ /*init*/ true); return; } - case TEK_Aggregate: + case TEK_Aggregate: { // The return value slot is guaranteed to not be aliased, but // that's not necessarily the same as "on the stack", so // we still potentially need objc_memmove_collectable. - EmitAggregateCopy(ReturnValue, LV.getAddress(), ivarType); - return; + EmitAggregateCopy(/* Dest= */ MakeAddrLValue(ReturnValue, ivarType), + /* Src= */ LV, ivarType); + return; } case TEK_Scalar: { llvm::Value *value; if (propType->isReferenceType()) { Index: lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- lib/CodeGen/CGOpenMPRuntime.cpp +++ lib/CodeGen/CGOpenMPRuntime.cpp @@ -4241,8 +4241,7 @@ // Initialize firstprivate array. if (!isa(Init) || CGF.isTrivialInitializer(Init)) { // Perform simple memcpy. - CGF.EmitAggregateAssign(PrivateLValue.getAddress(), - SharedRefLValue.getAddress(), Type); + CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); } else { // Initialize firstprivate array using element-by-element // initialization. @@ -4534,7 +4533,9 @@ KmpTaskTShareds)), Loc), CGF.getNaturalTypeAlignment(SharedsTy)); - CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy); + LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); + LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); + CGF.EmitAggregateCopy(Dest, Src, SharedsTy); } // Emit initial values for private copies (if any). TaskResultTy Result; Index: lib/CodeGen/CGStmt.cpp =================================================================== --- lib/CodeGen/CGStmt.cpp +++ lib/CodeGen/CGStmt.cpp @@ -1005,7 +1005,9 @@ if (RV.isScalar()) { Builder.CreateStore(RV.getScalarVal(), ReturnValue); } else if (RV.isAggregate()) { - EmitAggregateCopy(ReturnValue, RV.getAggregateAddress(), Ty); + LValue Dest = MakeAddrLValue(ReturnValue, Ty); + LValue Src = MakeAddrLValue(RV.getAggregateAddress(), Ty); + EmitAggregateCopy(Dest, Src, Ty); } else { EmitStoreOfComplex(RV.getComplexVal(), MakeAddrLValue(ReturnValue, Ty), /*init*/ true); Index: lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- lib/CodeGen/CGStmtOpenMP.cpp +++ lib/CodeGen/CGStmtOpenMP.cpp @@ -692,7 +692,9 @@ auto *BO = dyn_cast(Copy); if (BO && BO->getOpcode() == BO_Assign) { // Perform simple memcpy for simple copying. - EmitAggregateAssign(DestAddr, SrcAddr, OriginalType); + LValue Dest = MakeAddrLValue(DestAddr, OriginalType); + LValue Src = MakeAddrLValue(SrcAddr, OriginalType); + EmitAggregateAssign(Dest, Src, OriginalType); } else { // For arrays with complex element types perform element by element // copying. @@ -765,7 +767,8 @@ DeclRefExpr DRE(const_cast(OrigVD), /*RefersToEnclosingVariableOrCapture=*/FD != nullptr, (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); - Address OriginalAddr = EmitLValue(&DRE).getAddress(); + LValue OriginalLVal = EmitLValue(&DRE); + Address OriginalAddr = OriginalLVal.getAddress(); QualType Type = VD->getType(); if (Type->isArrayType()) { // Emit VarDecl with copy init for arrays. @@ -776,8 +779,9 @@ auto *Init = VD->getInit(); if (!isa(Init) || isTrivialInitializer(Init)) { // Perform simple memcpy. - EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr, - Type); + LValue Dest = MakeAddrLValue(Emission.getAllocatedAddress(), + Type); + EmitAggregateAssign(Dest, OriginalLVal, Type); } else { EmitOMPAggregateAssign( Emission.getAllocatedAddress(), OriginalAddr, Type, Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -2101,16 +2101,14 @@ /// /// The difference to EmitAggregateCopy is that tail padding is not copied. /// This is required for correctness when assigning non-POD structures in C++. - void EmitAggregateAssign(Address DestPtr, Address SrcPtr, - QualType EltTy) { + void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy) { bool IsVolatile = hasVolatileMember(EltTy); - EmitAggregateCopy(DestPtr, SrcPtr, EltTy, IsVolatile, true); + EmitAggregateCopy(Dest, Src, EltTy, IsVolatile, /* isAssignment= */ true); } - void EmitAggregateCopyCtor(Address DestPtr, Address SrcPtr, - QualType DestTy, QualType SrcTy) { - EmitAggregateCopy(DestPtr, SrcPtr, SrcTy, /*IsVolatile=*/false, - /*IsAssignment=*/false); + void EmitAggregateCopyCtor(LValue Dest, LValue Src) { + EmitAggregateCopy(Dest, Src, Src.getType(), + /* IsVolatile= */ false, /* IsAssignment= */ false); } /// EmitAggregateCopy - Emit an aggregate copy. @@ -2119,9 +2117,8 @@ /// volatile. /// \param isAssignment - If false, allow padding to be copied. This often /// yields more efficient. - void EmitAggregateCopy(Address DestPtr, Address SrcPtr, - QualType EltTy, bool isVolatile=false, - bool isAssignment = false); + void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, + bool isVolatile = false, bool isAssignment = false); /// GetAddrOfLocalVar - Return the address of a local variable. Address GetAddrOfLocalVar(const VarDecl *VD) { Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -689,6 +689,11 @@ TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, TBAAAccessInfo InfoB); + /// mergeTBAAInfoForMemoryTransfer - Get merged TBAA information for the + /// purposes of memory transfer calls. + TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, + TBAAAccessInfo SrcInfo); + /// getTBAAInfoForSubobject - Get TBAA information for an access with a given /// base lvalue. TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType) { Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -651,6 +651,14 @@ return TBAA->mergeTBAAInfoForConditionalOperator(InfoA, InfoB); } +TBAAAccessInfo +CodeGenModule::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, + TBAAAccessInfo SrcInfo) { + if (!TBAA) + return TBAAAccessInfo(); + return TBAA->mergeTBAAInfoForConditionalOperator(DestInfo, SrcInfo); +} + void CodeGenModule::DecorateInstructionWithTBAA(llvm::Instruction *Inst, TBAAAccessInfo TBAAInfo) { if (llvm::MDNode *Tag = getTBAAAccessTagInfo(TBAAInfo)) Index: lib/CodeGen/CodeGenTBAA.h =================================================================== --- lib/CodeGen/CodeGenTBAA.h +++ lib/CodeGen/CodeGenTBAA.h @@ -201,6 +201,11 @@ /// purpose of conditional operator. TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, TBAAAccessInfo InfoB); + + /// mergeTBAAInfoForMemoryTransfer - Get merged TBAA information for the + /// purpose of memory transfer calls. + TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, + TBAAAccessInfo SrcInfo); }; } // end namespace CodeGen Index: lib/CodeGen/CodeGenTBAA.cpp =================================================================== --- lib/CodeGen/CodeGenTBAA.cpp +++ lib/CodeGen/CodeGenTBAA.cpp @@ -391,3 +391,21 @@ // access type regardless of their base types. return TBAAAccessInfo::getMayAliasInfo(); } + +TBAAAccessInfo +CodeGenTBAA::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, + TBAAAccessInfo SrcInfo) { + if (DestInfo == SrcInfo) + return DestInfo; + + if (!DestInfo || !SrcInfo) + return TBAAAccessInfo(); + + if (DestInfo.isMayAlias() || SrcInfo.isMayAlias()) + return TBAAAccessInfo::getMayAliasInfo(); + + // TODO: Implement the rest of the logic here. For example, two accesses + // with same final access types result in an access to an object of that final + // access type regardless of their base types. + return TBAAAccessInfo::getMayAliasInfo(); +} Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -3902,7 +3902,9 @@ llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true); Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy), caughtExnAlignment); - CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType); + LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType); + LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType); + CGF.EmitAggregateCopy(Dest, Src, CatchType); return; } Index: test/CodeGen/tbaa-struct.cpp =================================================================== --- test/CodeGen/tbaa-struct.cpp +++ test/CodeGen/tbaa-struct.cpp @@ -1,6 +1,11 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - -O1 %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - -O1 %s | \ +// RUN: FileCheck -check-prefixes=CHECK,CHECK-OLD %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -new-struct-path-tbaa \ +// RUN: -emit-llvm -o - -O1 %s | \ +// RUN: FileCheck -check-prefixes=CHECK,CHECK-NEW %s // -// Check that we generate !tbaa.struct metadata for struct copies. +// Check that we generate TBAA metadata for struct copies correctly. + struct A { short s; int i; @@ -8,68 +13,117 @@ int j; }; -void copy(struct A *a, struct A *b) { - *a = *b; -} +typedef A __attribute__((may_alias)) AA; -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 16, i1 false), !tbaa.struct [[TS:!.*]] +void copy(A *a1, A *a2) { +// CHECK-LABEL: _Z4copyP1AS0_ +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 16, i1 false) +// CHECK-OLD-SAME: !tbaa.struct [[TS:!.*]] +// CHECK-NEW-SAME: !tbaa [[TAG_A:![0-9]*]] + *a1 = *a2; +} struct B { - char c1; - struct A a; - int ii; + char c; + A a; + int i; }; -void copy2(struct B *a, struct B *b) { - *a = *b; +void copy2(B *b1, B *b2) { +// CHECK-LABEL: _Z5copy2P1BS0_ +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 24, i1 false) +// CHECK-OLD-SAME: !tbaa.struct [[TS2:!.*]] +// CHECK-NEW-SAME: !tbaa [[TAG_B:![0-9]*]] + *b1 = *b2; } -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 24, i1 false), !tbaa.struct [[TS2:!.*]] +struct S { + _Complex char cc; + _Complex int ci; +}; -typedef _Complex int T2; -typedef _Complex char T5; -typedef _Complex int T7; -typedef struct T4 { T5 field0; T7 field1; } T4; -typedef union T1 { T2 field0; T4 field1; } T1; +union U { + _Complex int ci; + S s; +}; -void copy3 (T1 *a, T1 *b) { - *a = *b; +void copy3(U *u1, U *u2) { +// CHECK-LABEL: _Z5copy3P1US0_ +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 12, i1 false) +// CHECK-OLD-SAME: !tbaa.struct [[TS3:!.*]] +// CHECK-NEW-SAME: !tbaa [[TAG_U:![0-9]*]] + *u1 = *u2; } -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 12, i1 false), !tbaa.struct [[TS3:!.*]] - // Make sure that zero-length bitfield works. -#define ATTR __attribute__ ((ms_struct)) -struct five { +struct C { char a; - int :0; /* ignored; prior field is not a bitfield. */ + int : 0; // Shall not be ignored; see r185018. char b; char c; -} ATTR; -void copy4(struct five *a, struct five *b) { - *a = *b; +} __attribute__((ms_struct)); + +void copy4(C *c1, C *c2) { +// CHECK-LABEL: _Z5copy4P1CS0_ +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 3, i1 false) +// CHECK-OLD-SAME: !tbaa.struct [[TS4:!.*]] +// CHECK-NEW-SAME: !tbaa [[TAG_C:![0-9]*]] + *c1 = *c2; } -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 3, i1 false), !tbaa.struct [[TS4:!.*]] -struct six { +struct D { char a; - int :0; + int : 0; char b; char c; }; -void copy5(struct six *a, struct six *b) { - *a = *b; + +void copy5(D *d1, D *d2) { +// CHECK-LABEL: _Z5copy5P1DS0_ +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 6, i1 false) +// CHECK-OLD-SAME: !tbaa.struct [[TS5:!.*]] +// CHECK-NEW-SAME: !tbaa [[TAG_D:![0-9]*]] + *d1 = *d2; +} + +void copy6(AA *a1, A *a2) { +// CHECK-LABEL: _Z5copy6P1AS0_ +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 16, i1 false) +// CHECK-OLD-SAME: !tbaa.struct [[TS]] +// CHECK-NEW-SAME: !tbaa [[TAG_char:![0-9]*]] + *a1 = *a2; +} + +void copy7(A *a1, AA *a2) { +// CHECK-LABEL: _Z5copy7P1AS0_ +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 16, i1 false) +// CHECK-OLD-SAME: !tbaa.struct [[TS]] +// CHECK-NEW-SAME: !tbaa [[TAG_char]] + *a1 = *a2; } -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 6, i1 false), !tbaa.struct [[TS5:!.*]] -// CHECK: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}} -// CHECK: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}} -// CHECK: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0} -// CHECK: [[INT]] = !{!"int", [[CHAR]] -// CHECK: [[TAG_CHAR:!.*]] = !{[[CHAR]], [[CHAR]], i64 0} +// CHECK-OLD: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}} +// CHECK-OLD: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}} +// CHECK-OLD: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0} +// CHECK-OLD: [[INT]] = !{!"int", [[CHAR]] +// CHECK-OLD: [[TAG_CHAR:!.*]] = !{[[CHAR]], [[CHAR]], i64 0} // (offset, size) = (0,1) char; (4,2) short; (8,4) int; (12,1) char; (16,4) int; (20,4) int -// CHECK: [[TS2]] = !{i64 0, i64 1, !{{.*}}, i64 4, i64 2, !{{.*}}, i64 8, i64 4, !{{.*}}, i64 12, i64 1, !{{.*}}, i64 16, i64 4, {{.*}}, i64 20, i64 4, {{.*}}} +// CHECK-OLD: [[TS2]] = !{i64 0, i64 1, !{{.*}}, i64 4, i64 2, !{{.*}}, i64 8, i64 4, !{{.*}}, i64 12, i64 1, !{{.*}}, i64 16, i64 4, {{.*}}, i64 20, i64 4, {{.*}}} // (offset, size) = (0,8) char; (0,2) char; (4,8) char -// CHECK: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}} -// CHECK: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 4, [[TAG_INT]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]} -// CHECK: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 4, [[TAG_INT]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]} +// CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}} +// CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 4, [[TAG_INT]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]} +// CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 4, [[TAG_INT]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]} + +// CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"} +// CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0} +// CHECK-NEW-DAG: [[TYPE_short:!.*]] = !{[[TYPE_char]], i64 2, !"short"} +// CHECK-NEW-DAG: [[TYPE_int:!.*]] = !{[[TYPE_char]], i64 4, !"int"} +// CHECK-NEW-DAG: [[TYPE_A:!.*]] = !{[[TYPE_char]], i64 16, !"_ZTS1A", [[TYPE_short]], i64 0, i64 2, [[TYPE_int]], i64 4, i64 4, [[TYPE_char]], i64 8, i64 1, [[TYPE_int]], i64 12, i64 4} +// CHECK-NEW-DAG: [[TAG_A]] = !{[[TYPE_A]], [[TYPE_A]], i64 0, i64 16} +// CHECK-NEW-DAG: [[TYPE_B:!.*]] = !{[[TYPE_char]], i64 24, !"_ZTS1B", [[TYPE_char]], i64 0, i64 1, [[TYPE_A]], i64 4, i64 16, [[TYPE_int]], i64 20, i64 4} +// CHECK-NEW-DAG: [[TAG_B]] = !{[[TYPE_B]], [[TYPE_B]], i64 0, i64 24} +// CHECK-NEW-DAG: [[TAG_U]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 12} +// CHECK-NEW-DAG: [[TYPE_C:!.*]] = !{[[TYPE_char]], i64 3, !"_ZTS1C", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 1, i64 4, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1} +// CHECK-NEW-DAG: [[TAG_C]] = !{[[TYPE_C]], [[TYPE_C]], i64 0, i64 3} +// CHECK-NEW-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS1D", [[TYPE_char]], i64 0, i64 1, [[TYPE_int]], i64 4, i64 4, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1} +// CHECK-NEW-DAG: [[TAG_D]] = !{[[TYPE_D]], [[TYPE_D]], i64 0, i64 6}