diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -642,21 +642,27 @@ /// A collection of metadata nodes that might be associated with a /// memory access used by the alias-analysis infrastructure. struct AAMDNodes { - explicit AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr, - MDNode *N = nullptr) - : TBAA(T), Scope(S), NoAlias(N) {} + explicit AAMDNodes(MDNode *T = nullptr, MDNode *TS = nullptr, + MDNode *S = nullptr, MDNode *N = nullptr) + : TBAA(T), TBAAStruct(TS), Scope(S), NoAlias(N) {} bool operator==(const AAMDNodes &A) const { - return TBAA == A.TBAA && Scope == A.Scope && NoAlias == A.NoAlias; + return TBAA == A.TBAA && TBAAStruct == A.TBAAStruct && Scope == A.Scope && + NoAlias == A.NoAlias; } bool operator!=(const AAMDNodes &A) const { return !(*this == A); } - explicit operator bool() const { return TBAA || Scope || NoAlias; } + explicit operator bool() const { + return TBAA || TBAAStruct || Scope || NoAlias; + } /// The tag for type-based alias analysis. MDNode *TBAA; + /// The tag for type-based alias analysis (tbaa struct). + MDNode *TBAAStruct; + /// The tag for alias scope specification (used with noalias). MDNode *Scope; @@ -671,6 +677,7 @@ AAMDNodes intersect(const AAMDNodes &Other) { AAMDNodes Result; Result.TBAA = Other.TBAA == TBAA ? TBAA : nullptr; + Result.TBAAStruct = Other.TBAAStruct == TBAAStruct ? TBAAStruct : nullptr; Result.Scope = Other.Scope == Scope ? Scope : nullptr; Result.NoAlias = Other.NoAlias == NoAlias ? NoAlias : nullptr; return Result; @@ -692,6 +699,7 @@ static unsigned getHashValue(const AAMDNodes &Val) { return DenseMapInfo::getHashValue(Val.TBAA) ^ + DenseMapInfo::getHashValue(Val.TBAAStruct) ^ DenseMapInfo::getHashValue(Val.Scope) ^ DenseMapInfo::getHashValue(Val.NoAlias); } diff --git a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp --- a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp +++ b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -521,23 +521,20 @@ } void Instruction::getAAMetadata(AAMDNodes &N, bool Merge) const { - if (Merge) + if (Merge) { N.TBAA = MDNode::getMostGenericTBAA(N.TBAA, getMetadata(LLVMContext::MD_tbaa)); - else - N.TBAA = getMetadata(LLVMContext::MD_tbaa); - - if (Merge) + N.TBAAStruct = nullptr; N.Scope = MDNode::getMostGenericAliasScope( N.Scope, getMetadata(LLVMContext::MD_alias_scope)); - else - N.Scope = getMetadata(LLVMContext::MD_alias_scope); - - if (Merge) N.NoAlias = MDNode::intersect(N.NoAlias, getMetadata(LLVMContext::MD_noalias)); - else + } else { + N.TBAA = getMetadata(LLVMContext::MD_tbaa); + N.TBAAStruct = getMetadata(LLVMContext::MD_tbaa_struct); + N.Scope = getMetadata(LLVMContext::MD_alias_scope); N.NoAlias = getMetadata(LLVMContext::MD_noalias); + } } static const MDNode *createAccessTag(const MDNode *AccessType) { diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -1262,6 +1262,7 @@ void Instruction::setAAMetadata(const AAMDNodes &N) { setMetadata(LLVMContext::MD_tbaa, N.TBAA); + setMetadata(LLVMContext::MD_tbaa_struct, N.TBAAStruct); setMetadata(LLVMContext::MD_alias_scope, N.Scope); setMetadata(LLVMContext::MD_noalias, N.NoAlias); } diff --git a/llvm/test/Transforms/SROA/tbaa-struct.ll b/llvm/test/Transforms/SROA/tbaa-struct.ll --- a/llvm/test/Transforms/SROA/tbaa-struct.ll +++ b/llvm/test/Transforms/SROA/tbaa-struct.ll @@ -11,7 +11,7 @@ ; CHECK-LABEL: @bar( ; CHECK-NEXT: [[X14:%.*]] = call <2 x float> @foo(%vector* [[Y2:%.*]]) ; CHECK-NEXT: [[X7_SROA_0_0_X18_SROA_CAST:%.*]] = bitcast %vector* [[Y2]] to <2 x float>* -; CHECK-NEXT: store <2 x float> [[X14]], <2 x float>* [[X7_SROA_0_0_X18_SROA_CAST]], align 4 +; CHECK-NEXT: store <2 x float> [[X14]], <2 x float>* [[X7_SROA_0_0_X18_SROA_CAST]], align 4, !tbaa.struct !0 ; CHECK-NEXT: ret void ; %x7 = alloca %vector