aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r--llvm/lib/Analysis/HashRecognize.cpp2
-rw-r--r--llvm/lib/Analysis/IR2Vec.cpp86
-rw-r--r--llvm/lib/Analysis/LoopAccessAnalysis.cpp32
-rw-r--r--llvm/lib/Analysis/MemoryProfileInfo.cpp22
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp26
5 files changed, 89 insertions, 79 deletions
diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp
index 5d7ee1f..4529123 100644
--- a/llvm/lib/Analysis/HashRecognize.cpp
+++ b/llvm/lib/Analysis/HashRecognize.cpp
@@ -97,7 +97,7 @@ static bool containsUnreachable(const Loop &L,
}
}
}
- return std::distance(Latch->begin(), Latch->end()) != Visited.size();
+ return Latch->size() != Visited.size();
}
/// A structure that can hold either a Simple Recurrence or a Conditional
diff --git a/llvm/lib/Analysis/IR2Vec.cpp b/llvm/lib/Analysis/IR2Vec.cpp
index af30422..295b6d3 100644
--- a/llvm/lib/Analysis/IR2Vec.cpp
+++ b/llvm/lib/Analysis/IR2Vec.cpp
@@ -330,6 +330,43 @@ bool VocabStorage::const_iterator::operator!=(
return !(*this == Other);
}
+Error VocabStorage::parseVocabSection(StringRef Key,
+ const json::Value &ParsedVocabValue,
+ VocabMap &TargetVocab, unsigned &Dim) {
+ json::Path::Root Path("");
+ const json::Object *RootObj = ParsedVocabValue.getAsObject();
+ if (!RootObj)
+ return createStringError(errc::invalid_argument,
+ "JSON root is not an object");
+
+ const json::Value *SectionValue = RootObj->get(Key);
+ if (!SectionValue)
+ return createStringError(errc::invalid_argument,
+ "Missing '" + std::string(Key) +
+ "' section in vocabulary file");
+ if (!json::fromJSON(*SectionValue, TargetVocab, Path))
+ return createStringError(errc::illegal_byte_sequence,
+ "Unable to parse '" + std::string(Key) +
+ "' section from vocabulary");
+
+ Dim = TargetVocab.begin()->second.size();
+ if (Dim == 0)
+ return createStringError(errc::illegal_byte_sequence,
+ "Dimension of '" + std::string(Key) +
+ "' section of the vocabulary is zero");
+
+ if (!std::all_of(TargetVocab.begin(), TargetVocab.end(),
+ [Dim](const std::pair<StringRef, Embedding> &Entry) {
+ return Entry.second.size() == Dim;
+ }))
+ return createStringError(
+ errc::illegal_byte_sequence,
+ "All vectors in the '" + std::string(Key) +
+ "' section of the vocabulary are not of the same dimension");
+
+ return Error::success();
+}
+
// ==----------------------------------------------------------------------===//
// Vocabulary
//===----------------------------------------------------------------------===//
@@ -460,43 +497,6 @@ VocabStorage Vocabulary::createDummyVocabForTest(unsigned Dim) {
// IR2VecVocabAnalysis
//===----------------------------------------------------------------------===//
-Error IR2VecVocabAnalysis::parseVocabSection(
- StringRef Key, const json::Value &ParsedVocabValue, VocabMap &TargetVocab,
- unsigned &Dim) {
- json::Path::Root Path("");
- const json::Object *RootObj = ParsedVocabValue.getAsObject();
- if (!RootObj)
- return createStringError(errc::invalid_argument,
- "JSON root is not an object");
-
- const json::Value *SectionValue = RootObj->get(Key);
- if (!SectionValue)
- return createStringError(errc::invalid_argument,
- "Missing '" + std::string(Key) +
- "' section in vocabulary file");
- if (!json::fromJSON(*SectionValue, TargetVocab, Path))
- return createStringError(errc::illegal_byte_sequence,
- "Unable to parse '" + std::string(Key) +
- "' section from vocabulary");
-
- Dim = TargetVocab.begin()->second.size();
- if (Dim == 0)
- return createStringError(errc::illegal_byte_sequence,
- "Dimension of '" + std::string(Key) +
- "' section of the vocabulary is zero");
-
- if (!std::all_of(TargetVocab.begin(), TargetVocab.end(),
- [Dim](const std::pair<StringRef, Embedding> &Entry) {
- return Entry.second.size() == Dim;
- }))
- return createStringError(
- errc::illegal_byte_sequence,
- "All vectors in the '" + std::string(Key) +
- "' section of the vocabulary are not of the same dimension");
-
- return Error::success();
-}
-
// FIXME: Make this optional. We can avoid file reads
// by auto-generating a default vocabulary during the build time.
Error IR2VecVocabAnalysis::readVocabulary(VocabMap &OpcVocab,
@@ -513,16 +513,16 @@ Error IR2VecVocabAnalysis::readVocabulary(VocabMap &OpcVocab,
return ParsedVocabValue.takeError();
unsigned OpcodeDim = 0, TypeDim = 0, ArgDim = 0;
- if (auto Err =
- parseVocabSection("Opcodes", *ParsedVocabValue, OpcVocab, OpcodeDim))
+ if (auto Err = VocabStorage::parseVocabSection("Opcodes", *ParsedVocabValue,
+ OpcVocab, OpcodeDim))
return Err;
- if (auto Err =
- parseVocabSection("Types", *ParsedVocabValue, TypeVocab, TypeDim))
+ if (auto Err = VocabStorage::parseVocabSection("Types", *ParsedVocabValue,
+ TypeVocab, TypeDim))
return Err;
- if (auto Err =
- parseVocabSection("Arguments", *ParsedVocabValue, ArgVocab, ArgDim))
+ if (auto Err = VocabStorage::parseVocabSection("Arguments", *ParsedVocabValue,
+ ArgVocab, ArgDim))
return Err;
if (!(OpcodeDim == TypeDim && TypeDim == ArgDim))
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 47dccde..7adb25d 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -233,19 +233,25 @@ static bool evaluatePtrAddRecAtMaxBTCWillNotWrap(
const SCEV *DerefBytesSCEV = SE.getConstant(WiderTy, DerefBytes);
// Check if we have a suitable dereferencable assumption we can use.
- if (!StartPtrV->canBeFreed()) {
- Instruction *CtxI = &*L->getHeader()->getFirstNonPHIIt();
- if (BasicBlock *LoopPred = L->getLoopPredecessor()) {
- if (isa<BranchInst>(LoopPred->getTerminator()))
- CtxI = LoopPred->getTerminator();
- }
-
- RetainedKnowledge DerefRK = getKnowledgeValidInContext(
- StartPtrV, {Attribute::Dereferenceable}, *AC, CtxI, DT);
- if (DerefRK) {
- DerefBytesSCEV =
- SE.getUMaxExpr(DerefBytesSCEV, SE.getSCEV(DerefRK.IRArgValue));
- }
+ Instruction *CtxI = &*L->getHeader()->getFirstNonPHIIt();
+ if (BasicBlock *LoopPred = L->getLoopPredecessor()) {
+ if (isa<BranchInst>(LoopPred->getTerminator()))
+ CtxI = LoopPred->getTerminator();
+ }
+ RetainedKnowledge DerefRK;
+ getKnowledgeForValue(StartPtrV, {Attribute::Dereferenceable}, *AC,
+ [&](RetainedKnowledge RK, Instruction *Assume, auto) {
+ if (!isValidAssumeForContext(Assume, CtxI, DT))
+ return false;
+ if (StartPtrV->canBeFreed() &&
+ !willNotFreeBetween(Assume, CtxI))
+ return false;
+ DerefRK = std::max(DerefRK, RK);
+ return true;
+ });
+ if (DerefRK) {
+ DerefBytesSCEV =
+ SE.getUMaxExpr(DerefBytesSCEV, SE.getSCEV(DerefRK.IRArgValue));
}
if (DerefBytesSCEV->isZero())
diff --git a/llvm/lib/Analysis/MemoryProfileInfo.cpp b/llvm/lib/Analysis/MemoryProfileInfo.cpp
index 11602d2..0c1f8db 100644
--- a/llvm/lib/Analysis/MemoryProfileInfo.cpp
+++ b/llvm/lib/Analysis/MemoryProfileInfo.cpp
@@ -125,24 +125,6 @@ bool llvm::memprof::hasSingleAllocType(uint8_t AllocTypes) {
return NumAllocTypes == 1;
}
-void llvm::memprof::removeAnyExistingAmbiguousAttribute(CallBase *CB) {
- if (!CB->hasFnAttr("memprof"))
- return;
- assert(CB->getFnAttr("memprof").getValueAsString() == "ambiguous");
- CB->removeFnAttr("memprof");
-}
-
-void llvm::memprof::addAmbiguousAttribute(CallBase *CB) {
- // We may have an existing ambiguous attribute if we are reanalyzing
- // after inlining.
- if (CB->hasFnAttr("memprof")) {
- assert(CB->getFnAttr("memprof").getValueAsString() == "ambiguous");
- } else {
- auto A = llvm::Attribute::get(CB->getContext(), "memprof", "ambiguous");
- CB->addFnAttr(A);
- }
-}
-
void CallStackTrie::addCallStack(
AllocationType AllocType, ArrayRef<uint64_t> StackIds,
std::vector<ContextTotalSize> ContextSizeInfo) {
@@ -488,9 +470,6 @@ void CallStackTrie::addSingleAllocTypeAttribute(CallBase *CI, AllocationType AT,
StringRef Descriptor) {
auto AllocTypeString = getAllocTypeAttributeString(AT);
auto A = llvm::Attribute::get(CI->getContext(), "memprof", AllocTypeString);
- // After inlining we may be able to convert an existing ambiguous allocation
- // to an unambiguous one.
- removeAnyExistingAmbiguousAttribute(CI);
CI->addFnAttr(A);
if (MemProfReportHintedSizes) {
std::vector<ContextTotalSize> ContextSizeInfo;
@@ -550,7 +529,6 @@ bool CallStackTrie::buildAndAttachMIBMetadata(CallBase *CI) {
assert(MIBCallStack.size() == 1 &&
"Should only be left with Alloc's location in stack");
CI->setMetadata(LLVMContext::MD_memprof, MDNode::get(Ctx, MIBNodes));
- addAmbiguousAttribute(CI);
return true;
}
// If there exists corner case that CallStackTrie has one chain to leaf
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 09a8fbe..1eda7a7 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -89,6 +89,9 @@ using namespace llvm::PatternMatch;
static cl::opt<unsigned> DomConditionsMaxUses("dom-conditions-max-uses",
cl::Hidden, cl::init(20));
+/// Maximum number of instructions to check between assume and context
+/// instruction.
+static constexpr unsigned MaxInstrsToCheckForFree = 16;
/// Returns the bitwidth of the given scalar or pointer type. For vector types,
/// returns the element type's bitwidth.
@@ -561,6 +564,29 @@ bool llvm::isValidAssumeForContext(const Instruction *Inv,
return false;
}
+bool llvm::willNotFreeBetween(const Instruction *Assume,
+ const Instruction *CtxI) {
+ if (CtxI->getParent() != Assume->getParent() || !Assume->comesBefore(CtxI))
+ return false;
+ // Make sure the current function cannot arrange for another thread to free on
+ // its behalf.
+ if (!CtxI->getFunction()->hasNoSync())
+ return false;
+
+ // Check if there are any calls between the assume and CtxI that may
+ // free memory.
+ for (const auto &[Idx, I] :
+ enumerate(make_range(Assume->getIterator(), CtxI->getIterator()))) {
+ // Limit number of instructions to walk.
+ if (Idx > MaxInstrsToCheckForFree)
+ return false;
+ if (const auto *CB = dyn_cast<CallBase>(&I))
+ if (!CB->hasFnAttr(Attribute::NoFree))
+ return false;
+ }
+ return true;
+}
+
// TODO: cmpExcludesZero misses many cases where `RHS` is non-constant but
// we still have enough information about `RHS` to conclude non-zero. For
// example Pred=EQ, RHS=isKnownNonZero. cmpExcludesZero is called in loops