computeMinimumValueSizes(ArrayRef<BasicBlock*> 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<Value *> VL);
+
} // llvm namespace
#endif
return MinBWs;
}
+
+/// \returns \p I after propagating metadata from \p VL.
+Instruction *llvm::propagateMetadata(Instruction *Inst, ArrayRef<Value *> VL) {
+ Instruction *I0 = cast<Instruction>(VL[0]);
+ SmallVector<std::pair<unsigned, MDNode *>, 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<Instruction>(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;
+}
/// 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<Value *> &To, const Instruction *From);
+ void addMetadata(ArrayRef<Value *> 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
}
#endif
-/// \brief Propagate known metadata from one instruction to another.
-static void propagateMetadata(Instruction *To, const Instruction *From) {
- SmallVector<std::pair<unsigned, MDNode *>, 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
}
void InnerLoopVectorizer::addMetadata(Instruction *To,
- const Instruction *From) {
+ Instruction *From) {
propagateMetadata(To, From);
addNewMetadata(To, From);
}
-void InnerLoopVectorizer::addMetadata(SmallVectorImpl<Value *> &To,
- const Instruction *From) {
- for (Value *V : To)
+void InnerLoopVectorizer::addMetadata(ArrayRef<Value *> To,
+ Instruction *From) {
+ for (Value *V : To) {
if (Instruction *I = dyn_cast<Instruction>(V))
addMetadata(I, From);
+ }
}
/// \brief The group of interleaved loads/stores sharing the same stride and
}
}
-/// \returns \p I after propagating metadata from \p VL.
-static Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL) {
- Instruction *I0 = cast<Instruction>(VL[0]);
- SmallVector<std::pair<unsigned, MDNode *>, 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<Instruction>(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<Value *> VL) {
--- /dev/null
+; 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}