blob: a9ded6034d0b4e7e9d84699c50cf006fef6ca10d [file] [log] [blame]
//===- MemoryModelRelaxationAnnotations.h -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This file provides utility for Memory Model Relaxation Annotations (MMRAs).
/// Those annotations are represented using Metadata. The MMRATagSet class
/// offers a simple API to parse the metadata and perform common operations on
/// it. The MMRAMetadata class is a simple tuple of MDNode that provides easy
/// access to all MMRA annotations on an instruction.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_MEMORYMODELRELAXATIONANNOTATIONS_H
#define LLVM_IR_MEMORYMODELRELAXATIONANNOTATIONS_H
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include <tuple> // for std::pair
namespace llvm {
template <typename T> class ArrayRef;
class MDNode;
class MDTuple;
class Metadata;
class raw_ostream;
class LLVMContext;
class Instruction;
/// Helper class to manipulate `!mmra` metadata nodes.
///
/// This can be visualized as a set of "tags", with each tag
/// representing a particular property of an instruction, as
/// explained in the MemoryModelRelaxationAnnotations docs.
///
/// This class (and the optimizer in general) does not reason
/// about the exact nature of the tags and the properties they
/// imply. It just sees the metadata as a collection of tags, which
/// are a prefix/suffix pair of strings.
class MMRAMetadata {
public:
using TagT = std::pair<StringRef, StringRef>;
using SetT = DenseSet<TagT>;
using const_iterator = SetT::const_iterator;
/// \name Constructors
/// @{
MMRAMetadata() = default;
MMRAMetadata(const Instruction &I);
MMRAMetadata(MDNode *MD);
/// @}
/// \name Metadata Helpers & Builders
/// @{
/// Combines \p A and \p B according to MMRA semantics.
/// \returns !mmra metadata for the combined MMRAs.
static MDNode *combine(LLVMContext &Ctx, const MMRAMetadata &A,
const MMRAMetadata &B);
/// Creates !mmra metadata for a single tag.
///
/// !mmra metadata can either be a single tag, or a MDTuple containing
/// multiple tags.
static MDTuple *getTagMD(LLVMContext &Ctx, StringRef Prefix,
StringRef Suffix);
static MDTuple *getTagMD(LLVMContext &Ctx, const TagT &T) {
return getTagMD(Ctx, T.first, T.second);
}
/// Creates !mmra metadata from \p Tags.
/// \returns nullptr or a MDTuple* from \p Tags.
static MDTuple *getMD(LLVMContext &Ctx, ArrayRef<TagT> Tags);
/// \returns true if \p MD is a well-formed MMRA tag.
static bool isTagMD(const Metadata *MD);
/// @}
/// \name Compatibility Helpers
/// @{
/// \returns whether the MMRAs on \p A and \p B are compatible.
static bool checkCompatibility(const Instruction &A, const Instruction &B) {
return MMRAMetadata(A).isCompatibleWith(B);
}
/// \returns whether this set of tags is compatible with \p Other.
bool isCompatibleWith(const MMRAMetadata &Other) const;
/// @}
/// \name Content Queries
/// @{
bool hasTag(StringRef Prefix, StringRef Suffix) const;
bool hasTagWithPrefix(StringRef Prefix) const;
const_iterator begin() const;
const_iterator end() const;
bool empty() const;
unsigned size() const;
/// @}
void print(raw_ostream &OS) const;
void dump() const;
operator bool() const { return !Tags.empty(); }
bool operator==(const MMRAMetadata &Other) const {
return Tags == Other.Tags;
}
bool operator!=(const MMRAMetadata &Other) const {
return Tags != Other.Tags;
}
private:
SetT Tags;
};
/// \returns true if \p I can have !mmra metadata.
bool canInstructionHaveMMRAs(const Instruction &I);
} // namespace llvm
#endif