1//===- MemoryModelRelaxationAnnotations.h -----------------------*- 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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// This file provides utility for Memory Model Relaxation Annotations (MMRAs).
11/// Those annotations are represented using Metadata. The MMRATagSet class
12/// offers a simple API to parse the metadata and perform common operations on
13/// it. The MMRAMetadata class is a simple tuple of MDNode that provides easy
14/// access to all MMRA annotations on an instruction.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef LLVM_IR_MEMORYMODELRELAXATIONANNOTATIONS_H
19#define LLVM_IR_MEMORYMODELRELAXATIONANNOTATIONS_H
20
21#include "llvm/ADT/DenseSet.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/Support/Compiler.h"
24#include <tuple> // for std::pair
25
26namespace llvm {
27
28template <typename T> class ArrayRef;
29
30class MDNode;
31class MDTuple;
32class Metadata;
33class raw_ostream;
34class LLVMContext;
35class Instruction;
36
37/// Helper class to manipulate `!mmra` metadata nodes.
38///
39/// This can be visualized as a set of "tags", with each tag
40/// representing a particular property of an instruction, as
41/// explained in the MemoryModelRelaxationAnnotations docs.
42///
43/// This class (and the optimizer in general) does not reason
44/// about the exact nature of the tags and the properties they
45/// imply. It just sees the metadata as a collection of tags, which
46/// are a prefix/suffix pair of strings.
47class MMRAMetadata {
48public:
49 using TagT = std::pair<StringRef, StringRef>;
50 using SetT = DenseSet<TagT>;
51 using const_iterator = SetT::const_iterator;
52
53 /// \name Constructors
54 /// @{
55 MMRAMetadata() = default;
56 LLVM_ABI MMRAMetadata(const Instruction &I);
57 LLVM_ABI MMRAMetadata(MDNode *MD);
58 /// @}
59
60 /// \name Metadata Helpers & Builders
61 /// @{
62
63 /// Combines \p A and \p B according to MMRA semantics.
64 /// \returns !mmra metadata for the combined MMRAs.
65 LLVM_ABI static MDNode *combine(LLVMContext &Ctx, const MMRAMetadata &A,
66 const MMRAMetadata &B);
67
68 /// Creates !mmra metadata for a single tag.
69 ///
70 /// !mmra metadata can either be a single tag, or a MDTuple containing
71 /// multiple tags.
72 LLVM_ABI static MDTuple *getTagMD(LLVMContext &Ctx, StringRef Prefix,
73 StringRef Suffix);
74 static MDTuple *getTagMD(LLVMContext &Ctx, const TagT &T) {
75 return getTagMD(Ctx, Prefix: T.first, Suffix: T.second);
76 }
77
78 /// Creates !mmra metadata from \p Tags.
79 /// \returns nullptr or a MDTuple* from \p Tags.
80 LLVM_ABI static MDTuple *getMD(LLVMContext &Ctx, ArrayRef<TagT> Tags);
81
82 /// \returns true if \p MD is a well-formed MMRA tag.
83 LLVM_ABI static bool isTagMD(const Metadata *MD);
84
85 /// @}
86
87 /// \name Compatibility Helpers
88 /// @{
89
90 /// \returns whether the MMRAs on \p A and \p B are compatible.
91 static bool checkCompatibility(const Instruction &A, const Instruction &B) {
92 return MMRAMetadata(A).isCompatibleWith(Other: B);
93 }
94
95 /// \returns whether this set of tags is compatible with \p Other.
96 LLVM_ABI bool isCompatibleWith(const MMRAMetadata &Other) const;
97
98 /// @}
99
100 /// \name Content Queries
101 /// @{
102
103 LLVM_ABI bool hasTag(StringRef Prefix, StringRef Suffix) const;
104 LLVM_ABI bool hasTagWithPrefix(StringRef Prefix) const;
105
106 LLVM_ABI const_iterator begin() const;
107 LLVM_ABI const_iterator end() const;
108 LLVM_ABI bool empty() const;
109 LLVM_ABI unsigned size() const;
110
111 /// @}
112
113 LLVM_ABI void print(raw_ostream &OS) const;
114 LLVM_ABI void dump() const;
115
116 operator bool() const { return !Tags.empty(); }
117 bool operator==(const MMRAMetadata &Other) const {
118 return Tags == Other.Tags;
119 }
120 bool operator!=(const MMRAMetadata &Other) const {
121 return Tags != Other.Tags;
122 }
123
124private:
125 SetT Tags;
126};
127
128/// \returns true if \p I can have !mmra metadata.
129LLVM_ABI bool canInstructionHaveMMRAs(const Instruction &I);
130
131} // namespace llvm
132
133#endif
134