[llvm] [FunctionAttrs] Add the "initializes" attribute inference (PR #97373)
Haopeng Liu via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 18 17:15:03 PDT 2024
================
@@ -866,9 +1070,124 @@ static bool addAccessAttr(Argument *A, Attribute::AttrKind R) {
return true;
}
+static bool inferInitializes(Argument &A, Function &F) {
+ SmallDenseMap<const BasicBlock *, UsesPerBlockInfo, 16> UsesPerBlock;
+ auto [HasAnyWrite, HasWriteOutsideEntryBB] =
+ CollectArgumentUsesPerBlock(A, F, UsesPerBlock);
+ // No write anywhere in the function, bail.
+ if (!HasAnyWrite)
+ return false;
+
+ BasicBlock &EntryBB = F.getEntryBlock();
+ DenseMap<const BasicBlock *, ConstantRangeList> Initialized;
+ auto VisitBlock = [&](const BasicBlock *BB) -> ConstantRangeList {
+ auto UPB = UsesPerBlock.find(BB);
+
+ // If this block has uses and none are writes, the argument is not
+ // initialized in this block.
+ if (UPB != UsesPerBlock.end() && !UPB->second.HasWrites)
+ return ConstantRangeList();
+
+ ConstantRangeList CRL;
+
+ // Start with intersection of successors.
+ // If this block has any clobbering use, we're going to clear out the
+ // ranges at some point in this block anyway, so don't bother looking at
+ // successors.
+ if (UPB == UsesPerBlock.end() || !UPB->second.HasClobber) {
+ bool HasAddedSuccessor = false;
+ for (auto *Succ : successors(BB)) {
+ if (auto SuccI = Initialized.find(Succ); SuccI != Initialized.end()) {
+ if (HasAddedSuccessor) {
+ CRL = CRL.intersectWith(SuccI->second);
+ } else {
+ CRL = SuccI->second;
+ HasAddedSuccessor = true;
+ }
+ } else {
+ CRL = ConstantRangeList();
+ break;
+ }
+ }
+ }
+
+ if (UPB != UsesPerBlock.end()) {
+ // Sort uses in this block by instruction order.
+ SmallVector<std::pair<Instruction *, ArgumentAccessInfo>, 2> Insts;
+ append_range(Insts, UPB->second.Insts);
+ sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &LHS,
+ std::pair<Instruction *, ArgumentAccessInfo> &RHS) {
+ return LHS.first->comesBefore(RHS.first);
+ });
+
+ // From the end of the block to the beginning of the block, set
+ // initializes ranges.
+ for (auto &[_, Info] : reverse(Insts)) {
+ if (Info.IsClobber)
+ CRL = ConstantRangeList();
+ if (!Info.AccessRanges.empty()) {
+ if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write) {
+ CRL = CRL.unionWith(Info.AccessRanges);
+ } else {
+ assert(Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
+ for (const auto &ReadRange : Info.AccessRanges)
+ CRL.subtract(ReadRange);
+ }
+ }
+ }
+ }
+ return CRL;
+ };
+
+ ConstantRangeList EntryCRL;
+ // If all write instructions are in the EntryBB, or if the EntryBB has
+ // a clobbering use, we only need to look at EntryBB.
+ bool OnlyScanEntryBlock = !HasWriteOutsideEntryBB;
+ if (!OnlyScanEntryBlock)
+ if (auto EntryUPB = UsesPerBlock.find(&EntryBB);
+ EntryUPB != UsesPerBlock.end())
+ OnlyScanEntryBlock = EntryUPB->second.HasClobber;
+ if (OnlyScanEntryBlock) {
+ EntryCRL = VisitBlock(&EntryBB);
+ if (EntryCRL.empty())
+ return false;
+ } else {
+ // Visit successors before predecessors with a post-order walk of the
----------------
haopliu wrote:
Done!
https://github.com/llvm/llvm-project/pull/97373
More information about the llvm-commits
mailing list