[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