[llvm] r215994 - Small refactor on VectorizerHint for deduplication
Yaron Keren
yaron.keren at gmail.com
Tue Aug 19 11:00:06 PDT 2014
Maybe move init into constructor?
Hint *Hints[3];
...
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) {
Hints[0] = &Width;
Hints[1] = &Unroll;
Hints[2] = &Force;
// Populate values with existing loop metadata.
getHintsFromMetadata();
2014-08-19 20:55 GMT+03:00 Yaron Keren <yaron.keren at gmail.com>:
> Hi Renato,
>
> Visual C++ 2013 does not like:
>
> 1>------ Build started: Project: LLVMVectorize, Configuration:
> RelWithDebInfo Win32 ------
> 1> LoopVectorize.cpp
> 1>..\..\..\..\lib\Transforms\Vectorize\LoopVectorize.cpp(1016): error
> C2536:
> '`anonymous-namespace'::LoopVectorizeHints::`anonymous-namespace'::LoopVectorizeHints::Hints'
> : cannot specify explicit initializer for arrays
> 1> ..\..\..\..\lib\Transforms\Vectorize\LoopVectorize.cpp(1016) :
> see declaration of '`anonymous-namespace'::LoopVectorizeHints::Hints'
> 1> ..\..\..\..\lib\Transforms\Vectorize\LoopVectorize.cpp(1016) :
> see declaration of '`anonymous-namespace'::LoopVectorizeHints::Hints'
> ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
>
> Yaron
>
>
>
> 2014-08-19 20:30 GMT+03:00 Renato Golin <renato.golin at linaro.org>:
>
>> Author: rengolin
>> Date: Tue Aug 19 12:30:43 2014
>> New Revision: 215994
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=215994&view=rev
>> Log:
>> Small refactor on VectorizerHint for deduplication
>>
>> Previously, the hint mechanism relied on clean up passes to remove
>> redundant
>> metadata, which still showed up if running opt at low levels of
>> optimization.
>> That also has shown that multiple nodes of the same type, but with
>> different
>> values could still coexist, even if temporary, and cause confusion if the
>> next pass got the wrong value.
>>
>> This patch makes sure that, if metadata already exists in a loop, the hint
>> mechanism will never append a new node, but always replace the existing
>> one.
>> It also enhances the algorithm to cope with more metadata types in the
>> future
>> by just adding a new type, not a lot of code.
>>
>> Added:
>> llvm/trunk/test/Transforms/LoopVectorize/duplicated-metadata.ll
>> Modified:
>> llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
>>
>> Modified: llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp?rev=215994&r1=215993&r2=215994&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp (original)
>> +++ llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp Tue Aug 19
>> 12:30:43 2014
>> @@ -970,7 +970,54 @@ 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.
>> @@ -979,70 +1026,40 @@ public:
>> };
>>
>> LoopVectorizeHints(const Loop *L, bool DisableUnrolling)
>> - : Width(VectorizationFactor),
>> - Unroll(DisableUnrolling),
>> - Force(FK_Undefined),
>> - LoopID(L->getLoopID()) {
>> - getHints(L);
>> + : 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();
>> +
>> // force-vector-unroll overrides DisableUnrolling.
>> if (VectorizationUnroll.getNumOccurrences() > 0)
>> - Unroll = VectorizationUnroll;
>> + Unroll.Value = VectorizationUnroll;
>>
>> - DEBUG(if (DisableUnrolling && Unroll == 1) dbgs()
>> + DEBUG(if (DisableUnrolling && Unroll.Value == 1) dbgs()
>> << "LV: Unrolling disabled by the pass manager\n");
>> }
>>
>> - /// 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;
>> + void setAlreadyVectorized() {
>> + Width.Value = Unroll.Value = 1;
>> + writeHintsToMetadata({ Width, Unroll });
>> }
>>
>> + /// Dumps all the hint information.
>> std::string emitRemark() const {
>> Report R;
>> - if (Force == LoopVectorizeHints::FK_Disabled)
>> + if (Force.Value == LoopVectorizeHints::FK_Disabled)
>> R << "vectorization is explicitly disabled";
>> else {
>> R << "use -Rpass-analysis=loop-vectorize for more info";
>> - if (Force == LoopVectorizeHints::FK_Enabled) {
>> + if (Force.Value == LoopVectorizeHints::FK_Enabled) {
>> R << " (Force=true";
>> - if (Width != 0)
>> - R << ", Vector Width=" << Width;
>> - if (Unroll != 0)
>> - R << ", Interleave Count=" << Unroll;
>> + if (Width.Value != 0)
>> + R << ", Vector Width=" << Width.Value;
>> + if (Unroll.Value != 0)
>> + R << ", Interleave Count=" << Unroll.Value;
>> R << ")";
>> }
>> }
>> @@ -1050,14 +1067,14 @@ public:
>> return R.str();
>> }
>>
>> - unsigned getWidth() const { return Width; }
>> - unsigned getUnroll() const { return Unroll; }
>> - enum ForceKind getForce() const { return Force; }
>> - MDNode *getLoopID() const { return LoopID; }
>> + unsigned getWidth() const { return Width.Value; }
>> + unsigned getUnroll() const { return Unroll.Value; }
>> + enum ForceKind getForce() const { return (ForceKind)Force.Value; }
>>
>> private:
>> - /// Find hints specified in the loop metadata.
>> - void getHints(const Loop *L) {
>> + /// Find hints specified in the loop metadata and update local values.
>> + void getHintsFromMetadata() {
>> + MDNode *LoopID = TheLoop->getLoopID();
>> if (!LoopID)
>> return;
>>
>> @@ -1086,52 +1103,91 @@ private:
>> continue;
>>
>> // Check if the hint starts with the loop metadata prefix.
>> - StringRef Hint = S->getString();
>> - if (!Hint.startswith(Prefix()))
>> - continue;
>> - // Remove the prefix.
>> - Hint = Hint.substr(Prefix().size(), StringRef::npos);
>> -
>> + StringRef Name = S->getString();
>> if (Args.size() == 1)
>> - getHint(Hint, Args[0]);
>> + setHint(Name, Args[0]);
>> }
>> }
>>
>> - // Check string hint with one operand.
>> - void getHint(StringRef Hint, Value *Arg) {
>> + /// 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);
>> +
>> const ConstantInt *C = dyn_cast<ConstantInt>(Arg);
>> if (!C) return;
>> unsigned Val = C->getZExtValue();
>>
>> - 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');
>> + 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;
>> + }
>> }
>> }
>>
>> - /// Vectorization width.
>> - unsigned Width;
>> - /// Vectorization unroll factor.
>> - unsigned Unroll;
>> - /// Vectorization forced
>> - enum ForceKind Force;
>> + /// 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);
>> + }
>> +
>> + /// 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;
>> + }
>>
>> - MDNode *LoopID;
>> + /// The loop these hints belong to.
>> + const Loop *TheLoop;
>> };
>>
>> static void emitMissedWarning(Function *F, Loop *L,
>> @@ -1393,7 +1449,7 @@ struct LoopVectorize : public FunctionPa
>> }
>>
>> // Mark the loop as already vectorized to avoid vectorizing again.
>> - Hints.setAlreadyVectorized(L);
>> + Hints.setAlreadyVectorized();
>>
>> DEBUG(verifyFunction(*L->getHeader()->getParent()));
>> return true;
>> @@ -2495,7 +2551,7 @@ void InnerLoopVectorizer::createEmptyLoo
>> LoopScalarBody = OldBasicBlock;
>>
>> LoopVectorizeHints Hints(Lp, true);
>> - Hints.setAlreadyVectorized(Lp);
>> + Hints.setAlreadyVectorized();
>> }
>>
>> /// This function returns the identity element (or neutral element) for
>>
>> Added: llvm/trunk/test/Transforms/LoopVectorize/duplicated-metadata.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/duplicated-metadata.ll?rev=215994&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/Transforms/LoopVectorize/duplicated-metadata.ll
>> (added)
>> +++ llvm/trunk/test/Transforms/LoopVectorize/duplicated-metadata.ll Tue
>> Aug 19 12:30:43 2014
>> @@ -0,0 +1,30 @@
>> +; 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}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140819/aa64a195/attachment.html>
More information about the llvm-commits
mailing list