blob: 8feeb8af65a76e5730aebbd3cb103dd15e7609a2 [file] [log] [blame]
//===- 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