diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 66baa962880..da6d5cb5e7c 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -879,6 +879,7 @@ public: static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); + static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B); }; /// \brief Tuple of metadata. diff --git a/lib/Analysis/TypeBasedAliasAnalysis.cpp b/lib/Analysis/TypeBasedAliasAnalysis.cpp index 085ce920139..ff8955870cb 100644 --- a/lib/Analysis/TypeBasedAliasAnalysis.cpp +++ b/lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -623,8 +623,8 @@ void Instruction::getAAMetadata(AAMDNodes &N, bool Merge) const { N.TBAA = getMetadata(LLVMContext::MD_tbaa); if (Merge) - N.Scope = - MDNode::intersect(N.Scope, getMetadata(LLVMContext::MD_alias_scope)); + N.Scope = MDNode::getMostGenericAliasScope( + N.Scope, getMetadata(LLVMContext::MD_alias_scope)); else N.Scope = getMetadata(LLVMContext::MD_alias_scope); diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 6227c209352..55dc96b10bf 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -782,6 +782,28 @@ MDNode *MDNode::intersect(MDNode *A, MDNode *B) { return getOrSelfReference(A->getContext(), MDs); } +MDNode *MDNode::getMostGenericAliasScope(MDNode *A, MDNode *B) { + if (!A || !B) + return nullptr; + + SmallVector MDs(B->op_begin(), B->op_end()); + for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) { + Metadata *MD = A->getOperand(i); + bool insert = true; + for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j) + if (MD == B->getOperand(j)) { + insert = false; + break; + } + if (insert) + MDs.push_back(MD); + } + + // FIXME: This preserves long-standing behaviour, but is it really the right + // behaviour? Or was that an unintended side-effect of node uniquing? + return getOrSelfReference(A->getContext(), MDs); +} + MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) { if (!A || !B) return nullptr; diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 648d605a618..c2dfaf52746 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -1334,6 +1334,8 @@ void llvm::combineMetadata(Instruction *K, const Instruction *J, ArrayRefsetMetadata(Kind, MDNode::getMostGenericTBAA(JMD, KMD)); break; case LLVMContext::MD_alias_scope: + K->setMetadata(Kind, MDNode::getMostGenericAliasScope(JMD, KMD)); + break; case LLVMContext::MD_noalias: K->setMetadata(Kind, MDNode::intersect(JMD, KMD)); break; diff --git a/lib/Transforms/Vectorize/SLPVectorizer.cpp b/lib/Transforms/Vectorize/SLPVectorizer.cpp index d1a843828c3..38763beb744 100644 --- a/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -217,6 +217,8 @@ static Instruction *propagateMetadata(Instruction *I, ArrayRef VL) { MD = MDNode::getMostGenericTBAA(MD, IMD); break; case LLVMContext::MD_alias_scope: + MD = MDNode::getMostGenericAliasScope(MD, IMD); + break; case LLVMContext::MD_noalias: MD = MDNode::intersect(MD, IMD); break; diff --git a/test/Transforms/Util/combine-alias-scope-metadata.ll b/test/Transforms/Util/combine-alias-scope-metadata.ll new file mode 100644 index 00000000000..fd0a3d5c5b9 --- /dev/null +++ b/test/Transforms/Util/combine-alias-scope-metadata.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -S -basicaa -memcpyopt | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define void @test(i8* noalias dereferenceable(1) %in, i8* noalias dereferenceable(1) %out) { + %tmp = alloca i8 + %tmp2 = alloca i8 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %out, i8* %in, i64 1, i32 8, i1 false) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp, i8* %in, i64 1, i32 8, i1 false), !alias.scope !4 + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp2, i8* %tmp, i64 1, i32 8, i1 false), !alias.scope !5 + + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %out, i8* %tmp2, i64 1, i32 8, i1 false), !noalias !6 + + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1) + +!0 = !{!0} +!1 = distinct !{!1, !0, !"in"} +!2 = distinct !{!2, !0, !"tmp"} +!3 = distinct !{!3, !0, !"tmp2"} +!4 = distinct !{!1, !2} +!5 = distinct !{!2, !3} +!6 = distinct !{!1, !2}