AssumeBundleBuilder.cpp 23 KB

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