AliasAnalysisTest.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. //===--- AliasAnalysisTest.cpp - Mixed TBAA unit tests --------------------===//
  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. #include "llvm/Analysis/AliasAnalysis.h"
  9. #include "llvm/ADT/SetVector.h"
  10. #include "llvm/Analysis/AssumptionCache.h"
  11. #include "llvm/Analysis/BasicAliasAnalysis.h"
  12. #include "llvm/Analysis/TargetLibraryInfo.h"
  13. #include "llvm/AsmParser/Parser.h"
  14. #include "llvm/IR/Constants.h"
  15. #include "llvm/IR/InstIterator.h"
  16. #include "llvm/IR/Instructions.h"
  17. #include "llvm/IR/LLVMContext.h"
  18. #include "llvm/IR/LegacyPassManager.h"
  19. #include "llvm/IR/Module.h"
  20. #include "llvm/Support/SourceMgr.h"
  21. #include "gtest/gtest.h"
  22. using namespace llvm;
  23. // Set up some test passes.
  24. namespace llvm {
  25. void initializeAATestPassPass(PassRegistry&);
  26. void initializeTestCustomAAWrapperPassPass(PassRegistry&);
  27. }
  28. namespace {
  29. struct AATestPass : FunctionPass {
  30. static char ID;
  31. AATestPass() : FunctionPass(ID) {
  32. initializeAATestPassPass(*PassRegistry::getPassRegistry());
  33. }
  34. void getAnalysisUsage(AnalysisUsage &AU) const override {
  35. AU.addRequired<AAResultsWrapperPass>();
  36. AU.setPreservesAll();
  37. }
  38. bool runOnFunction(Function &F) override {
  39. AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
  40. SetVector<Value *> Pointers;
  41. for (Argument &A : F.args())
  42. if (A.getType()->isPointerTy())
  43. Pointers.insert(&A);
  44. for (Instruction &I : instructions(F))
  45. if (I.getType()->isPointerTy())
  46. Pointers.insert(&I);
  47. for (Value *P1 : Pointers)
  48. for (Value *P2 : Pointers)
  49. (void)AA.alias(P1, LocationSize::unknown(), P2,
  50. LocationSize::unknown());
  51. return false;
  52. }
  53. };
  54. }
  55. char AATestPass::ID = 0;
  56. INITIALIZE_PASS_BEGIN(AATestPass, "aa-test-pas", "Alias Analysis Test Pass",
  57. false, true)
  58. INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
  59. INITIALIZE_PASS_END(AATestPass, "aa-test-pass", "Alias Analysis Test Pass",
  60. false, true)
  61. namespace {
  62. /// A test customizable AA result. It merely accepts a callback to run whenever
  63. /// it receives an alias query. Useful for testing that a particular AA result
  64. /// is reached.
  65. struct TestCustomAAResult : AAResultBase<TestCustomAAResult> {
  66. friend AAResultBase<TestCustomAAResult>;
  67. std::function<void()> CB;
  68. explicit TestCustomAAResult(std::function<void()> CB)
  69. : AAResultBase(), CB(std::move(CB)) {}
  70. TestCustomAAResult(TestCustomAAResult &&Arg)
  71. : AAResultBase(std::move(Arg)), CB(std::move(Arg.CB)) {}
  72. bool invalidate(Function &, const PreservedAnalyses &) { return false; }
  73. AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
  74. CB();
  75. return MayAlias;
  76. }
  77. };
  78. }
  79. namespace {
  80. /// A wrapper pass for the legacy pass manager to use with the above custom AA
  81. /// result.
  82. class TestCustomAAWrapperPass : public ImmutablePass {
  83. std::function<void()> CB;
  84. std::unique_ptr<TestCustomAAResult> Result;
  85. public:
  86. static char ID;
  87. explicit TestCustomAAWrapperPass(
  88. std::function<void()> CB = std::function<void()>())
  89. : ImmutablePass(ID), CB(std::move(CB)) {
  90. initializeTestCustomAAWrapperPassPass(*PassRegistry::getPassRegistry());
  91. }
  92. void getAnalysisUsage(AnalysisUsage &AU) const override {
  93. AU.setPreservesAll();
  94. AU.addRequired<TargetLibraryInfoWrapperPass>();
  95. }
  96. bool doInitialization(Module &M) override {
  97. Result.reset(new TestCustomAAResult(std::move(CB)));
  98. return true;
  99. }
  100. bool doFinalization(Module &M) override {
  101. Result.reset();
  102. return true;
  103. }
  104. TestCustomAAResult &getResult() { return *Result; }
  105. const TestCustomAAResult &getResult() const { return *Result; }
  106. };
  107. }
  108. char TestCustomAAWrapperPass::ID = 0;
  109. INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass, "test-custom-aa",
  110. "Test Custom AA Wrapper Pass", false, true)
  111. INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
  112. INITIALIZE_PASS_END(TestCustomAAWrapperPass, "test-custom-aa",
  113. "Test Custom AA Wrapper Pass", false, true)
  114. namespace {
  115. class AliasAnalysisTest : public testing::Test {
  116. protected:
  117. LLVMContext C;
  118. Module M;
  119. TargetLibraryInfoImpl TLII;
  120. TargetLibraryInfo TLI;
  121. std::unique_ptr<AssumptionCache> AC;
  122. std::unique_ptr<BasicAAResult> BAR;
  123. std::unique_ptr<AAResults> AAR;
  124. AliasAnalysisTest() : M("AliasAnalysisTest", C), TLI(TLII) {}
  125. AAResults &getAAResults(Function &F) {
  126. // Reset the Function AA results first to clear out any references.
  127. AAR.reset(new AAResults(TLI));
  128. // Build the various AA results and register them.
  129. AC.reset(new AssumptionCache(F));
  130. BAR.reset(new BasicAAResult(M.getDataLayout(), F, TLI, *AC));
  131. AAR->addAAResult(*BAR);
  132. return *AAR;
  133. }
  134. };
  135. TEST_F(AliasAnalysisTest, getModRefInfo) {
  136. // Setup function.
  137. FunctionType *FTy =
  138. FunctionType::get(Type::getVoidTy(C), std::vector<Type *>(), false);
  139. auto *F = Function::Create(FTy, Function::ExternalLinkage, "f", M);
  140. auto *BB = BasicBlock::Create(C, "entry", F);
  141. auto IntType = Type::getInt32Ty(C);
  142. auto PtrType = Type::getInt32PtrTy(C);
  143. auto *Value = ConstantInt::get(IntType, 42);
  144. auto *Addr = ConstantPointerNull::get(PtrType);
  145. auto *Store1 = new StoreInst(Value, Addr, BB);
  146. auto *Load1 = new LoadInst(Addr, "load", BB);
  147. auto *Add1 = BinaryOperator::CreateAdd(Value, Value, "add", BB);
  148. auto *VAArg1 = new VAArgInst(Addr, PtrType, "vaarg", BB);
  149. auto *CmpXChg1 = new AtomicCmpXchgInst(
  150. Addr, ConstantInt::get(IntType, 0), ConstantInt::get(IntType, 1),
  151. AtomicOrdering::Monotonic, AtomicOrdering::Monotonic,
  152. SyncScope::System, BB);
  153. auto *AtomicRMW =
  154. new AtomicRMWInst(AtomicRMWInst::Xchg, Addr, ConstantInt::get(IntType, 1),
  155. AtomicOrdering::Monotonic, SyncScope::System, BB);
  156. ReturnInst::Create(C, nullptr, BB);
  157. auto &AA = getAAResults(*F);
  158. // Check basic results
  159. EXPECT_EQ(AA.getModRefInfo(Store1, MemoryLocation()), ModRefInfo::Mod);
  160. EXPECT_EQ(AA.getModRefInfo(Store1, None), ModRefInfo::Mod);
  161. EXPECT_EQ(AA.getModRefInfo(Load1, MemoryLocation()), ModRefInfo::Ref);
  162. EXPECT_EQ(AA.getModRefInfo(Load1, None), ModRefInfo::Ref);
  163. EXPECT_EQ(AA.getModRefInfo(Add1, MemoryLocation()), ModRefInfo::NoModRef);
  164. EXPECT_EQ(AA.getModRefInfo(Add1, None), ModRefInfo::NoModRef);
  165. EXPECT_EQ(AA.getModRefInfo(VAArg1, MemoryLocation()), ModRefInfo::ModRef);
  166. EXPECT_EQ(AA.getModRefInfo(VAArg1, None), ModRefInfo::ModRef);
  167. EXPECT_EQ(AA.getModRefInfo(CmpXChg1, MemoryLocation()), ModRefInfo::ModRef);
  168. EXPECT_EQ(AA.getModRefInfo(CmpXChg1, None), ModRefInfo::ModRef);
  169. EXPECT_EQ(AA.getModRefInfo(AtomicRMW, MemoryLocation()), ModRefInfo::ModRef);
  170. EXPECT_EQ(AA.getModRefInfo(AtomicRMW, None), ModRefInfo::ModRef);
  171. }
  172. class AAPassInfraTest : public testing::Test {
  173. protected:
  174. LLVMContext C;
  175. SMDiagnostic Err;
  176. std::unique_ptr<Module> M;
  177. public:
  178. AAPassInfraTest()
  179. : M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
  180. "entry:\n"
  181. " %lx = load i32, i32* %x\n"
  182. " %ly = load i32, i32* %y\n"
  183. " %sum = add i32 %lx, %ly\n"
  184. " ret i32 %sum\n"
  185. "}\n",
  186. Err, C)) {
  187. assert(M && "Failed to build the module!");
  188. }
  189. };
  190. TEST_F(AAPassInfraTest, injectExternalAA) {
  191. legacy::PassManager PM;
  192. // Register our custom AA's wrapper pass manually.
  193. bool IsCustomAAQueried = false;
  194. PM.add(new TestCustomAAWrapperPass([&] { IsCustomAAQueried = true; }));
  195. // Now add the external AA wrapper with a lambda which queries for the
  196. // wrapper around our custom AA and adds it to the results.
  197. PM.add(createExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) {
  198. if (auto *WrapperPass = P.getAnalysisIfAvailable<TestCustomAAWrapperPass>())
  199. AAR.addAAResult(WrapperPass->getResult());
  200. }));
  201. // And run a pass that will make some alias queries. This will automatically
  202. // trigger the rest of the alias analysis stack to be run. It is analagous to
  203. // building a full pass pipeline with any of the existing pass manager
  204. // builders.
  205. PM.add(new AATestPass());
  206. PM.run(*M);
  207. // Finally, ensure that our custom AA was indeed queried.
  208. EXPECT_TRUE(IsCustomAAQueried);
  209. }
  210. } // end anonymous namspace