Index: include/llvm/Analysis/VectorUtils.h =================================================================== --- include/llvm/Analysis/VectorUtils.h +++ include/llvm/Analysis/VectorUtils.h @@ -113,7 +113,16 @@ computeMinimumValueSizes(ArrayRef Blocks, DemandedBits &DB, const TargetTransformInfo *TTI=nullptr); - + +/// Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath, +/// MD_nontemporal]. For K in Kinds, we get the MDNode for K from each of the +/// elements of VL, compute their "intersection" (i.e., the most generic +/// metadata value that covers all of the individual values), and set I's +/// metadata for M equal to the intersection value. +/// +/// This function always sets a (possibly null) value for each K in Kinds. +Instruction *propagateMetadata(Instruction *I, ArrayRef VL); + } // llvm namespace #endif Index: lib/Analysis/VectorUtils.cpp =================================================================== --- lib/Analysis/VectorUtils.cpp +++ lib/Analysis/VectorUtils.cpp @@ -447,3 +447,44 @@ return MinBWs; } + +/// \returns \p I after propagating metadata from \p VL. +Instruction *llvm::propagateMetadata(Instruction *Inst, ArrayRef VL) { + Instruction *I0 = cast(VL[0]); + SmallVector, 4> Metadata; + I0->getAllMetadataOtherThanDebugLoc(Metadata); + + for (auto Kind : { LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope, + LLVMContext::MD_noalias, LLVMContext::MD_fpmath, + LLVMContext::MD_nontemporal }) { + MDNode *MD = I0->getMetadata(Kind); + + for (int J = 1, E = VL.size(); MD && J != E; ++J) { + const Instruction *IJ = cast(VL[J]); + MDNode *IMD = IJ->getMetadata(Kind); + switch (Kind) { + case LLVMContext::MD_tbaa: + 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; + case LLVMContext::MD_fpmath: + MD = MDNode::getMostGenericFPMath(MD, IMD); + break; + case LLVMContext::MD_nontemporal: + MD = MDNode::intersect(MD, IMD); + break; + default: + llvm_unreachable("unhandled metadata"); + } + } + + Inst->setMetadata(Kind, MD); + } + + return Inst; +} Index: lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- lib/Transforms/Vectorize/LoopVectorize.cpp +++ lib/Transforms/Vectorize/LoopVectorize.cpp @@ -478,11 +478,11 @@ /// This includes both the original MDs from \p From and additional ones (\see /// addNewMetadata). Use this for *newly created* instructions in the vector /// loop. - void addMetadata(Instruction *To, const Instruction *From); + void addMetadata(Instruction *To, Instruction *From); /// \brief Similar to the previous function but it adds the metadata to a /// vector of instructions. - void addMetadata(SmallVectorImpl &To, const Instruction *From); + void addMetadata(ArrayRef To, Instruction *From); /// This is a helper class that holds the vectorizer state. It maps scalar /// instructions to vector instructions. When the code is 'unrolled' then @@ -669,28 +669,6 @@ } #endif -/// \brief Propagate known metadata from one instruction to another. -static void propagateMetadata(Instruction *To, const Instruction *From) { - SmallVector, 4> Metadata; - From->getAllMetadataOtherThanDebugLoc(Metadata); - - for (auto M : Metadata) { - unsigned Kind = M.first; - - // These are safe to transfer (this is safe for TBAA, even when we - // if-convert, because should that metadata have had a control dependency - // on the condition, and thus actually aliased with some other - // non-speculated memory access when the condition was false, this would be - // caught by the runtime overlap checks). - if (Kind != LLVMContext::MD_tbaa && Kind != LLVMContext::MD_alias_scope && - Kind != LLVMContext::MD_noalias && Kind != LLVMContext::MD_fpmath && - Kind != LLVMContext::MD_nontemporal) - continue; - - To->setMetadata(Kind, M.second); - } -} - void InnerLoopVectorizer::addNewMetadata(Instruction *To, const Instruction *Orig) { // If the loop was versioned with memchecks, add the corresponding no-alias @@ -700,16 +678,17 @@ } void InnerLoopVectorizer::addMetadata(Instruction *To, - const Instruction *From) { + Instruction *From) { propagateMetadata(To, From); addNewMetadata(To, From); } -void InnerLoopVectorizer::addMetadata(SmallVectorImpl &To, - const Instruction *From) { - for (Value *V : To) +void InnerLoopVectorizer::addMetadata(ArrayRef To, + Instruction *From) { + for (Value *V : To) { if (Instruction *I = dyn_cast(V)) addMetadata(I, From); + } } /// \brief The group of interleaved loads/stores sharing the same stride and Index: lib/Transforms/Vectorize/SLPVectorizer.cpp =================================================================== --- lib/Transforms/Vectorize/SLPVectorizer.cpp +++ lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -220,46 +220,6 @@ } } -/// \returns \p I after propagating metadata from \p VL. -static Instruction *propagateMetadata(Instruction *I, ArrayRef VL) { - Instruction *I0 = cast(VL[0]); - SmallVector, 4> Metadata; - I0->getAllMetadataOtherThanDebugLoc(Metadata); - - for (unsigned i = 0, n = Metadata.size(); i != n; ++i) { - unsigned Kind = Metadata[i].first; - MDNode *MD = Metadata[i].second; - - for (int i = 1, e = VL.size(); MD && i != e; i++) { - Instruction *I = cast(VL[i]); - MDNode *IMD = I->getMetadata(Kind); - - switch (Kind) { - default: - MD = nullptr; // Remove unknown metadata - break; - case LLVMContext::MD_tbaa: - 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; - case LLVMContext::MD_fpmath: - MD = MDNode::getMostGenericFPMath(MD, IMD); - break; - case LLVMContext::MD_nontemporal: - MD = MDNode::intersect(MD, IMD); - break; - } - } - I->setMetadata(Kind, MD); - } - return I; -} - /// \returns The type that all of the values in \p VL have or null if there /// are different types. static Type* getSameType(ArrayRef VL) { Index: test/Transforms/LoopVectorize/X86/propagate-metadata.ll =================================================================== --- /dev/null +++ test/Transforms/LoopVectorize/X86/propagate-metadata.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -mtriple="x86_64-unknown-linux-gnu" -loop-vectorize < %s | FileCheck %s + +; Don't crash on unknown metadata +; CHECK-LABEL: @no_propagate_range_metadata( +; CHECK: load <16 x i8> +; CHECK: store <16 x i8> +define void @no_propagate_range_metadata(i8* readonly %first.coerce, i8* readnone %last.coerce, i8* nocapture %result) { +for.body.preheader: + br label %for.body + +for.body: ; preds = %for.body, %for.body.preheader + %result.addr.05 = phi i8* [ %incdec.ptr, %for.body ], [ %result, %for.body.preheader ] + %first.sroa.0.04 = phi i8* [ %incdec.ptr.i.i.i, %for.body ], [ %first.coerce, %for.body.preheader ] + %0 = load i8, i8* %first.sroa.0.04, align 1, !range !0 + store i8 %0, i8* %result.addr.05, align 1 + %incdec.ptr.i.i.i = getelementptr inbounds i8, i8* %first.sroa.0.04, i64 1 + %incdec.ptr = getelementptr inbounds i8, i8* %result.addr.05, i64 1 + %lnot.i = icmp eq i8* %incdec.ptr.i.i.i, %last.coerce + br i1 %lnot.i, label %for.end.loopexit, label %for.body + +for.end.loopexit: ; preds = %for.body + ret void +} + +!0 = !{i8 0, i8 2}