From 0dd1c441f1c5851ea5a24445f09df99a7e785c85 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Mon, 13 Apr 2015 23:05:45 +0000 Subject: [PATCH] Make getModRefInfo with a default location not crash. Add getModRefInfo that works without location. Add unit tests. llvm-svn: 234811 --- include/llvm/Analysis/AliasAnalysis.h | 18 +++++ lib/Analysis/AliasAnalysis.cpp | 21 +++--- unittests/Analysis/AliasAnalysisTest.cpp | 94 ++++++++++++++++++++++++ unittests/Analysis/CMakeLists.txt | 1 + 4 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 unittests/Analysis/AliasAnalysisTest.cpp diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 43bcc343d36..9ce394c0984 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -352,6 +352,24 @@ public: return (MRB & ModRef) && (MRB & ArgumentPointees); } + /// getModRefInfo - Return information about whether or not an + /// instruction may read or write memory (without regard to a + /// specific location) + ModRefResult getModRefInfo(const Instruction *I) { + if (auto CS = ImmutableCallSite(I)) { + auto MRB = getModRefBehavior(CS); + if (MRB & ModRef) + return ModRef; + else if (MRB & Ref) + return Ref; + else if (MRB & Mod) + return Mod; + return NoModRef; + } + + return getModRefInfo(I, Location()); + } + /// getModRefInfo - Return information about whether or not an instruction may /// read or write the specified memory location. An instruction /// that doesn't read or write memory may be trivially LICM'd for example. diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp index 0b0fd50a866..c8323620558 100644 --- a/lib/Analysis/AliasAnalysis.cpp +++ b/lib/Analysis/AliasAnalysis.cpp @@ -330,7 +330,7 @@ AliasAnalysis::getModRefInfo(const LoadInst *L, const Location &Loc) { // If the load address doesn't alias the given address, it doesn't read // or write the specified memory. - if (!alias(getLocation(L), Loc)) + if (Loc.Ptr && !alias(getLocation(L), Loc)) return NoModRef; // Otherwise, a load just reads. @@ -343,15 +343,18 @@ AliasAnalysis::getModRefInfo(const StoreInst *S, const Location &Loc) { if (!S->isUnordered()) return ModRef; - // If the store address cannot alias the pointer in question, then the - // specified memory cannot be modified by the store. - if (!alias(getLocation(S), Loc)) - return NoModRef; + if (Loc.Ptr) { + // If the store address cannot alias the pointer in question, then the + // specified memory cannot be modified by the store. + if (!alias(getLocation(S), Loc)) + return NoModRef; - // If the pointer is a pointer to constant memory, then it could not have been - // modified by this store. - if (pointsToConstantMemory(Loc)) - return NoModRef; + // If the pointer is a pointer to constant memory, then it could not have + // been modified by this store. + if (pointsToConstantMemory(Loc)) + return NoModRef; + + } // Otherwise, a store just writes. return Mod; diff --git a/unittests/Analysis/AliasAnalysisTest.cpp b/unittests/Analysis/AliasAnalysisTest.cpp new file mode 100644 index 00000000000..1ba396c1eca --- /dev/null +++ b/unittests/Analysis/AliasAnalysisTest.cpp @@ -0,0 +1,94 @@ +//===--- AliasAnalysisTest.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/AliasAnalysis.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Support/CommandLine.h" +#include "gtest/gtest.h" + +namespace llvm { +namespace { + +class AliasAnalysisTest : public testing::Test { +protected: + AliasAnalysisTest() : M("AliasAnalysisTBAATest", C) {} + + // This is going to check that calling getModRefInfo without a location, and + // with a default location, first, doesn't crash, and second, gives the right + // answer. + void CheckModRef(Instruction *I, AliasAnalysis::ModRefResult Result) { + static char ID; + class CheckModRefTestPass : public FunctionPass { + public: + CheckModRefTestPass(Instruction *I, AliasAnalysis::ModRefResult Result) + : FunctionPass(ID), ExpectResult(Result), I(I) {} + static int initialize() { + PassInfo *PI = new PassInfo("CheckModRef testing pass", "", &ID, + nullptr, true, true); + PassRegistry::getPassRegistry()->registerPass(*PI, false); + initializeAliasAnalysisAnalysisGroup(*PassRegistry::getPassRegistry()); + initializeBasicAliasAnalysisPass(*PassRegistry::getPassRegistry()); + return 0; + } + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + } + bool runOnFunction(Function &) override { + AliasAnalysis &AA = getAnalysis(); + EXPECT_EQ(AA.getModRefInfo(I, AliasAnalysis::Location()), ExpectResult); + EXPECT_EQ(AA.getModRefInfo(I), ExpectResult); + return false; + } + AliasAnalysis::ModRefResult ExpectResult; + Instruction *I; + }; + static int initialize = CheckModRefTestPass::initialize(); + (void)initialize; + CheckModRefTestPass *P = new CheckModRefTestPass(I, Result); + legacy::PassManager PM; + PM.add(createBasicAliasAnalysisPass()); + PM.add(P); + PM.run(M); + } + + LLVMContext C; + Module M; +}; + +TEST_F(AliasAnalysisTest, getModRefInfo) { + // Setup function. + FunctionType *FTy = + FunctionType::get(Type::getVoidTy(C), std::vector(), false); + auto *F = cast(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 *Load1 = new LoadInst(Addr, "load", BB); + auto *Add1 = BinaryOperator::CreateAdd(Value, Value, "add", BB); + + ReturnInst::Create(C, nullptr, BB); + + // Check basic results + CheckModRef(Store1, AliasAnalysis::ModRefResult::Mod); + CheckModRef(Load1, AliasAnalysis::ModRefResult::Ref); + CheckModRef(Add1, AliasAnalysis::ModRefResult::NoModRef); +} + +} // end anonymous namspace +} // end llvm namespace diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt index baf0c28a8d9..35a6d92ce17 100644 --- a/unittests/Analysis/CMakeLists.txt +++ b/unittests/Analysis/CMakeLists.txt @@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_unittest(AnalysisTests + AliasAnalysisTest.cpp CallGraphTest.cpp CFGTest.cpp LazyCallGraphTest.cpp