mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-03 09:14:30 +00:00
SLPVectorizer: Move propagateMetadata to VectorUtils
This will be re-used by the LoadStoreVectorizer. Fix handling of range metadata and testcase by Justin Lebar. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274281 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7b7d4b781c
commit
6bcca1a915
@ -113,7 +113,16 @@ MapVector<Instruction*, uint64_t>
|
||||
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
|
||||
|
@ -447,3 +447,44 @@ llvm::computeMinimumValueSizes(ArrayRef<BasicBlock *> Blocks, DemandedBits &DB,
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -463,11 +463,11 @@ protected:
|
||||
/// 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
|
||||
@ -654,28 +654,6 @@ static std::string getDebugLocString(const Loop *L) {
|
||||
}
|
||||
#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
|
||||
@ -685,16 +663,17 @@ void InnerLoopVectorizer::addNewMetadata(Instruction *To,
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -220,46 +220,6 @@ static void propagateIRFlags(Value *I, ArrayRef<Value *> VL) {
|
||||
}
|
||||
}
|
||||
|
||||
/// \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) {
|
||||
|
25
test/Transforms/LoopVectorize/X86/propagate-metadata.ll
Normal file
25
test/Transforms/LoopVectorize/X86/propagate-metadata.ll
Normal file
@ -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}
|
Loading…
x
Reference in New Issue
Block a user