[TBAA] Drop support for "old style" scalar TBAA tags

Summary:
We've had support for auto upgrading old style scalar TBAA access
metadata tags into the "new" struct path aware TBAA metadata for 3 years
now.  The only way to actually generate old style TBAA was explicitly
through the IRBuilder API.  I think this is a good time for dropping
support for old style scalar TBAA.

I'm not removing support for textual or bitcode upgrade -- if you have
IR with the old style scalar TBAA tags that go through the AsmParser orf
the bitcode parser before LLVM sees them, they will keep working as
usual.

Note:

  %val = load i32, i32* %ptr, !tbaa !N
  !N = < scalar tbaa node >

is equivalent to

  %val = load i32, i32* %ptr, !tbaa !M
  !N = < scalar tbaa node >
  !M = !{!N, !N, 0}

Reviewers: manmanren, chandlerc, sunfish

Subscribers: mcrosier, llvm-commits, mgorny

Differential Revision: https://reviews.llvm.org/D26229

llvm-svn: 286291
This commit is contained in:
Sanjoy Das 2016-11-08 20:46:01 +00:00
parent d092107b0e
commit 2582e690b7
5 changed files with 87 additions and 137 deletions

View File

@ -417,15 +417,14 @@ MDNode *MDNode::getMostGenericTBAA(MDNode *A, MDNode *B) {
return A;
// For struct-path aware TBAA, we use the access type of the tag.
bool StructPath = isStructPathTBAA(A) && isStructPathTBAA(B);
if (StructPath) {
A = cast_or_null<MDNode>(MutableTBAAStructTagNode(A).getAccessType());
if (!A)
return nullptr;
B = cast_or_null<MDNode>(MutableTBAAStructTagNode(B).getAccessType());
if (!B)
return nullptr;
}
assert(isStructPathTBAA(A) && isStructPathTBAA(B) &&
"Auto upgrade should have taken care of this!");
A = cast_or_null<MDNode>(MutableTBAAStructTagNode(A).getAccessType());
if (!A)
return nullptr;
B = cast_or_null<MDNode>(MutableTBAAStructTagNode(B).getAccessType());
if (!B)
return nullptr;
SmallSetVector<MDNode *, 4> PathA;
MutableTBAANode TA(A);
@ -457,8 +456,6 @@ MDNode *MDNode::getMostGenericTBAA(MDNode *A, MDNode *B) {
--IA;
--IB;
}
if (!StructPath)
return Ret;
if (!Ret)
return nullptr;
@ -492,52 +489,8 @@ void Instruction::getAAMetadata(AAMDNodes &N, bool Merge) const {
/// Aliases - Test whether the type represented by A may alias the
/// type represented by B.
bool TypeBasedAAResult::Aliases(const MDNode *A, const MDNode *B) const {
// Make sure that both MDNodes are struct-path aware.
if (isStructPathTBAA(A) && isStructPathTBAA(B))
return PathAliases(A, B);
// Keep track of the root node for A and B.
TBAANode RootA, RootB;
// Climb the tree from A to see if we reach B.
for (TBAANode T(A);;) {
if (T.getNode() == B)
// B is an ancestor of A.
return true;
RootA = T;
T = T.getParent();
if (!T.getNode())
break;
}
// Climb the tree from B to see if we reach A.
for (TBAANode T(B);;) {
if (T.getNode() == A)
// A is an ancestor of B.
return true;
RootB = T;
T = T.getParent();
if (!T.getNode())
break;
}
// Neither node is an ancestor of the other.
// If they have different roots, they're part of different potentially
// unrelated type systems, so we must be conservative.
if (RootA.getNode() != RootB.getNode())
return true;
// If they have the same root, then we've proved there's no alias.
return false;
}
/// Test whether the struct-path tag represented by A may alias the
/// struct-path tag represented by B.
bool TypeBasedAAResult::PathAliases(const MDNode *A, const MDNode *B) const {
// Verify that both input nodes are struct-path aware.
// Verify that both input nodes are struct-path aware. Auto-upgrade should
// have taken care of this.
assert(isStructPathTBAA(A) && "MDNode A is not struct-path aware.");
assert(isStructPathTBAA(B) && "MDNode B is not struct-path aware.");

View File

@ -391,6 +391,7 @@ private:
void visitBasicBlock(BasicBlock &BB);
void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty);
void visitDereferenceableMetadata(Instruction& I, MDNode* MD);
void visitTBAAMetadata(Instruction &I, MDNode *MD);
template <class Ty> bool isValidMetadataArray(const MDTuple &N);
#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N);
@ -3658,6 +3659,15 @@ void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) {
"dereferenceable_or_null metadata value must be an i64!", &I);
}
void Verifier::visitTBAAMetadata(Instruction &I, MDNode *MD) {
bool IsStructPathTBAA =
isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3;
Assert(IsStructPathTBAA,
"Old-style TBAA is no longer allowed, use struct-path TBAA instead",
&I);
}
/// verifyInstruction - Verify that an instruction is well formed.
///
void Verifier::visitInstruction(Instruction &I) {
@ -3793,6 +3803,9 @@ void Verifier::visitInstruction(Instruction &I) {
if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null))
visitDereferenceableMetadata(I, MD);
if (MDNode *MD = I.getMetadata(LLVMContext::MD_tbaa))
visitTBAAMetadata(I, MD);
if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) {
Assert(I.getType()->isPointerTy(), "align applies only to pointer types",
&I);

View File

@ -14,7 +14,7 @@ add_llvm_unittest(AnalysisTests
LazyCallGraphTest.cpp
LoopPassManagerTest.cpp
ScalarEvolutionTest.cpp
MixedTBAATest.cpp
TBAATest.cpp
ValueTrackingTest.cpp
UnrollAnalyzer.cpp
)

View File

@ -1,79 +0,0 @@
//===--- MixedTBAATest.cpp - Mixed TBAA unit tests ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
#include "llvm/Analysis/AliasAnalysisEvaluator.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/CommandLine.h"
#include "gtest/gtest.h"
namespace llvm {
namespace {
class MixedTBAATest : public testing::Test {
protected:
MixedTBAATest() : M("MixedTBAATest", C), MD(C) {}
LLVMContext C;
Module M;
MDBuilder MD;
legacy::PassManager PM;
};
TEST_F(MixedTBAATest, MixedTBAA) {
// Setup function.
FunctionType *FTy = FunctionType::get(Type::getVoidTy(C),
std::vector<Type *>(), false);
auto *F = cast<Function>(M.getOrInsertFunction("f", FTy));
auto *BB = BasicBlock::Create(C, "entry", F);
auto IntType = Type::getInt32Ty(C);
auto PtrType = Type::getInt32PtrTy(C);
auto *Value = ConstantInt::get(IntType, 42);
auto *Addr = ConstantPointerNull::get(PtrType);
auto *Store1 = new StoreInst(Value, Addr, BB);
auto *Store2 = new StoreInst(Value, Addr, BB);
ReturnInst::Create(C, nullptr, BB);
// New TBAA metadata
{
auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA");
auto MD1 = MD.createTBAAScalarTypeNode("omnipotent char", RootMD);
auto MD2 = MD.createTBAAScalarTypeNode("int", MD1);
auto MD3 = MD.createTBAAStructTagNode(MD2, MD2, 0);
Store2->setMetadata(LLVMContext::MD_tbaa, MD3);
}
// Old TBAA metadata
{
auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA");
auto MD1 = MD.createTBAANode("omnipotent char", RootMD);
auto MD2 = MD.createTBAANode("int", MD1);
Store1->setMetadata(LLVMContext::MD_tbaa, MD2);
}
// Run the TBAA eval pass on a mixture of path-aware and non-path-aware TBAA.
// The order of the metadata (path-aware vs non-path-aware) is important,
// because the AA eval pass only runs one test per store-pair.
const char* args[] = { "MixedTBAATest", "-evaluate-aa-metadata" };
cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args);
PM.add(createTypeBasedAAWrapperPass());
PM.add(createAAEvalPass());
PM.run(M);
}
} // end anonymous namspace
} // end llvm namespace

View File

@ -0,0 +1,63 @@
//===--- TBAATest.cpp - Mixed TBAA unit tests -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/AliasAnalysisEvaluator.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/CommandLine.h"
#include "gtest/gtest.h"
namespace llvm {
namespace {
class OldTBAATest : public testing::Test {
protected:
OldTBAATest() : M("MixedTBAATest", C), MD(C) {}
LLVMContext C;
Module M;
MDBuilder MD;
};
TEST_F(OldTBAATest, checkVerifierBehavior) {
// C++ unit test case to avoid going through the auto upgrade logic.
FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), {});
auto *F = cast<Function>(M.getOrInsertFunction("f", FTy));
auto *BB = BasicBlock::Create(C, "entry", F);
auto *IntType = Type::getInt32Ty(C);
auto *PtrType = Type::getInt32PtrTy(C);
auto *SI = new StoreInst(ConstantInt::get(IntType, 42),
ConstantPointerNull::get(PtrType), BB);
ReturnInst::Create(C, nullptr, BB);
auto *RootMD = MD.createTBAARoot("Simple C/C++ TBAA");
auto *MD1 = MD.createTBAANode("omnipotent char", RootMD);
auto *MD2 = MD.createTBAANode("int", MD1);
SI->setMetadata(LLVMContext::MD_tbaa, MD2);
SmallVector<char, 0> ErrorMsg;
raw_svector_ostream Outs(ErrorMsg);
StringRef ExpectedFailureMsg(
"Old-style TBAA is no longer allowed, use struct-path TBAA instead");
EXPECT_TRUE(verifyFunction(*F, &Outs));
EXPECT_TRUE(StringRef(ErrorMsg.begin(), ErrorMsg.size())
.startswith(ExpectedFailureMsg));
}
} // end anonymous namspace
} // end llvm namespace