AssumeBundleBuilder.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. //===- AssumeBundleBuilder.cpp - tools to preserve informations -*- C++ -*-===//
  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. #define DEBUG_TYPE "assume-builder"
  9. #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
  10. #include "llvm/ADT/DepthFirstIterator.h"
  11. #include "llvm/ADT/MapVector.h"
  12. #include "llvm/ADT/Statistic.h"
  13. #include "llvm/Analysis/AssumeBundleQueries.h"
  14. #include "llvm/Analysis/AssumptionCache.h"
  15. #include "llvm/Analysis/ValueTracking.h"
  16. #include "llvm/IR/Dominators.h"
  17. #include "llvm/IR/Function.h"
  18. #include "llvm/IR/InstIterator.h"
  19. #include "llvm/IR/IntrinsicInst.h"
  20. #include "llvm/IR/Module.h"
  21. #include "llvm/InitializePasses.h"
  22. #include "llvm/Support/CommandLine.h"
  23. #include "llvm/Support/DebugCounter.h"
  24. #include "llvm/Transforms/Utils/Local.h"
  25. using namespace llvm;
  26. cl::opt<bool> ShouldPreserveAllAttributes(
  27. "assume-preserve-all", cl::init(false), cl::Hidden,
  28. cl::desc("enable preservation of all attrbitues. even those that are "
  29. "unlikely to be usefull"));
  30. cl::opt<bool> EnableKnowledgeRetention(
  31. "enable-knowledge-retention", cl::init(false), cl::Hidden,
  32. cl::desc(
  33. "enable preservation of attributes throughout code transformation"));
  34. STATISTIC(NumAssumeBuilt, "Number of assume built by the assume builder");
  35. STATISTIC(NumBundlesInAssumes, "Total number of Bundles in the assume built");
  36. STATISTIC(NumAssumesMerged,
  37. "Number of assume merged by the assume simplify pass");
  38. STATISTIC(NumAssumesRemoved,
  39. "Number of assume removed by the assume simplify pass");
  40. DEBUG_COUNTER(BuildAssumeCounter, "assume-builder-counter",
  41. "Controls which assumes gets created");
  42. namespace {
  43. bool isUsefullToPreserve(Attribute::AttrKind Kind) {
  44. switch (Kind) {
  45. case Attribute::NonNull:
  46. case Attribute::NoUndef:
  47. case Attribute::Alignment:
  48. case Attribute::Dereferenceable:
  49. case Attribute::DereferenceableOrNull:
  50. case Attribute::Cold:
  51. return true;
  52. default:
  53. return false;
  54. }
  55. }
  56. /// This function will try to transform the given knowledge into a more
  57. /// canonical one. the canonical knowledge maybe the given one.
  58. RetainedKnowledge canonicalizedKnowledge(RetainedKnowledge RK, Module *M) {
  59. switch (RK.AttrKind) {
  60. default:
  61. return RK;
  62. case Attribute::NonNull:
  63. RK.WasOn = getUnderlyingObject(RK.WasOn);
  64. return RK;
  65. case Attribute::Alignment: {
  66. Value *V = RK.WasOn->stripInBoundsOffsets([&](const Value *Strip) {
  67. if (auto *GEP = dyn_cast<GEPOperator>(Strip))
  68. RK.ArgValue =
  69. MinAlign(RK.ArgValue,
  70. GEP->getMaxPreservedAlignment(M->getDataLayout()).value());
  71. });
  72. RK.WasOn = V;
  73. return RK;
  74. }
  75. case Attribute::Dereferenceable:
  76. case Attribute::DereferenceableOrNull: {
  77. int64_t Offset = 0;
  78. Value *V = GetPointerBaseWithConstantOffset(
  79. RK.WasOn, Offset, M->getDataLayout(), /*AllowNonInBounds*/ false);
  80. if (Offset < 0)
  81. return RK;
  82. RK.ArgValue = RK.ArgValue + Offset;
  83. RK.WasOn = V;
  84. }
  85. }
  86. return RK;
  87. }
  88. /// This class contain all knowledge that have been gather while building an
  89. /// llvm.assume and the function to manipulate it.
  90. struct AssumeBuilderState {
  91. Module *M;
  92. using MapKey = std::pair<Value *, Attribute::AttrKind>;
  93. SmallMapVector<MapKey, unsigned, 8> AssumedKnowledgeMap;
  94. Instruction *InstBeingRemoved = nullptr;
  95. AssumptionCache* AC = nullptr;
  96. DominatorTree* DT = nullptr;
  97. AssumeBuilderState(Module *M, Instruction *I = nullptr,
  98. AssumptionCache *AC = nullptr, DominatorTree *DT = nullptr)
  99. : M(M), InstBeingRemoved(I), AC(AC), DT(DT) {}
  100. bool tryToPreserveWithoutAddingAssume(RetainedKnowledge RK) {
  101. if (!InstBeingRemoved || !RK.WasOn)
  102. return false;
  103. bool HasBeenPreserved = false;
  104. Use* ToUpdate = nullptr;
  105. getKnowledgeForValue(
  106. RK.WasOn, {RK.AttrKind}, AC,
  107. [&](RetainedKnowledge RKOther, Instruction *Assume,
  108. const CallInst::BundleOpInfo *Bundle) {
  109. if (!isValidAssumeForContext(Assume, InstBeingRemoved, DT))
  110. return false;
  111. if (RKOther.ArgValue >= RK.ArgValue) {
  112. HasBeenPreserved = true;
  113. return true;
  114. } else if (isValidAssumeForContext(InstBeingRemoved, Assume,
  115. DT)) {
  116. HasBeenPreserved = true;
  117. IntrinsicInst *Intr = cast<IntrinsicInst>(Assume);
  118. ToUpdate = &Intr->op_begin()[Bundle->Begin + ABA_Argument];
  119. return true;
  120. }
  121. return false;
  122. });
  123. if (ToUpdate)
  124. ToUpdate->set(
  125. ConstantInt::get(Type::getInt64Ty(M->getContext()), RK.ArgValue));
  126. return HasBeenPreserved;
  127. }
  128. bool isKnowledgeWorthPreserving(RetainedKnowledge RK) {
  129. if (!RK)
  130. return false;
  131. if (!RK.WasOn)
  132. return true;
  133. if (RK.WasOn->getType()->isPointerTy()) {
  134. Value *UnderlyingPtr = getUnderlyingObject(RK.WasOn);
  135. if (isa<AllocaInst>(UnderlyingPtr) || isa<GlobalValue>(UnderlyingPtr))
  136. return false;
  137. }
  138. if (auto *Arg = dyn_cast<Argument>(RK.WasOn)) {
  139. if (Arg->hasAttribute(RK.AttrKind) &&
  140. (!Attribute::doesAttrKindHaveArgument(RK.AttrKind) ||
  141. Arg->getAttribute(RK.AttrKind).getValueAsInt() >= RK.ArgValue))
  142. return false;
  143. return true;
  144. }
  145. if (auto *Inst = dyn_cast<Instruction>(RK.WasOn))
  146. if (wouldInstructionBeTriviallyDead(Inst)) {
  147. if (RK.WasOn->use_empty())
  148. return false;
  149. Use *SingleUse = RK.WasOn->getSingleUndroppableUse();
  150. if (SingleUse && SingleUse->getUser() == InstBeingRemoved)
  151. return false;
  152. }
  153. return true;
  154. }
  155. void addKnowledge(RetainedKnowledge RK) {
  156. RK = canonicalizedKnowledge(RK, M);
  157. if (!isKnowledgeWorthPreserving(RK))
  158. return;
  159. if (tryToPreserveWithoutAddingAssume(RK))
  160. return;
  161. MapKey Key{RK.WasOn, RK.AttrKind};
  162. auto Lookup = AssumedKnowledgeMap.find(Key);
  163. if (Lookup == AssumedKnowledgeMap.end()) {
  164. AssumedKnowledgeMap[Key] = RK.ArgValue;
  165. return;
  166. }
  167. assert(((Lookup->second == 0 && RK.ArgValue == 0) ||
  168. (Lookup->second != 0 && RK.ArgValue != 0)) &&
  169. "inconsistent argument value");
  170. /// This is only desirable because for all attributes taking an argument
  171. /// higher is better.
  172. Lookup->second = std::max(Lookup->second, RK.ArgValue);
  173. }
  174. void addAttribute(Attribute Attr, Value *WasOn) {
  175. if (Attr.isTypeAttribute() || Attr.isStringAttribute() ||
  176. (!ShouldPreserveAllAttributes &&
  177. !isUsefullToPreserve(Attr.getKindAsEnum())))
  178. return;
  179. unsigned AttrArg = 0;
  180. if (Attr.isIntAttribute())
  181. AttrArg = Attr.getValueAsInt();
  182. addKnowledge({Attr.getKindAsEnum(), AttrArg, WasOn});
  183. }
  184. void addCall(const CallBase *Call) {
  185. auto addAttrList = [&](AttributeList AttrList) {
  186. for (unsigned Idx = AttributeList::FirstArgIndex;
  187. Idx < AttrList.getNumAttrSets(); Idx++)
  188. for (Attribute Attr : AttrList.getAttributes(Idx))
  189. addAttribute(Attr, Call->getArgOperand(Idx - 1));
  190. for (Attribute Attr : AttrList.getFnAttributes())
  191. addAttribute(Attr, nullptr);
  192. };
  193. addAttrList(Call->getAttributes());
  194. if (Function *Fn = Call->getCalledFunction())
  195. addAttrList(Fn->getAttributes());
  196. }
  197. IntrinsicInst *build() {
  198. if (AssumedKnowledgeMap.empty())
  199. return nullptr;
  200. if (!DebugCounter::shouldExecute(BuildAssumeCounter))
  201. return nullptr;
  202. Function *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume);
  203. LLVMContext &C = M->getContext();
  204. SmallVector<OperandBundleDef, 8> OpBundle;
  205. for (auto &MapElem : AssumedKnowledgeMap) {
  206. SmallVector<Value *, 2> Args;
  207. if (MapElem.first.first)
  208. Args.push_back(MapElem.first.first);
  209. /// This is only valid because for all attribute that currently exist a
  210. /// value of 0 is useless. and should not be preserved.
  211. if (MapElem.second)
  212. Args.push_back(ConstantInt::get(Type::getInt64Ty(M->getContext()),
  213. MapElem.second));
  214. OpBundle.push_back(OperandBundleDefT<Value *>(
  215. std::string(Attribute::getNameFromAttrKind(MapElem.first.second)),
  216. Args));
  217. NumBundlesInAssumes++;
  218. }
  219. NumAssumeBuilt++;
  220. return cast<IntrinsicInst>(CallInst::Create(
  221. FnAssume, ArrayRef<Value *>({ConstantInt::getTrue(C)}), OpBundle));
  222. }
  223. void addAccessedPtr(Instruction *MemInst, Value *Pointer, Type *AccType,
  224. MaybeAlign MA) {
  225. unsigned DerefSize = MemInst->getModule()
  226. ->getDataLayout()
  227. .getTypeStoreSize(AccType)
  228. .getKnownMinSize();
  229. if (DerefSize != 0) {
  230. addKnowledge({Attribute::Dereferenceable, DerefSize, Pointer});
  231. if (!NullPointerIsDefined(MemInst->getFunction(),
  232. Pointer->getType()->getPointerAddressSpace()))
  233. addKnowledge({Attribute::NonNull, 0u, Pointer});
  234. }
  235. if (MA.valueOrOne() > 1)
  236. addKnowledge(
  237. {Attribute::Alignment, unsigned(MA.valueOrOne().value()), Pointer});
  238. }
  239. void addInstruction(Instruction *I) {
  240. if (auto *Call = dyn_cast<CallBase>(I))
  241. return addCall(Call);
  242. if (auto *Load = dyn_cast<LoadInst>(I))
  243. return addAccessedPtr(I, Load->getPointerOperand(), Load->getType(),
  244. Load->getAlign());
  245. if (auto *Store = dyn_cast<StoreInst>(I))
  246. return addAccessedPtr(I, Store->getPointerOperand(),
  247. Store->getValueOperand()->getType(),
  248. Store->getAlign());
  249. // TODO: Add support for the other Instructions.
  250. // TODO: Maybe we should look around and merge with other llvm.assume.
  251. }
  252. };
  253. } // namespace
  254. IntrinsicInst *llvm::buildAssumeFromInst(Instruction *I) {
  255. if (!EnableKnowledgeRetention)
  256. return nullptr;
  257. AssumeBuilderState Builder(I->getModule());
  258. Builder.addInstruction(I);
  259. return Builder.build();
  260. }
  261. void llvm::salvageKnowledge(Instruction *I, AssumptionCache *AC,
  262. DominatorTree *DT) {
  263. if (!EnableKnowledgeRetention || I->isTerminator())
  264. return;
  265. AssumeBuilderState Builder(I->getModule(), I, AC, DT);
  266. Builder.addInstruction(I);
  267. if (IntrinsicInst *Intr = Builder.build()) {
  268. Intr->insertBefore(I);
  269. if (AC)
  270. AC->registerAssumption(Intr);
  271. }
  272. }
  273. namespace {
  274. struct AssumeSimplify {
  275. Function &F;
  276. AssumptionCache &AC;
  277. DominatorTree *DT;
  278. LLVMContext &C;
  279. SmallDenseSet<IntrinsicInst *> CleanupToDo;
  280. StringMapEntry<uint32_t> *IgnoreTag;
  281. SmallDenseMap<BasicBlock *, SmallVector<IntrinsicInst *, 4>, 8> BBToAssume;
  282. bool MadeChange = false;
  283. AssumeSimplify(Function &F, AssumptionCache &AC, DominatorTree *DT,
  284. LLVMContext &C)
  285. : F(F), AC(AC), DT(DT), C(C),
  286. IgnoreTag(C.getOrInsertBundleTag(IgnoreBundleTag)) {}
  287. void buildMapping(bool FilterBooleanArgument) {
  288. BBToAssume.clear();
  289. for (Value *V : AC.assumptions()) {
  290. if (!V)
  291. continue;
  292. IntrinsicInst *Assume = cast<IntrinsicInst>(V);
  293. if (FilterBooleanArgument) {
  294. auto *Arg = dyn_cast<ConstantInt>(Assume->getOperand(0));
  295. if (!Arg || Arg->isZero())
  296. continue;
  297. }
  298. BBToAssume[Assume->getParent()].push_back(Assume);
  299. }
  300. for (auto &Elem : BBToAssume) {
  301. llvm::sort(Elem.second,
  302. [](const IntrinsicInst *LHS, const IntrinsicInst *RHS) {
  303. return LHS->comesBefore(RHS);
  304. });
  305. }
  306. }
  307. /// Remove all asumes in CleanupToDo if there boolean argument is true and
  308. /// ForceCleanup is set or the assume doesn't hold valuable knowledge.
  309. void RunCleanup(bool ForceCleanup) {
  310. for (IntrinsicInst *Assume : CleanupToDo) {
  311. auto *Arg = dyn_cast<ConstantInt>(Assume->getOperand(0));
  312. if (!Arg || Arg->isZero() ||
  313. (!ForceCleanup && !isAssumeWithEmptyBundle(*Assume)))
  314. continue;
  315. MadeChange = true;
  316. if (ForceCleanup)
  317. NumAssumesMerged++;
  318. else
  319. NumAssumesRemoved++;
  320. Assume->eraseFromParent();
  321. }
  322. CleanupToDo.clear();
  323. }
  324. /// Remove knowledge stored in assume when it is already know by an attribute
  325. /// or an other assume. This can when valid update an existing knowledge in an
  326. /// attribute or an other assume.
  327. void dropRedundantKnowledge() {
  328. struct MapValue {
  329. IntrinsicInst *Assume;
  330. unsigned ArgValue;
  331. CallInst::BundleOpInfo *BOI;
  332. };
  333. buildMapping(false);
  334. SmallDenseMap<std::pair<Value *, Attribute::AttrKind>,
  335. SmallVector<MapValue, 2>, 16>
  336. Knowledge;
  337. for (BasicBlock *BB : depth_first(&F))
  338. for (Value *V : BBToAssume[BB]) {
  339. if (!V)
  340. continue;
  341. IntrinsicInst *Assume = cast<IntrinsicInst>(V);
  342. for (CallInst::BundleOpInfo &BOI : Assume->bundle_op_infos()) {
  343. auto RemoveFromAssume = [&]() {
  344. CleanupToDo.insert(Assume);
  345. if (BOI.Begin != BOI.End) {
  346. Use *U = &Assume->op_begin()[BOI.Begin + ABA_WasOn];
  347. U->set(UndefValue::get(U->get()->getType()));
  348. }
  349. BOI.Tag = IgnoreTag;
  350. };
  351. if (BOI.Tag == IgnoreTag) {
  352. CleanupToDo.insert(Assume);
  353. continue;
  354. }
  355. RetainedKnowledge RK = getKnowledgeFromBundle(*Assume, BOI);
  356. if (auto *Arg = dyn_cast_or_null<Argument>(RK.WasOn)) {
  357. bool HasSameKindAttr = Arg->hasAttribute(RK.AttrKind);
  358. if (HasSameKindAttr)
  359. if (!Attribute::doesAttrKindHaveArgument(RK.AttrKind) ||
  360. Arg->getAttribute(RK.AttrKind).getValueAsInt() >=
  361. RK.ArgValue) {
  362. RemoveFromAssume();
  363. continue;
  364. }
  365. if (isValidAssumeForContext(
  366. Assume, &*F.getEntryBlock().getFirstInsertionPt()) ||
  367. Assume == &*F.getEntryBlock().getFirstInsertionPt()) {
  368. if (HasSameKindAttr)
  369. Arg->removeAttr(RK.AttrKind);
  370. Arg->addAttr(Attribute::get(C, RK.AttrKind, RK.ArgValue));
  371. MadeChange = true;
  372. RemoveFromAssume();
  373. continue;
  374. }
  375. }
  376. auto &Lookup = Knowledge[{RK.WasOn, RK.AttrKind}];
  377. for (MapValue &Elem : Lookup) {
  378. if (!isValidAssumeForContext(Elem.Assume, Assume, DT))
  379. continue;
  380. if (Elem.ArgValue >= RK.ArgValue) {
  381. RemoveFromAssume();
  382. continue;
  383. } else if (isValidAssumeForContext(Assume, Elem.Assume, DT)) {
  384. Elem.Assume->op_begin()[Elem.BOI->Begin + ABA_Argument].set(
  385. ConstantInt::get(Type::getInt64Ty(C), RK.ArgValue));
  386. MadeChange = true;
  387. RemoveFromAssume();
  388. continue;
  389. }
  390. }
  391. Lookup.push_back({Assume, RK.ArgValue, &BOI});
  392. }
  393. }
  394. }
  395. using MergeIterator = SmallVectorImpl<IntrinsicInst *>::iterator;
  396. /// Merge all Assumes from Begin to End in and insert the resulting assume as
  397. /// high as possible in the basicblock.
  398. void mergeRange(BasicBlock *BB, MergeIterator Begin, MergeIterator End) {
  399. if (Begin == End || std::next(Begin) == End)
  400. return;
  401. /// Provide no additional information so that AssumeBuilderState doesn't
  402. /// try to do any punning since it already has been done better.
  403. AssumeBuilderState Builder(F.getParent());
  404. /// For now it is initialized to the best value it could have
  405. Instruction *InsertPt = BB->getFirstNonPHI();
  406. if (isa<LandingPadInst>(InsertPt))
  407. InsertPt = InsertPt->getNextNode();
  408. for (IntrinsicInst *I : make_range(Begin, End)) {
  409. CleanupToDo.insert(I);
  410. for (CallInst::BundleOpInfo &BOI : I->bundle_op_infos()) {
  411. RetainedKnowledge RK = getKnowledgeFromBundle(*I, BOI);
  412. if (!RK)
  413. continue;
  414. Builder.addKnowledge(RK);
  415. if (auto *I = dyn_cast_or_null<Instruction>(RK.WasOn))
  416. if (I->getParent() == InsertPt->getParent() &&
  417. (InsertPt->comesBefore(I) || InsertPt == I))
  418. InsertPt = I->getNextNode();
  419. }
  420. }
  421. /// Adjust InsertPt if it is before Begin, since mergeAssumes only
  422. /// guarantees we can place the resulting assume between Begin and End.
  423. if (InsertPt->comesBefore(*Begin))
  424. for (auto It = (*Begin)->getIterator(), E = InsertPt->getIterator();
  425. It != E; --It)
  426. if (!isGuaranteedToTransferExecutionToSuccessor(&*It)) {
  427. InsertPt = It->getNextNode();
  428. break;
  429. }
  430. IntrinsicInst *MergedAssume = Builder.build();
  431. if (!MergedAssume)
  432. return;
  433. MadeChange = true;
  434. MergedAssume->insertBefore(InsertPt);
  435. AC.registerAssumption(MergedAssume);
  436. }
  437. /// Merge assume when they are in the same BasicBlock and for all instruction
  438. /// between them isGuaranteedToTransferExecutionToSuccessor returns true.
  439. void mergeAssumes() {
  440. buildMapping(true);
  441. SmallVector<MergeIterator, 4> SplitPoints;
  442. for (auto &Elem : BBToAssume) {
  443. SmallVectorImpl<IntrinsicInst *> &AssumesInBB = Elem.second;
  444. if (AssumesInBB.size() < 2)
  445. continue;
  446. /// AssumesInBB is already sorted by order in the block.
  447. BasicBlock::iterator It = AssumesInBB.front()->getIterator();
  448. BasicBlock::iterator E = AssumesInBB.back()->getIterator();
  449. SplitPoints.push_back(AssumesInBB.begin());
  450. MergeIterator LastSplit = AssumesInBB.begin();
  451. for (; It != E; ++It)
  452. if (!isGuaranteedToTransferExecutionToSuccessor(&*It)) {
  453. for (; (*LastSplit)->comesBefore(&*It); ++LastSplit)
  454. ;
  455. if (SplitPoints.back() != LastSplit)
  456. SplitPoints.push_back(LastSplit);
  457. }
  458. SplitPoints.push_back(AssumesInBB.end());
  459. for (auto SplitIt = SplitPoints.begin();
  460. SplitIt != std::prev(SplitPoints.end()); SplitIt++) {
  461. mergeRange(Elem.first, *SplitIt, *(SplitIt + 1));
  462. }
  463. SplitPoints.clear();
  464. }
  465. }
  466. };
  467. bool simplifyAssumes(Function &F, AssumptionCache *AC, DominatorTree *DT) {
  468. AssumeSimplify AS(F, *AC, DT, F.getContext());
  469. /// Remove knowledge that is already known by a dominating other assume or an
  470. /// attribute.
  471. AS.dropRedundantKnowledge();
  472. /// Remove assume that are empty.
  473. AS.RunCleanup(false);
  474. /// Merge assume in the same basicblock when possible.
  475. AS.mergeAssumes();
  476. /// Remove assume that were merged.
  477. AS.RunCleanup(true);
  478. return AS.MadeChange;
  479. }
  480. } // namespace
  481. PreservedAnalyses AssumeSimplifyPass::run(Function &F,
  482. FunctionAnalysisManager &AM) {
  483. if (!EnableKnowledgeRetention)
  484. return PreservedAnalyses::all();
  485. simplifyAssumes(F, &AM.getResult<AssumptionAnalysis>(F),
  486. AM.getCachedResult<DominatorTreeAnalysis>(F));
  487. return PreservedAnalyses::all();
  488. }
  489. namespace {
  490. class AssumeSimplifyPassLegacyPass : public FunctionPass {
  491. public:
  492. static char ID;
  493. AssumeSimplifyPassLegacyPass() : FunctionPass(ID) {
  494. initializeAssumeSimplifyPassLegacyPassPass(
  495. *PassRegistry::getPassRegistry());
  496. }
  497. bool runOnFunction(Function &F) override {
  498. if (skipFunction(F) || !EnableKnowledgeRetention)
  499. return false;
  500. AssumptionCache &AC =
  501. getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
  502. DominatorTreeWrapperPass *DTWP =
  503. getAnalysisIfAvailable<DominatorTreeWrapperPass>();
  504. return simplifyAssumes(F, &AC, DTWP ? &DTWP->getDomTree() : nullptr);
  505. }
  506. void getAnalysisUsage(AnalysisUsage &AU) const override {
  507. AU.addRequired<AssumptionCacheTracker>();
  508. AU.setPreservesAll();
  509. }
  510. };
  511. } // namespace
  512. char AssumeSimplifyPassLegacyPass::ID = 0;
  513. INITIALIZE_PASS_BEGIN(AssumeSimplifyPassLegacyPass, "assume-simplify",
  514. "Assume Simplify", false, false)
  515. INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
  516. INITIALIZE_PASS_END(AssumeSimplifyPassLegacyPass, "assume-simplify",
  517. "Assume Simplify", false, false)
  518. FunctionPass *llvm::createAssumeSimplifyPass() {
  519. return new AssumeSimplifyPassLegacyPass();
  520. }
  521. PreservedAnalyses AssumeBuilderPass::run(Function &F,
  522. FunctionAnalysisManager &AM) {
  523. AssumptionCache *AC = &AM.getResult<AssumptionAnalysis>(F);
  524. DominatorTree* DT = AM.getCachedResult<DominatorTreeAnalysis>(F);
  525. for (Instruction &I : instructions(F))
  526. salvageKnowledge(&I, AC, DT);
  527. return PreservedAnalyses::all();
  528. }
  529. namespace {
  530. class AssumeBuilderPassLegacyPass : public FunctionPass {
  531. public:
  532. static char ID;
  533. AssumeBuilderPassLegacyPass() : FunctionPass(ID) {
  534. initializeAssumeBuilderPassLegacyPassPass(*PassRegistry::getPassRegistry());
  535. }
  536. bool runOnFunction(Function &F) override {
  537. AssumptionCache &AC =
  538. getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
  539. DominatorTreeWrapperPass *DTWP =
  540. getAnalysisIfAvailable<DominatorTreeWrapperPass>();
  541. for (Instruction &I : instructions(F))
  542. salvageKnowledge(&I, &AC, DTWP ? &DTWP->getDomTree() : nullptr);
  543. return true;
  544. }
  545. void getAnalysisUsage(AnalysisUsage &AU) const override {
  546. AU.addRequired<AssumptionCacheTracker>();
  547. AU.setPreservesAll();
  548. }
  549. };
  550. } // namespace
  551. char AssumeBuilderPassLegacyPass::ID = 0;
  552. INITIALIZE_PASS_BEGIN(AssumeBuilderPassLegacyPass, "assume-builder",
  553. "Assume Builder", false, false)
  554. INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
  555. INITIALIZE_PASS_END(AssumeBuilderPassLegacyPass, "assume-builder",
  556. "Assume Builder", false, false)