diff options
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r-- | llvm/lib/Analysis/DependenceAnalysis.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/Analysis/IR2Vec.cpp | 180 | ||||
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/Analysis/TargetLibraryInfo.cpp | 5 |
4 files changed, 93 insertions, 134 deletions
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index 1f0da8d1..8d20b0e 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -275,7 +275,7 @@ bool Dependence::isAnti() const { // if no subscript in the source or destination mention the induction // variable associated with the loop at this level. // Leave this out of line, so it will serve as a virtual method anchor -bool Dependence::isScalar(unsigned level, bool isSameSD) const { return false; } +bool Dependence::isScalar(unsigned level, bool IsSameSD) const { return false; } //===----------------------------------------------------------------------===// // FullDependence methods @@ -351,38 +351,38 @@ bool FullDependence::normalize(ScalarEvolution *SE) { // getDirection - Returns the direction associated with a particular common or // SameSD level. -unsigned FullDependence::getDirection(unsigned Level, bool isSameSD) const { - return getDVEntry(Level, isSameSD).Direction; +unsigned FullDependence::getDirection(unsigned Level, bool IsSameSD) const { + return getDVEntry(Level, IsSameSD).Direction; } // Returns the distance (or NULL) associated with a particular common or // SameSD level. -const SCEV *FullDependence::getDistance(unsigned Level, bool isSameSD) const { - return getDVEntry(Level, isSameSD).Distance; +const SCEV *FullDependence::getDistance(unsigned Level, bool IsSameSD) const { + return getDVEntry(Level, IsSameSD).Distance; } // Returns true if a particular regular or SameSD level is scalar; that is, // if no subscript in the source or destination mention the induction variable // associated with the loop at this level. -bool FullDependence::isScalar(unsigned Level, bool isSameSD) const { - return getDVEntry(Level, isSameSD).Scalar; +bool FullDependence::isScalar(unsigned Level, bool IsSameSD) const { + return getDVEntry(Level, IsSameSD).Scalar; } // Returns true if peeling the first iteration from this regular or SameSD // loop level will break this dependence. -bool FullDependence::isPeelFirst(unsigned Level, bool isSameSD) const { - return getDVEntry(Level, isSameSD).PeelFirst; +bool FullDependence::isPeelFirst(unsigned Level, bool IsSameSD) const { + return getDVEntry(Level, IsSameSD).PeelFirst; } // Returns true if peeling the last iteration from this regular or SameSD // loop level will break this dependence. -bool FullDependence::isPeelLast(unsigned Level, bool isSameSD) const { - return getDVEntry(Level, isSameSD).PeelLast; +bool FullDependence::isPeelLast(unsigned Level, bool IsSameSD) const { + return getDVEntry(Level, IsSameSD).PeelLast; } // Returns true if splitting loop will break the dependence. -bool FullDependence::isSplitable(unsigned Level, bool isSameSD) const { - return getDVEntry(Level, isSameSD).Splitable; +bool FullDependence::isSplitable(unsigned Level, bool IsSameSD) const { + return getDVEntry(Level, IsSameSD).Splitable; } // inSameSDLoops - Returns true if this level is an SameSD level, i.e., @@ -691,7 +691,7 @@ void Dependence::dump(raw_ostream &OS) const { dumpImp(OS); unsigned SameSDLevels = getSameSDLevels(); if (SameSDLevels > 0) { - OS << "! / assuming " << SameSDLevels << " loop level(s) fused: "; + OS << " / assuming " << SameSDLevels << " loop level(s) fused: "; dumpImp(OS, true); } } @@ -706,13 +706,13 @@ void Dependence::dump(raw_ostream &OS) const { // For debugging purposes. Dumps a dependence to OS with or without considering // the SameSD levels. -void Dependence::dumpImp(raw_ostream &OS, bool isSameSD) const { +void Dependence::dumpImp(raw_ostream &OS, bool IsSameSD) const { bool Splitable = false; unsigned Levels = getLevels(); unsigned SameSDLevels = getSameSDLevels(); bool OnSameSD = false; unsigned LevelNum = Levels; - if (isSameSD) + if (IsSameSD) LevelNum += SameSDLevels; OS << " ["; for (unsigned II = 1; II <= LevelNum; ++II) { diff --git a/llvm/lib/Analysis/IR2Vec.cpp b/llvm/lib/Analysis/IR2Vec.cpp index 1794a60..85b5372 100644 --- a/llvm/lib/Analysis/IR2Vec.cpp +++ b/llvm/lib/Analysis/IR2Vec.cpp @@ -153,11 +153,6 @@ void Embedding::print(raw_ostream &OS) const { // Embedder and its subclasses //===----------------------------------------------------------------------===// -Embedder::Embedder(const Function &F, const Vocabulary &Vocab) - : F(F), Vocab(Vocab), Dimension(Vocab.getDimension()), - OpcWeight(::OpcWeight), TypeWeight(::TypeWeight), ArgWeight(::ArgWeight), - FuncVector(Embedding(Dimension)) {} - std::unique_ptr<Embedder> Embedder::create(IR2VecKind Mode, const Function &F, const Vocabulary &Vocab) { switch (Mode) { @@ -169,110 +164,85 @@ std::unique_ptr<Embedder> Embedder::create(IR2VecKind Mode, const Function &F, return nullptr; } -const InstEmbeddingsMap &Embedder::getInstVecMap() const { - if (InstVecMap.empty()) - computeEmbeddings(); - return InstVecMap; -} - -const BBEmbeddingsMap &Embedder::getBBVecMap() const { - if (BBVecMap.empty()) - computeEmbeddings(); - return BBVecMap; -} - -const Embedding &Embedder::getBBVector(const BasicBlock &BB) const { - auto It = BBVecMap.find(&BB); - if (It != BBVecMap.end()) - return It->second; - computeEmbeddings(BB); - return BBVecMap[&BB]; -} +Embedding Embedder::computeEmbeddings() const { + Embedding FuncVector(Dimension, 0.0); -const Embedding &Embedder::getFunctionVector() const { - // Currently, we always (re)compute the embeddings for the function. - // This is cheaper than caching the vector. - computeEmbeddings(); - return FuncVector; -} - -void Embedder::computeEmbeddings() const { if (F.isDeclaration()) - return; - - FuncVector = Embedding(Dimension, 0.0); + return FuncVector; // Consider only the basic blocks that are reachable from entry - for (const BasicBlock *BB : depth_first(&F)) { - computeEmbeddings(*BB); - FuncVector += BBVecMap[BB]; - } + for (const BasicBlock *BB : depth_first(&F)) + FuncVector += computeEmbeddings(*BB); + return FuncVector; } -void SymbolicEmbedder::computeEmbeddings(const BasicBlock &BB) const { +Embedding Embedder::computeEmbeddings(const BasicBlock &BB) const { Embedding BBVector(Dimension, 0); // We consider only the non-debug and non-pseudo instructions - for (const auto &I : BB.instructionsWithoutDebug()) { - Embedding ArgEmb(Dimension, 0); - for (const auto &Op : I.operands()) - ArgEmb += Vocab[*Op]; - auto InstVector = - Vocab[I.getOpcode()] + Vocab[I.getType()->getTypeID()] + ArgEmb; - if (const auto *IC = dyn_cast<CmpInst>(&I)) - InstVector += Vocab[IC->getPredicate()]; - InstVecMap[&I] = InstVector; - BBVector += InstVector; - } - BBVecMap[&BB] = BBVector; -} - -void FlowAwareEmbedder::computeEmbeddings(const BasicBlock &BB) const { - Embedding BBVector(Dimension, 0); + for (const auto &I : BB.instructionsWithoutDebug()) + BBVector += computeEmbeddings(I); + return BBVector; +} + +Embedding SymbolicEmbedder::computeEmbeddings(const Instruction &I) const { + // Currently, we always (re)compute the embeddings for symbolic embedder. + // This is cheaper than caching the vectors. + Embedding ArgEmb(Dimension, 0); + for (const auto &Op : I.operands()) + ArgEmb += Vocab[*Op]; + auto InstVector = + Vocab[I.getOpcode()] + Vocab[I.getType()->getTypeID()] + ArgEmb; + if (const auto *IC = dyn_cast<CmpInst>(&I)) + InstVector += Vocab[IC->getPredicate()]; + return InstVector; +} + +Embedding FlowAwareEmbedder::computeEmbeddings(const Instruction &I) const { + // If we have already computed the embedding for this instruction, return it + auto It = InstVecMap.find(&I); + if (It != InstVecMap.end()) + return It->second; - // We consider only the non-debug and non-pseudo instructions - for (const auto &I : BB.instructionsWithoutDebug()) { - // TODO: Handle call instructions differently. - // For now, we treat them like other instructions - Embedding ArgEmb(Dimension, 0); - for (const auto &Op : I.operands()) { - // If the operand is defined elsewhere, we use its embedding - if (const auto *DefInst = dyn_cast<Instruction>(Op)) { - auto DefIt = InstVecMap.find(DefInst); - // Fixme (#159171): Ideally we should never miss an instruction - // embedding here. - // But when we have cyclic dependencies (e.g., phi - // nodes), we might miss the embedding. In such cases, we fall back to - // using the vocabulary embedding. This can be fixed by iterating to a - // fixed-point, or by using a simple solver for the set of simultaneous - // equations. - // Another case when we might miss an instruction embedding is when - // the operand instruction is in a different basic block that has not - // been processed yet. This can be fixed by processing the basic blocks - // in a topological order. - if (DefIt != InstVecMap.end()) - ArgEmb += DefIt->second; - else - ArgEmb += Vocab[*Op]; - } - // If the operand is not defined by an instruction, we use the vocabulary - else { - LLVM_DEBUG(errs() << "Using embedding from vocabulary for operand: " - << *Op << "=" << Vocab[*Op][0] << "\n"); + // TODO: Handle call instructions differently. + // For now, we treat them like other instructions + Embedding ArgEmb(Dimension, 0); + for (const auto &Op : I.operands()) { + // If the operand is defined elsewhere, we use its embedding + if (const auto *DefInst = dyn_cast<Instruction>(Op)) { + auto DefIt = InstVecMap.find(DefInst); + // Fixme (#159171): Ideally we should never miss an instruction + // embedding here. + // But when we have cyclic dependencies (e.g., phi + // nodes), we might miss the embedding. In such cases, we fall back to + // using the vocabulary embedding. This can be fixed by iterating to a + // fixed-point, or by using a simple solver for the set of simultaneous + // equations. + // Another case when we might miss an instruction embedding is when + // the operand instruction is in a different basic block that has not + // been processed yet. This can be fixed by processing the basic blocks + // in a topological order. + if (DefIt != InstVecMap.end()) + ArgEmb += DefIt->second; + else ArgEmb += Vocab[*Op]; - } } - // Create the instruction vector by combining opcode, type, and arguments - // embeddings - auto InstVector = - Vocab[I.getOpcode()] + Vocab[I.getType()->getTypeID()] + ArgEmb; - // Add compare predicate embedding as an additional operand if applicable - if (const auto *IC = dyn_cast<CmpInst>(&I)) - InstVector += Vocab[IC->getPredicate()]; - InstVecMap[&I] = InstVector; - BBVector += InstVector; + // If the operand is not defined by an instruction, we use the + // vocabulary + else { + LLVM_DEBUG(errs() << "Using embedding from vocabulary for operand: " + << *Op << "=" << Vocab[*Op][0] << "\n"); + ArgEmb += Vocab[*Op]; + } } - BBVecMap[&BB] = BBVector; + // Create the instruction vector by combining opcode, type, and arguments + // embeddings + auto InstVector = + Vocab[I.getOpcode()] + Vocab[I.getType()->getTypeID()] + ArgEmb; + if (const auto *IC = dyn_cast<CmpInst>(&I)) + InstVector += Vocab[IC->getPredicate()]; + InstVecMap[&I] = InstVector; + return InstVector; } // ==----------------------------------------------------------------------===// @@ -695,25 +665,17 @@ PreservedAnalyses IR2VecPrinterPass::run(Module &M, Emb->getFunctionVector().print(OS); OS << "Basic block vectors:\n"; - const auto &BBMap = Emb->getBBVecMap(); for (const BasicBlock &BB : F) { - auto It = BBMap.find(&BB); - if (It != BBMap.end()) { - OS << "Basic block: " << BB.getName() << ":\n"; - It->second.print(OS); - } + OS << "Basic block: " << BB.getName() << ":\n"; + Emb->getBBVector(BB).print(OS); } OS << "Instruction vectors:\n"; - const auto &InstMap = Emb->getInstVecMap(); for (const BasicBlock &BB : F) { for (const Instruction &I : BB) { - auto It = InstMap.find(&I); - if (It != InstMap.end()) { - OS << "Instruction: "; - I.print(OS); - It->second.print(OS); - } + OS << "Instruction: "; + I.print(OS); + Emb->getInstVector(I).print(OS); } } } diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index d1977f0..4e38626 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -671,12 +671,12 @@ Value *llvm::simplifyAddInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW, /// This is very similar to stripAndAccumulateConstantOffsets(), except it /// normalizes the offset bitwidth to the stripped pointer type, not the /// original pointer type. -static APInt stripAndComputeConstantOffsets(const DataLayout &DL, Value *&V, - bool AllowNonInbounds = false) { +static APInt stripAndComputeConstantOffsets(const DataLayout &DL, Value *&V) { assert(V->getType()->isPtrOrPtrVectorTy()); APInt Offset = APInt::getZero(DL.getIndexTypeSizeInBits(V->getType())); - V = V->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds); + V = V->stripAndAccumulateConstantOffsets(DL, Offset, + /*AllowNonInbounds=*/true); // As that strip may trace through `addrspacecast`, need to sext or trunc // the offset calculated. return Offset.sextOrTrunc(DL.getIndexTypeSizeInBits(V->getType())); @@ -853,10 +853,12 @@ static Value *simplifySubInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW, return W; // Variations on GEP(base, I, ...) - GEP(base, i, ...) -> GEP(null, I-i, ...). - if (match(Op0, m_PtrToInt(m_Value(X))) && match(Op1, m_PtrToInt(m_Value(Y)))) + if (match(Op0, m_PtrToIntOrAddr(m_Value(X))) && + match(Op1, m_PtrToIntOrAddr(m_Value(Y)))) { if (Constant *Result = computePointerDifference(Q.DL, X, Y)) return ConstantFoldIntegerCast(Result, Op0->getType(), /*IsSigned*/ true, Q.DL); + } // i1 sub -> xor. if (MaxRecurse && Op0->getType()->isIntOrIntVectorTy(1)) diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 6e92766..813632c 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -740,11 +740,6 @@ static void initializeLibCalls(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setAvailable(LibFunc_fgets_unlocked); } - if (T.isAndroid() && T.isAndroidVersionLT(21)) { - TLI.setUnavailable(LibFunc_stpcpy); - TLI.setUnavailable(LibFunc_stpncpy); - } - if (T.isPS()) { // PS4/PS5 do have memalign. TLI.setAvailable(LibFunc_memalign); |