Revert "Small refactor on VectorizerHint for deduplication"

This reverts commit r215994 because MSVC 2012 can't cope with its C++11 goodness.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215999 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Renato Golin 2014-08-19 18:08:50 +00:00
parent 8841fb5f25
commit 8308f0e30f
2 changed files with 92 additions and 178 deletions

View File

@ -970,54 +970,7 @@ private:
/// Utility class for getting and setting loop vectorizer hints in the form
/// of loop metadata.
/// This class keeps a number of loop annotations locally (as member variables)
/// and can, upon request, write them back as metadata on the loop. It will
/// initially scan the loop for existing metadata, and will update the local
/// values based on information in the loop.
/// We cannot write all values to metadata, as the mere presence of some info,
/// for example 'force', means a decision has been made. So, we need to be
/// careful NOT to add them if the user hasn't specifically asked so.
class LoopVectorizeHints {
enum HintKind {
HK_WIDTH,
HK_UNROLL,
HK_FORCE
};
/// Hint - associates name and validation with the hint value.
struct Hint {
const char * Name;
unsigned Value; // This may have to change for non-numeric values.
HintKind Kind;
Hint(const char * Name, unsigned Value, HintKind Kind)
: Name(Name), Value(Value), Kind(Kind) { }
bool validate(unsigned Val) {
switch (Kind) {
case HK_WIDTH:
return isPowerOf2_32(Val) && Val <= MaxVectorWidth;
case HK_UNROLL:
return isPowerOf2_32(Val) && Val <= MaxUnrollFactor;
case HK_FORCE:
return (Val <= 1);
}
return false;
}
};
/// Vectorization width.
Hint Width;
/// Vectorization unroll factor.
Hint Unroll;
/// Vectorization forced
Hint Force;
/// Array to help iterating through all hints.
Hint *Hints[3] = { &Width, &Unroll, &Force };
/// Return the loop metadata prefix.
static StringRef Prefix() { return "llvm.loop."; }
public:
enum ForceKind {
FK_Undefined = -1, ///< Not selected.
@ -1026,40 +979,70 @@ public:
};
LoopVectorizeHints(const Loop *L, bool DisableUnrolling)
: Width("vectorize.width", VectorizationFactor, HK_WIDTH),
Unroll("interleave.count", DisableUnrolling, HK_UNROLL),
Force("vectorize.enable", FK_Undefined, HK_FORCE),
TheLoop(L) {
// Populate values with existing loop metadata.
getHintsFromMetadata();
: Width(VectorizationFactor),
Unroll(DisableUnrolling),
Force(FK_Undefined),
LoopID(L->getLoopID()) {
getHints(L);
// force-vector-unroll overrides DisableUnrolling.
if (VectorizationUnroll.getNumOccurrences() > 0)
Unroll.Value = VectorizationUnroll;
Unroll = VectorizationUnroll;
DEBUG(if (DisableUnrolling && Unroll.Value == 1) dbgs()
DEBUG(if (DisableUnrolling && Unroll == 1) dbgs()
<< "LV: Unrolling disabled by the pass manager\n");
}
/// Mark the loop L as already vectorized by setting the width to 1.
void setAlreadyVectorized() {
Width.Value = Unroll.Value = 1;
writeHintsToMetadata({ Width, Unroll });
/// Return the loop metadata prefix.
static StringRef Prefix() { return "llvm.loop."; }
MDNode *createHint(LLVMContext &Context, StringRef Name, unsigned V) const {
SmallVector<Value*, 2> Vals;
Vals.push_back(MDString::get(Context, Name));
Vals.push_back(ConstantInt::get(Type::getInt32Ty(Context), V));
return MDNode::get(Context, Vals);
}
/// Mark the loop L as already vectorized by setting the width to 1.
void setAlreadyVectorized(Loop *L) {
LLVMContext &Context = L->getHeader()->getContext();
Width = 1;
// Create a new loop id with one more operand for the already_vectorized
// hint. If the loop already has a loop id then copy the existing operands.
SmallVector<Value*, 4> Vals(1);
if (LoopID)
for (unsigned i = 1, ie = LoopID->getNumOperands(); i < ie; ++i)
Vals.push_back(LoopID->getOperand(i));
Vals.push_back(
createHint(Context, Twine(Prefix(), "vectorize.width").str(), Width));
Vals.push_back(
createHint(Context, Twine(Prefix(), "interleave.count").str(), 1));
MDNode *NewLoopID = MDNode::get(Context, Vals);
// Set operand 0 to refer to the loop id itself.
NewLoopID->replaceOperandWith(0, NewLoopID);
L->setLoopID(NewLoopID);
if (LoopID)
LoopID->replaceAllUsesWith(NewLoopID);
LoopID = NewLoopID;
}
/// Dumps all the hint information.
std::string emitRemark() const {
Report R;
if (Force.Value == LoopVectorizeHints::FK_Disabled)
if (Force == LoopVectorizeHints::FK_Disabled)
R << "vectorization is explicitly disabled";
else {
R << "use -Rpass-analysis=loop-vectorize for more info";
if (Force.Value == LoopVectorizeHints::FK_Enabled) {
if (Force == LoopVectorizeHints::FK_Enabled) {
R << " (Force=true";
if (Width.Value != 0)
R << ", Vector Width=" << Width.Value;
if (Unroll.Value != 0)
R << ", Interleave Count=" << Unroll.Value;
if (Width != 0)
R << ", Vector Width=" << Width;
if (Unroll != 0)
R << ", Interleave Count=" << Unroll;
R << ")";
}
}
@ -1067,14 +1050,14 @@ public:
return R.str();
}
unsigned getWidth() const { return Width.Value; }
unsigned getUnroll() const { return Unroll.Value; }
enum ForceKind getForce() const { return (ForceKind)Force.Value; }
unsigned getWidth() const { return Width; }
unsigned getUnroll() const { return Unroll; }
enum ForceKind getForce() const { return Force; }
MDNode *getLoopID() const { return LoopID; }
private:
/// Find hints specified in the loop metadata and update local values.
void getHintsFromMetadata() {
MDNode *LoopID = TheLoop->getLoopID();
/// Find hints specified in the loop metadata.
void getHints(const Loop *L) {
if (!LoopID)
return;
@ -1103,91 +1086,52 @@ private:
continue;
// Check if the hint starts with the loop metadata prefix.
StringRef Name = S->getString();
StringRef Hint = S->getString();
if (!Hint.startswith(Prefix()))
continue;
// Remove the prefix.
Hint = Hint.substr(Prefix().size(), StringRef::npos);
if (Args.size() == 1)
setHint(Name, Args[0]);
getHint(Hint, Args[0]);
}
}
/// Checks string hint with one operand and set value if valid.
void setHint(StringRef Name, Value *Arg) {
if (!Name.startswith(Prefix()))
return;
Name = Name.substr(Prefix().size(), StringRef::npos);
// Check string hint with one operand.
void getHint(StringRef Hint, Value *Arg) {
const ConstantInt *C = dyn_cast<ConstantInt>(Arg);
if (!C) return;
unsigned Val = C->getZExtValue();
for (auto H : Hints) {
if (Name == H->Name) {
if (H->validate(Val))
H->Value = Val;
else
DEBUG(dbgs() << "LV: ignoring invalid hint '" << Name << "'\n");
break;
}
if (Hint == "vectorize.width") {
if (isPowerOf2_32(Val) && Val <= MaxVectorWidth)
Width = Val;
else
DEBUG(dbgs() << "LV: ignoring invalid width hint metadata\n");
} else if (Hint == "vectorize.enable") {
if (C->getBitWidth() == 1)
Force = Val == 1 ? LoopVectorizeHints::FK_Enabled
: LoopVectorizeHints::FK_Disabled;
else
DEBUG(dbgs() << "LV: ignoring invalid enable hint metadata\n");
} else if (Hint == "interleave.count") {
if (isPowerOf2_32(Val) && Val <= MaxUnrollFactor)
Unroll = Val;
else
DEBUG(dbgs() << "LV: ignoring invalid unroll hint metadata\n");
} else {
DEBUG(dbgs() << "LV: ignoring unknown hint " << Hint << '\n');
}
}
/// Create a new hint from name / value pair.
MDNode *createHintMetadata(StringRef Name, unsigned V) const {
LLVMContext &Context = TheLoop->getHeader()->getContext();
SmallVector<Value*, 2> Vals;
Vals.push_back(MDString::get(Context, Name));
Vals.push_back(ConstantInt::get(Type::getInt32Ty(Context), V));
return MDNode::get(Context, Vals);
}
/// Vectorization width.
unsigned Width;
/// Vectorization unroll factor.
unsigned Unroll;
/// Vectorization forced
enum ForceKind Force;
/// Matches metadata with hint name.
bool matchesHintMetadataName(MDNode *Node, std::vector<Hint> &HintTypes) {
MDString* Name = dyn_cast<MDString>(Node->getOperand(0));
if (!Name)
return false;
for (auto H : HintTypes)
if (Name->getName().endswith(H.Name))
return true;
return false;
}
/// Sets current hints into loop metadata, keeping other values intact.
void writeHintsToMetadata(std::vector<Hint> HintTypes) {
if (HintTypes.size() == 0)
return;
// Reserve the first element to LoopID (see below).
SmallVector<Value*, 4> Vals(1);
// If the loop already has metadata, then ignore the existing operands.
MDNode *LoopID = TheLoop->getLoopID();
if (LoopID) {
for (unsigned i = 1, ie = LoopID->getNumOperands(); i < ie; ++i) {
MDNode *Node = cast<MDNode>(LoopID->getOperand(i));
// If node in update list, ignore old value.
if (!matchesHintMetadataName(Node, HintTypes))
Vals.push_back(Node);
}
}
// Now, add the missing hints.
for (auto H : HintTypes)
Vals.push_back(
createHintMetadata(Twine(Prefix(), H.Name).str(), H.Value));
// Replace current metadata node with new one.
LLVMContext &Context = TheLoop->getHeader()->getContext();
MDNode *NewLoopID = MDNode::get(Context, Vals);
// Set operand 0 to refer to the loop id itself.
NewLoopID->replaceOperandWith(0, NewLoopID);
TheLoop->setLoopID(NewLoopID);
if (LoopID)
LoopID->replaceAllUsesWith(NewLoopID);
LoopID = NewLoopID;
}
/// The loop these hints belong to.
const Loop *TheLoop;
MDNode *LoopID;
};
static void emitMissedWarning(Function *F, Loop *L,
@ -1449,7 +1393,7 @@ struct LoopVectorize : public FunctionPass {
}
// Mark the loop as already vectorized to avoid vectorizing again.
Hints.setAlreadyVectorized();
Hints.setAlreadyVectorized(L);
DEBUG(verifyFunction(*L->getHeader()->getParent()));
return true;
@ -2551,7 +2495,7 @@ void InnerLoopVectorizer::createEmptyLoop() {
LoopScalarBody = OldBasicBlock;
LoopVectorizeHints Hints(Lp, true);
Hints.setAlreadyVectorized();
Hints.setAlreadyVectorized(Lp);
}
/// This function returns the identity element (or neutral element) for

View File

@ -1,30 +0,0 @@
; RUN: opt < %s -loop-vectorize -S 2>&1 | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; This test makes sure we don't duplicate the loop vectorizer's metadata
; while marking them as already vectorized (by setting width = 1), even
; at lower optimization levels, where no extra cleanup is done
define void @_Z3fooPf(float* %a) {
entry:
br label %for.body
for.body: ; preds = %for.body, %entry
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
%arrayidx = getelementptr inbounds float* %a, i64 %indvars.iv
%p = load float* %arrayidx, align 4
%mul = fmul float %p, 2.000000e+00
store float %mul, float* %arrayidx, align 4
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
%exitcond = icmp eq i64 %indvars.iv.next, 1024
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
for.end: ; preds = %for.body
ret void
}
!0 = metadata !{metadata !0, metadata !1}
!1 = metadata !{metadata !"llvm.loop.vectorize.width", i32 4}
; CHECK-NOT: !{metadata !"llvm.loop.vectorize.width", i32 4}
; CHECK: !{metadata !"llvm.loop.interleave.count", i32 1}