brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 819cad3 Raw
170 lines · cpp
1//===- MemoryModelRelaxationAnnotations.cpp ---------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/IR/MemoryModelRelaxationAnnotations.h"10#include "llvm/IR/Instructions.h"11#include "llvm/IR/Metadata.h"12#include "llvm/Support/Debug.h"13#include "llvm/Support/raw_ostream.h"14 15using namespace llvm;16 17//===- MMRAMetadata -------------------------------------------------------===//18 19MMRAMetadata::MMRAMetadata(const Instruction &I)20    : MMRAMetadata(I.getMetadata(LLVMContext::MD_mmra)) {}21 22MMRAMetadata::MMRAMetadata(MDNode *MD) {23  if (!MD)24    return;25 26  // TODO: Split this into a "tryParse" function that can return an err.27  // CTor can use the tryParse & just fatal on err.28 29  MDTuple *Tuple = dyn_cast<MDTuple>(MD);30  assert(Tuple && "Invalid MMRA structure");31 32  const auto HandleTagMD = [this](MDNode *TagMD) {33    Tags.insert({cast<MDString>(TagMD->getOperand(0))->getString(),34                 cast<MDString>(TagMD->getOperand(1))->getString()});35  };36 37  if (isTagMD(Tuple)) {38    HandleTagMD(Tuple);39    return;40  }41 42  for (const MDOperand &Op : Tuple->operands()) {43    MDNode *MDOp = cast<MDNode>(Op.get());44    assert(isTagMD(MDOp));45    HandleTagMD(MDOp);46  }47}48 49bool MMRAMetadata::isTagMD(const Metadata *MD) {50  if (auto *Tuple = dyn_cast<MDTuple>(MD)) {51    return Tuple->getNumOperands() == 2 &&52           isa<MDString>(Tuple->getOperand(0)) &&53           isa<MDString>(Tuple->getOperand(1));54  }55  return false;56}57 58MDTuple *MMRAMetadata::getTagMD(LLVMContext &Ctx, StringRef Prefix,59                                StringRef Suffix) {60  return MDTuple::get(Ctx,61                      {MDString::get(Ctx, Prefix), MDString::get(Ctx, Suffix)});62}63 64MDTuple *MMRAMetadata::getMD(LLVMContext &Ctx,65                             ArrayRef<MMRAMetadata::TagT> Tags) {66  if (Tags.empty())67    return nullptr;68 69  if (Tags.size() == 1)70    return getTagMD(Ctx, Tags.front());71 72  SmallVector<Metadata *> MMRAs;73  for (const auto &Tag : Tags)74    MMRAs.push_back(getTagMD(Ctx, Tag));75  return MDTuple::get(Ctx, MMRAs);76}77 78MDNode *MMRAMetadata::combine(LLVMContext &Ctx, const MMRAMetadata &A,79                              const MMRAMetadata &B) {80  // Let A and B be two tags set, and U be the prefix-wise union of A and B.81  // For every unique tag prefix P present in A or B:82  // * If either A or B has no tags with prefix P, no tags with prefix83  //   P are added to U.84  // * If both A and B have at least one tag with prefix P, all tags with prefix85  //   P from both sets are added to U.86 87  SmallVector<Metadata *> Result;88 89  for (const auto &[P, S] : A) {90    if (B.hasTagWithPrefix(P))91      Result.push_back(getTagMD(Ctx, P, S));92  }93  for (const auto &[P, S] : B) {94    if (A.hasTagWithPrefix(P))95      Result.push_back(getTagMD(Ctx, P, S));96  }97 98  return MDTuple::get(Ctx, Result);99}100 101bool MMRAMetadata::hasTag(StringRef Prefix, StringRef Suffix) const {102  return Tags.count({Prefix, Suffix});103}104 105bool MMRAMetadata::isCompatibleWith(const MMRAMetadata &Other) const {106  // Two sets of tags are compatible iff, for every unique tag prefix P107  // present in at least one set:108  //   - the other set contains no tag with prefix P, or109  //   - at least one tag with prefix P is common to both sets.110 111  StringMap<bool> PrefixStatuses;112  for (const auto &[P, S] : Tags)113    PrefixStatuses[P] |= (Other.hasTag(P, S) || !Other.hasTagWithPrefix(P));114  for (const auto &[P, S] : Other)115    PrefixStatuses[P] |= (hasTag(P, S) || !hasTagWithPrefix(P));116 117  for (auto &[Prefix, Status] : PrefixStatuses) {118    if (!Status)119      return false;120  }121 122  return true;123}124 125bool MMRAMetadata::hasTagWithPrefix(StringRef Prefix) const {126  for (const auto &[P, S] : Tags)127    if (P == Prefix)128      return true;129  return false;130}131 132MMRAMetadata::const_iterator MMRAMetadata::begin() const {133  return Tags.begin();134}135 136MMRAMetadata::const_iterator MMRAMetadata::end() const { return Tags.end(); }137 138bool MMRAMetadata::empty() const { return Tags.empty(); }139 140unsigned MMRAMetadata::size() const { return Tags.size(); }141 142void MMRAMetadata::print(raw_ostream &OS) const {143  bool IsFirst = true;144  // TODO: use map_iter + join145  for (const auto &[P, S] : Tags) {146    if (IsFirst)147      IsFirst = false;148    else149      OS << ", ";150    OS << P << ":" << S;151  }152}153 154LLVM_DUMP_METHOD155void MMRAMetadata::dump() const { print(dbgs()); }156 157//===- Helpers ------------------------------------------------------------===//158 159static bool isReadWriteMemCall(const Instruction &I) {160  if (const auto *C = dyn_cast<CallBase>(&I))161    return C->mayReadOrWriteMemory() ||162           !C->getMemoryEffects().doesNotAccessMemory();163  return false;164}165 166bool llvm::canInstructionHaveMMRAs(const Instruction &I) {167  return isa<LoadInst>(I) || isa<StoreInst>(I) || isa<AtomicCmpXchgInst>(I) ||168         isa<AtomicRMWInst>(I) || isa<FenceInst>(I) || isReadWriteMemCall(I);169}170