aboutsummaryrefslogtreecommitdiff
path: root/llvm/include/llvm/IR/MemoryModelRelaxationAnnotations.h
blob: 535635a9ad9b04ad69856876069a417fea4e13b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//===- 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 "llvm/Support/Compiler.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;
  LLVM_ABI MMRAMetadata(const Instruction &I);
  LLVM_ABI MMRAMetadata(MDNode *MD);
  /// @}

  /// \name Metadata Helpers & Builders
  /// @{

  /// Combines \p A and \p B according to MMRA semantics.
  /// \returns !mmra metadata for the combined MMRAs.
  LLVM_ABI 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.
  LLVM_ABI 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.
  LLVM_ABI static MDTuple *getMD(LLVMContext &Ctx, ArrayRef<TagT> Tags);

  /// \returns true if \p MD is a well-formed MMRA tag.
  LLVM_ABI 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.
  LLVM_ABI bool isCompatibleWith(const MMRAMetadata &Other) const;

  /// @}

  /// \name Content Queries
  /// @{

  LLVM_ABI bool hasTag(StringRef Prefix, StringRef Suffix) const;
  LLVM_ABI bool hasTagWithPrefix(StringRef Prefix) const;

  LLVM_ABI const_iterator begin() const;
  LLVM_ABI const_iterator end() const;
  LLVM_ABI bool empty() const;
  LLVM_ABI unsigned size() const;

  /// @}

  LLVM_ABI void print(raw_ostream &OS) const;
  LLVM_ABI 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.
LLVM_ABI bool canInstructionHaveMMRAs(const Instruction &I);

} // namespace llvm

#endif