mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-30 11:36:08 +00:00
213 lines
6.5 KiB
C++
213 lines
6.5 KiB
C++
//===- llvm/unittests/IR/MemoryModelRelaxationAnnotationsTest.cpp ---------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/IR/Metadata.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
void checkMMRA(const MMRAMetadata &MMRA,
|
|
ArrayRef<MMRAMetadata::TagT> Expected) {
|
|
EXPECT_EQ(MMRA.size(), Expected.size());
|
|
for (const auto &E : Expected)
|
|
EXPECT_TRUE(MMRA.hasTag(E.first, E.second));
|
|
}
|
|
|
|
MMRAMetadata createFromMD(LLVMContext &Ctx,
|
|
ArrayRef<MMRAMetadata::TagT> Expected) {
|
|
SmallVector<Metadata *> MD;
|
|
for (const auto &Tag : Expected)
|
|
MD.push_back(MMRAMetadata::getTagMD(Ctx, Tag));
|
|
return MDTuple::get(Ctx, MD);
|
|
}
|
|
|
|
TEST(MMRATest, MDParse) {
|
|
LLVMContext Ctx;
|
|
|
|
// No nesting:
|
|
// !{!"foo", "!bar"}
|
|
MDNode *FooBar =
|
|
MDTuple::get(Ctx, {MDString::get(Ctx, "foo"), MDString::get(Ctx, "bar")});
|
|
MMRAMetadata FooBarMMRA(FooBar);
|
|
|
|
checkMMRA(FooBarMMRA, {{"foo", "bar"}});
|
|
|
|
// Nested:
|
|
// !{!{!"foo", "!bar"}, !{!"bux", !"qux"}}
|
|
MDNode *BuxQux =
|
|
MDTuple::get(Ctx, {MDString::get(Ctx, "bux"), MDString::get(Ctx, "qux")});
|
|
MDNode *Nested = MDTuple::get(Ctx, {FooBar, BuxQux});
|
|
MMRAMetadata NestedMMRA(Nested);
|
|
|
|
checkMMRA(NestedMMRA, {{"foo", "bar"}, {"bux", "qux"}});
|
|
}
|
|
|
|
TEST(MMRATest, GetMD) {
|
|
LLVMContext Ctx;
|
|
|
|
EXPECT_EQ(MMRAMetadata::getMD(Ctx, {}), nullptr);
|
|
|
|
MDTuple *SingleMD = MMRAMetadata::getMD(Ctx, {{"foo", "bar"}});
|
|
EXPECT_EQ(SingleMD->getNumOperands(), 2u);
|
|
EXPECT_EQ(cast<MDString>(SingleMD->getOperand(0))->getString(), "foo");
|
|
EXPECT_EQ(cast<MDString>(SingleMD->getOperand(1))->getString(), "bar");
|
|
|
|
MDTuple *MultiMD = MMRAMetadata::getMD(Ctx, {{"foo", "bar"}, {"bux", "qux"}});
|
|
EXPECT_EQ(MultiMD->getNumOperands(), 2u);
|
|
|
|
MDTuple *FooBar = cast<MDTuple>(MultiMD->getOperand(0));
|
|
EXPECT_EQ(cast<MDString>(FooBar->getOperand(0))->getString(), "foo");
|
|
EXPECT_EQ(cast<MDString>(FooBar->getOperand(1))->getString(), "bar");
|
|
MDTuple *BuxQux = cast<MDTuple>(MultiMD->getOperand(1));
|
|
EXPECT_EQ(cast<MDString>(BuxQux->getOperand(0))->getString(), "bux");
|
|
EXPECT_EQ(cast<MDString>(BuxQux->getOperand(1))->getString(), "qux");
|
|
}
|
|
|
|
TEST(MMRATest, Utility) {
|
|
LLVMContext Ctx;
|
|
MMRAMetadata MMRA =
|
|
createFromMD(Ctx, {{"foo", "0"}, {"foo", "1"}, {"bar", "x"}});
|
|
|
|
EXPECT_TRUE(MMRA.hasTagWithPrefix("foo"));
|
|
EXPECT_TRUE(MMRA.hasTagWithPrefix("bar"));
|
|
EXPECT_FALSE(MMRA.hasTagWithPrefix("x"));
|
|
|
|
EXPECT_TRUE(MMRA.hasTag("foo", "0"));
|
|
EXPECT_TRUE(MMRA.hasTag("foo", "1"));
|
|
EXPECT_TRUE(MMRA.hasTag("bar", "x"));
|
|
}
|
|
|
|
TEST(MMRATest, Operators) {
|
|
LLVMContext Ctx;
|
|
|
|
MMRAMetadata A = createFromMD(Ctx, {{"foo", "0"}, {"bar", "x"}});
|
|
MMRAMetadata B = createFromMD(Ctx, {{"foo", "0"}, {"bar", "y"}});
|
|
|
|
// ensure we have different objects by creating copies.
|
|
EXPECT_EQ(MMRAMetadata(A), MMRAMetadata(A));
|
|
EXPECT_TRUE((bool)A);
|
|
|
|
EXPECT_EQ(MMRAMetadata(B), MMRAMetadata(B));
|
|
EXPECT_TRUE((bool)B);
|
|
|
|
EXPECT_NE(A, B);
|
|
|
|
EXPECT_EQ(MMRAMetadata(), MMRAMetadata());
|
|
EXPECT_NE(A, MMRAMetadata());
|
|
EXPECT_NE(B, MMRAMetadata());
|
|
|
|
MMRAMetadata Empty;
|
|
EXPECT_FALSE((bool)Empty);
|
|
}
|
|
|
|
TEST(MMRATest, Compatibility) {
|
|
LLVMContext Ctx;
|
|
|
|
MMRAMetadata Foo0 = createFromMD(Ctx, {{"foo", "0"}});
|
|
MMRAMetadata Foo1 = createFromMD(Ctx, {{"foo", "1"}});
|
|
MMRAMetadata Foo10 = createFromMD(Ctx, {{"foo", "0"}, {"foo", "1"}});
|
|
|
|
MMRAMetadata Bar = createFromMD(Ctx, {{"bar", "y"}});
|
|
|
|
MMRAMetadata Empty;
|
|
|
|
// Other set has no tag with same prefix
|
|
EXPECT_TRUE(Foo0.isCompatibleWith(Bar));
|
|
EXPECT_TRUE(Bar.isCompatibleWith(Foo0));
|
|
|
|
EXPECT_TRUE(Foo0.isCompatibleWith(Empty));
|
|
EXPECT_TRUE(Empty.isCompatibleWith(Foo0));
|
|
|
|
EXPECT_TRUE(Empty.isCompatibleWith(MMRAMetadata()));
|
|
EXPECT_TRUE(MMRAMetadata().isCompatibleWith(Empty));
|
|
|
|
// Other set has conflicting tags.
|
|
EXPECT_FALSE(Foo1.isCompatibleWith(Foo0));
|
|
EXPECT_FALSE(Foo0.isCompatibleWith(Foo1));
|
|
|
|
// Both have common tags.
|
|
EXPECT_TRUE(Foo0.isCompatibleWith(Foo0));
|
|
EXPECT_TRUE(Foo0.isCompatibleWith(Foo10));
|
|
EXPECT_TRUE(Foo10.isCompatibleWith(Foo0));
|
|
|
|
EXPECT_TRUE(Foo1.isCompatibleWith(Foo1));
|
|
EXPECT_TRUE(Foo1.isCompatibleWith(Foo10));
|
|
EXPECT_TRUE(Foo10.isCompatibleWith(Foo1));
|
|
|
|
// Try with more prefixes now:
|
|
MMRAMetadata Multiple0 =
|
|
createFromMD(Ctx, {{"foo", "y"}, {"foo", "x"}, {"bar", "z"}});
|
|
MMRAMetadata Multiple1 =
|
|
createFromMD(Ctx, {{"foo", "z"}, {"foo", "x"}, {"bar", "y"}});
|
|
MMRAMetadata Multiple2 =
|
|
createFromMD(Ctx, {{"foo", "z"}, {"foo", "x"}, {"bux", "y"}});
|
|
|
|
// Multiple0 and Multiple1 are not compatible because "bar" is getting in the
|
|
// way.
|
|
EXPECT_FALSE(Multiple0.isCompatibleWith(Multiple1));
|
|
EXPECT_FALSE(Multiple1.isCompatibleWith(Multiple0));
|
|
|
|
EXPECT_TRUE(Multiple0.isCompatibleWith(Empty));
|
|
EXPECT_TRUE(Empty.isCompatibleWith(Multiple0));
|
|
EXPECT_TRUE(Multiple1.isCompatibleWith(Empty));
|
|
EXPECT_TRUE(Empty.isCompatibleWith(Multiple1));
|
|
|
|
// Multiple2 is compatible with both 1/0 because there is always "foo:x" in
|
|
// common, and the other prefixes are unique to each set.
|
|
EXPECT_TRUE(Multiple2.isCompatibleWith(Multiple0));
|
|
EXPECT_TRUE(Multiple0.isCompatibleWith(Multiple2));
|
|
EXPECT_TRUE(Multiple2.isCompatibleWith(Multiple1));
|
|
EXPECT_TRUE(Multiple1.isCompatibleWith(Multiple2));
|
|
}
|
|
|
|
TEST(MMRATest, Combine) {
|
|
LLVMContext Ctx;
|
|
|
|
MMRAMetadata Foo0 = createFromMD(Ctx, {{"foo", "0"}});
|
|
MMRAMetadata Foo10 = createFromMD(Ctx, {{"foo", "0"}, {"foo", "1"}});
|
|
MMRAMetadata Bar0 = createFromMD(Ctx, {{"bar", "0"}});
|
|
MMRAMetadata BarFoo0 = createFromMD(Ctx, {{"bar", "0"}, {"foo", "0"}});
|
|
|
|
{
|
|
// foo is common to both sets
|
|
MMRAMetadata Combined = MMRAMetadata::combine(Ctx, Foo0, Foo10);
|
|
EXPECT_EQ(Combined, Foo10);
|
|
}
|
|
|
|
{
|
|
// nothing is common
|
|
MMRAMetadata Combined = MMRAMetadata::combine(Ctx, Foo0, Bar0);
|
|
EXPECT_TRUE(Combined.empty());
|
|
}
|
|
|
|
{
|
|
// only foo is common.
|
|
MMRAMetadata Combined = MMRAMetadata::combine(Ctx, BarFoo0, Foo0);
|
|
EXPECT_EQ(Combined, Foo0);
|
|
}
|
|
|
|
{
|
|
// only bar is common.
|
|
MMRAMetadata Combined = MMRAMetadata::combine(Ctx, BarFoo0, Bar0);
|
|
EXPECT_EQ(Combined, Bar0);
|
|
}
|
|
|
|
{
|
|
// only foo is common
|
|
MMRAMetadata Combined = MMRAMetadata::combine(Ctx, BarFoo0, Foo10);
|
|
EXPECT_EQ(Combined, Foo10);
|
|
}
|
|
}
|
|
|
|
} // namespace
|