[PATCH] D23619: Refactor metadata copying/swapping code to make it sharable

Xinliang David Li via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 17 14:29:31 PDT 2016


On Wed, Aug 17, 2016 at 1:19 PM, Duncan P. N. Exon Smith
<dexonsmith at apple.com> wrote:
>
>> On 2016-Aug-17, at 11:55, David Li <davidxl at google.com> wrote:
>>
>> davidxl created this revision.
>> davidxl added reviewers: spatel, dexonsmith.
>> davidxl added a subscriber: llvm-commits.
>> Herald added a subscriber: mzolotukhin.
>>
>> No functional change is intended.
>>
>> https://reviews.llvm.org/D23619
>>
>> Files:
>>  include/llvm/IR/Instruction.h
>>  lib/IR/Instruction.cpp
>>  lib/IR/Instructions.cpp
>>  lib/Transforms/Scalar/LoopUnswitch.cpp
>>
>> <D23619.68394.patch>
>
>> Index: lib/Transforms/Scalar/LoopUnswitch.cpp
>> ===================================================================
>> --- lib/Transforms/Scalar/LoopUnswitch.cpp
>> +++ lib/Transforms/Scalar/LoopUnswitch.cpp
>> @@ -742,42 +742,6 @@
>>    return &New;
>>  }
>>
>> -static void copyMetadata(Instruction *DstInst, const Instruction *SrcInst,
>> -                         bool Swapped) {
>> -  if (!SrcInst || !SrcInst->hasMetadata())
>> -    return;
>> -
>> -  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
>> -  SrcInst->getAllMetadata(MDs);
>> -  for (auto &MD : MDs) {
>> -    switch (MD.first) {
>> -    default:
>> -      break;
>> -    case LLVMContext::MD_prof:
>> -      if (Swapped && MD.second->getNumOperands() == 3 &&
>> -          isa<MDString>(MD.second->getOperand(0))) {
>> -        MDString *MDName = cast<MDString>(MD.second->getOperand(0));
>> -        if (MDName->getString() == "branch_weights") {
>> -          auto *ValT = cast_or_null<ConstantAsMetadata>(
>> -                           MD.second->getOperand(1))->getValue();
>> -          auto *ValF = cast_or_null<ConstantAsMetadata>(
>> -                           MD.second->getOperand(2))->getValue();
>> -          assert(ValT && ValF && "Invalid Operands of branch_weights");
>> -          auto NewMD =
>> -              MDBuilder(DstInst->getParent()->getContext())
>> -                  .createBranchWeights(cast<ConstantInt>(ValF)->getZExtValue(),
>> -                                       cast<ConstantInt>(ValT)->getZExtValue());
>> -          MD.second = NewMD;
>> -        }
>> -      }
>> -      // fallthrough.
>> -    case LLVMContext::MD_make_implicit:
>> -    case LLVMContext::MD_dbg:
>> -      DstInst->setMetadata(MD.first, MD.second);
>> -    }
>> -  }
>> -}
>> -
>>  /// Emit a conditional branch on two values if LIC == Val, branch to TrueDst,
>>  /// otherwise branch to FalseDest. Insert the code immediately before InsertPt.
>>  void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
>> @@ -800,7 +764,8 @@
>>
>>    // Insert the new branch.
>>    BranchInst *BI = BranchInst::Create(TrueDest, FalseDest, BranchVal, InsertPt);
>> -  copyMetadata(BI, TI, Swapped);
>> +  if (TI)
>> +    BI->copyMetadata(*TI, Swapped);
>
> This has different semantics than the old code.
>
>   - Previously, only MD_prof (with a possible swap), MD_dbg and
>     MD_make_implicit were copied.
>
>   - Now arbitrary metadata is copied.
>
> Are you sure this makes sense?  Why?

Good question. I checked the original patch review thread, a reviewer
asked white list without given reason.

It does not seem right -- for instance MD_predictable is another valid
MD data that should be copied over.

>
> Another possibility that would let you keep the current semantics:
> copyMetadata could take a list of IDs ( ArrayRef<unsigned>, say) for the
> metadata that should be copied over.

Ok. For the sake of making this NFC, I added more code to deal with
it. To make the default path (clone everything) fast, a new interface
is added to strip all metadata except those specified in white list.
Also added a FIXME there.


>
>>
>>    // If either edge is critical, split it. This helps preserve LoopSimplify
>>    // form for enclosing loops.
>> Index: lib/IR/Instructions.cpp
>> ===================================================================
>> --- lib/IR/Instructions.cpp
>> +++ lib/IR/Instructions.cpp
>> @@ -1209,15 +1209,7 @@
>>
>>    // Update profile metadata if present and it matches our structural
>>    // expectations.
>> -  MDNode *ProfileData = getMetadata(LLVMContext::MD_prof);
>> -  if (!ProfileData || ProfileData->getNumOperands() != 3)
>> -    return;
>> -
>> -  // The first operand is the name. Fetch them backwards and build a new one.
>> -  Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2),
>> -                     ProfileData->getOperand(1)};
>> -  setMetadata(LLVMContext::MD_prof,
>> -              MDNode::get(ProfileData->getContext(), Ops));
>> +  swapProfMetadata();
>
> It looks like swapProfMetadata() could be done separately.
>
>>  }
>>
>>  BasicBlock *BranchInst::getSuccessorV(unsigned idx) const {
>> Index: lib/IR/Instruction.cpp
>> ===================================================================
>> --- lib/IR/Instruction.cpp
>> +++ lib/IR/Instruction.cpp
>> @@ -627,6 +627,41 @@
>>    llvm_unreachable("Subclass of Instruction failed to implement cloneImpl");
>>  }
>>
>> +void Instruction::swapProfMetadata() {
>> +  MDNode *ProfileData = getMetadata(LLVMContext::MD_prof);
>> +  if (!ProfileData || ProfileData->getNumOperands() != 3 ||
>> +      !isa<MDString>(ProfileData->getOperand(0)))
>> +    return;
>> +
>> +  MDString *MDName = cast<MDString>(ProfileData->getOperand(0));
>> +  if (MDName->getString() != "branch_weights")
>> +    return;
>> +
>> +  // The first operand is the name. Fetch them backwards and build a new one.
>> +  Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2),
>> +                     ProfileData->getOperand(1)};
>> +  setMetadata(LLVMContext::MD_prof,
>> +              MDNode::get(ProfileData->getContext(), Ops));
>> +}
>> +
>> +void Instruction::copyMetadata(const Instruction &SrcInst, bool doSwapping) {
>
> "ShouldSwap" seems like a better name for the "doSwapping" parameter.
> However, I wonder whether it makes sense at all here?  Why not just have
> the caller call swapProfMetadata?
>

Now caller is calling the swapping explicitly.


>> +  if (!SrcInst.hasMetadata())
>> +    return;
>> +
>> +  // Otherwise, enumerate and copy over metadata from the old instruction to the
>> +  // new one.
>> +  SmallVector<std::pair<unsigned, MDNode *>, 4> TheMDs;
>> +  SrcInst.getAllMetadataOtherThanDebugLoc(TheMDs);
>> +  for (const auto &MD : TheMDs)
>> +    setMetadata(MD.first, MD.second);
>> +
>> +  setDebugLoc(SrcInst.getDebugLoc());
>> +
>> +  if (doSwapping)
>> +    swapProfMetadata();
>
> I.e., the caller could do this.  Or are you planning to optimize this
> in the future?


No. I think your suggestion is better.

thanks,

David
>
>> +  return;
>> +}
>> +
>>  Instruction *Instruction::clone() const {
>>    Instruction *New = nullptr;
>>    switch (getOpcode()) {
>> @@ -641,16 +676,6 @@
>>    }
>>
>>    New->SubclassOptionalData = SubclassOptionalData;
>> -  if (!hasMetadata())
>> -    return New;
>> -
>> -  // Otherwise, enumerate and copy over metadata from the old instruction to the
>> -  // new one.
>> -  SmallVector<std::pair<unsigned, MDNode *>, 4> TheMDs;
>> -  getAllMetadataOtherThanDebugLoc(TheMDs);
>> -  for (const auto &MD : TheMDs)
>> -    New->setMetadata(MD.first, MD.second);
>> -
>> -  New->setDebugLoc(getDebugLoc());
>> +  New->copyMetadata(*this, false);
>>    return New;
>>  }
>> Index: include/llvm/IR/Instruction.h
>> ===================================================================
>> --- include/llvm/IR/Instruction.h
>> +++ include/llvm/IR/Instruction.h
>> @@ -197,6 +197,15 @@
>>    void setMetadata(unsigned KindID, MDNode *Node);
>>    void setMetadata(StringRef Kind, MDNode *Node);
>>
>> +  /// Copy metadata from \p SrcInst to this instruction. If \p doSwapping
>> +  /// is set to true, \c MD_prof meta data will be swapped.
>> +  void copyMetadata(const Instruction &SrcInst, bool doSwapping);
>
> s/doSwapping/ShouldSwapProf/ (if we keep it).
>
>> +
>> +  /// If the instruction has "branch_weights" MD_prof metadata and the MDNode
>> +  /// has three operands (including name string), swap the order of the
>> +  /// metadata.
>> +  void swapProfMetadata();
>> +
>>    /// Drop all unknown metadata except for debug locations.
>>    /// @{
>>    /// Passes are required to drop metadata they don't understand. This is a
>>
>


More information about the llvm-commits mailing list