1//===- llvm/unittests/IR/MemoryModelRelaxationAnnotationsTest.cpp ---------===//
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#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/IR/Metadata.h"
12#include "llvm/IR/Module.h"
13#include "gtest/gtest.h"
14
15using namespace llvm;
16
17namespace {
18
19void checkMMRA(const MMRAMetadata &MMRA,
20 ArrayRef<MMRAMetadata::TagT> Expected) {
21 EXPECT_EQ(MMRA.size(), Expected.size());
22 for (const auto &E : Expected)
23 EXPECT_TRUE(MMRA.hasTag(E.first, E.second));
24}
25
26MMRAMetadata createFromMD(LLVMContext &Ctx,
27 ArrayRef<MMRAMetadata::TagT> Expected) {
28 SmallVector<Metadata *> MD;
29 for (const auto &Tag : Expected)
30 MD.push_back(Elt: MMRAMetadata::getTagMD(Ctx, T: Tag));
31 return MDTuple::get(Context&: Ctx, MDs: MD);
32}
33
34TEST(MMRATest, MDParse) {
35 LLVMContext Ctx;
36
37 // No nesting:
38 // !{!"foo", "!bar"}
39 MDNode *FooBar =
40 MDTuple::get(Context&: Ctx, MDs: {MDString::get(Context&: Ctx, Str: "foo"), MDString::get(Context&: Ctx, Str: "bar")});
41 MMRAMetadata FooBarMMRA(FooBar);
42
43 checkMMRA(MMRA: FooBarMMRA, Expected: {{"foo", "bar"}});
44
45 // Nested:
46 // !{!{!"foo", "!bar"}, !{!"bux", !"qux"}}
47 MDNode *BuxQux =
48 MDTuple::get(Context&: Ctx, MDs: {MDString::get(Context&: Ctx, Str: "bux"), MDString::get(Context&: Ctx, Str: "qux")});
49 MDNode *Nested = MDTuple::get(Context&: Ctx, MDs: {FooBar, BuxQux});
50 MMRAMetadata NestedMMRA(Nested);
51
52 checkMMRA(MMRA: NestedMMRA, Expected: {{"foo", "bar"}, {"bux", "qux"}});
53}
54
55TEST(MMRATest, GetMD) {
56 LLVMContext Ctx;
57
58 EXPECT_EQ(MMRAMetadata::getMD(Ctx, {}), nullptr);
59
60 MDTuple *SingleMD = MMRAMetadata::getMD(Ctx, Tags: {{"foo", "bar"}});
61 EXPECT_EQ(SingleMD->getNumOperands(), 2u);
62 EXPECT_EQ(cast<MDString>(SingleMD->getOperand(0))->getString(), "foo");
63 EXPECT_EQ(cast<MDString>(SingleMD->getOperand(1))->getString(), "bar");
64
65 MDTuple *MultiMD = MMRAMetadata::getMD(Ctx, Tags: {{"foo", "bar"}, {"bux", "qux"}});
66 EXPECT_EQ(MultiMD->getNumOperands(), 2u);
67
68 MDTuple *FooBar = cast<MDTuple>(Val: MultiMD->getOperand(I: 0));
69 EXPECT_EQ(cast<MDString>(FooBar->getOperand(0))->getString(), "foo");
70 EXPECT_EQ(cast<MDString>(FooBar->getOperand(1))->getString(), "bar");
71 MDTuple *BuxQux = cast<MDTuple>(Val: MultiMD->getOperand(I: 1));
72 EXPECT_EQ(cast<MDString>(BuxQux->getOperand(0))->getString(), "bux");
73 EXPECT_EQ(cast<MDString>(BuxQux->getOperand(1))->getString(), "qux");
74}
75
76TEST(MMRATest, Utility) {
77 LLVMContext Ctx;
78 MMRAMetadata MMRA =
79 createFromMD(Ctx, Expected: {{"foo", "0"}, {"foo", "1"}, {"bar", "x"}});
80
81 EXPECT_TRUE(MMRA.hasTagWithPrefix("foo"));
82 EXPECT_TRUE(MMRA.hasTagWithPrefix("bar"));
83 EXPECT_FALSE(MMRA.hasTagWithPrefix("x"));
84
85 EXPECT_TRUE(MMRA.hasTag("foo", "0"));
86 EXPECT_TRUE(MMRA.hasTag("foo", "1"));
87 EXPECT_TRUE(MMRA.hasTag("bar", "x"));
88}
89
90TEST(MMRATest, Operators) {
91 LLVMContext Ctx;
92
93 MMRAMetadata A = createFromMD(Ctx, Expected: {{"foo", "0"}, {"bar", "x"}});
94 MMRAMetadata B = createFromMD(Ctx, Expected: {{"foo", "0"}, {"bar", "y"}});
95
96 // ensure we have different objects by creating copies.
97 EXPECT_EQ(MMRAMetadata(A), MMRAMetadata(A));
98 EXPECT_TRUE((bool)A);
99
100 EXPECT_EQ(MMRAMetadata(B), MMRAMetadata(B));
101 EXPECT_TRUE((bool)B);
102
103 EXPECT_NE(A, B);
104
105 EXPECT_EQ(MMRAMetadata(), MMRAMetadata());
106 EXPECT_NE(A, MMRAMetadata());
107 EXPECT_NE(B, MMRAMetadata());
108
109 MMRAMetadata Empty;
110 EXPECT_FALSE((bool)Empty);
111}
112
113TEST(MMRATest, Compatibility) {
114 LLVMContext Ctx;
115
116 MMRAMetadata Foo0 = createFromMD(Ctx, Expected: {{"foo", "0"}});
117 MMRAMetadata Foo1 = createFromMD(Ctx, Expected: {{"foo", "1"}});
118 MMRAMetadata Foo10 = createFromMD(Ctx, Expected: {{"foo", "0"}, {"foo", "1"}});
119
120 MMRAMetadata Bar = createFromMD(Ctx, Expected: {{"bar", "y"}});
121
122 MMRAMetadata Empty;
123
124 // Other set has no tag with same prefix
125 EXPECT_TRUE(Foo0.isCompatibleWith(Bar));
126 EXPECT_TRUE(Bar.isCompatibleWith(Foo0));
127
128 EXPECT_TRUE(Foo0.isCompatibleWith(Empty));
129 EXPECT_TRUE(Empty.isCompatibleWith(Foo0));
130
131 EXPECT_TRUE(Empty.isCompatibleWith(MMRAMetadata()));
132 EXPECT_TRUE(MMRAMetadata().isCompatibleWith(Empty));
133
134 // Other set has conflicting tags.
135 EXPECT_FALSE(Foo1.isCompatibleWith(Foo0));
136 EXPECT_FALSE(Foo0.isCompatibleWith(Foo1));
137
138 // Both have common tags.
139 EXPECT_TRUE(Foo0.isCompatibleWith(Foo0));
140 EXPECT_TRUE(Foo0.isCompatibleWith(Foo10));
141 EXPECT_TRUE(Foo10.isCompatibleWith(Foo0));
142
143 EXPECT_TRUE(Foo1.isCompatibleWith(Foo1));
144 EXPECT_TRUE(Foo1.isCompatibleWith(Foo10));
145 EXPECT_TRUE(Foo10.isCompatibleWith(Foo1));
146
147 // Try with more prefixes now:
148 MMRAMetadata Multiple0 =
149 createFromMD(Ctx, Expected: {{"foo", "y"}, {"foo", "x"}, {"bar", "z"}});
150 MMRAMetadata Multiple1 =
151 createFromMD(Ctx, Expected: {{"foo", "z"}, {"foo", "x"}, {"bar", "y"}});
152 MMRAMetadata Multiple2 =
153 createFromMD(Ctx, Expected: {{"foo", "z"}, {"foo", "x"}, {"bux", "y"}});
154
155 // Multiple0 and Multiple1 are not compatible because "bar" is getting in the
156 // way.
157 EXPECT_FALSE(Multiple0.isCompatibleWith(Multiple1));
158 EXPECT_FALSE(Multiple1.isCompatibleWith(Multiple0));
159
160 EXPECT_TRUE(Multiple0.isCompatibleWith(Empty));
161 EXPECT_TRUE(Empty.isCompatibleWith(Multiple0));
162 EXPECT_TRUE(Multiple1.isCompatibleWith(Empty));
163 EXPECT_TRUE(Empty.isCompatibleWith(Multiple1));
164
165 // Multiple2 is compatible with both 1/0 because there is always "foo:x" in
166 // common, and the other prefixes are unique to each set.
167 EXPECT_TRUE(Multiple2.isCompatibleWith(Multiple0));
168 EXPECT_TRUE(Multiple0.isCompatibleWith(Multiple2));
169 EXPECT_TRUE(Multiple2.isCompatibleWith(Multiple1));
170 EXPECT_TRUE(Multiple1.isCompatibleWith(Multiple2));
171}
172
173TEST(MMRATest, Combine) {
174 LLVMContext Ctx;
175
176 MMRAMetadata Foo0 = createFromMD(Ctx, Expected: {{"foo", "0"}});
177 MMRAMetadata Foo10 = createFromMD(Ctx, Expected: {{"foo", "0"}, {"foo", "1"}});
178 MMRAMetadata Bar0 = createFromMD(Ctx, Expected: {{"bar", "0"}});
179 MMRAMetadata BarFoo0 = createFromMD(Ctx, Expected: {{"bar", "0"}, {"foo", "0"}});
180
181 {
182 // foo is common to both sets
183 MMRAMetadata Combined = MMRAMetadata::combine(Ctx, A: Foo0, B: Foo10);
184 EXPECT_EQ(Combined, Foo10);
185 }
186
187 {
188 // nothing is common
189 MMRAMetadata Combined = MMRAMetadata::combine(Ctx, A: Foo0, B: Bar0);
190 EXPECT_TRUE(Combined.empty());
191 }
192
193 {
194 // only foo is common.
195 MMRAMetadata Combined = MMRAMetadata::combine(Ctx, A: BarFoo0, B: Foo0);
196 EXPECT_EQ(Combined, Foo0);
197 }
198
199 {
200 // only bar is common.
201 MMRAMetadata Combined = MMRAMetadata::combine(Ctx, A: BarFoo0, B: Bar0);
202 EXPECT_EQ(Combined, Bar0);
203 }
204
205 {
206 // only foo is common
207 MMRAMetadata Combined = MMRAMetadata::combine(Ctx, A: BarFoo0, B: Foo10);
208 EXPECT_EQ(Combined, Foo10);
209 }
210}
211
212} // namespace
213

source code of llvm/unittests/IR/MemoryModelRelaxationAnnotationsTest.cpp