//===-- PredicateInfo.cpp - PredicateInfo Builder--------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------===// // // This file implements the PredicateInfo class. // //===----------------------------------------------------------------===// #include "llvm/Transforms/Utils/PredicateInfo.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/PatternMatch.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/DebugCounter.h" #include "llvm/Support/FormattedStream.h" #include <algorithm> #define DEBUG_TYPE … usingnamespacellvm; usingnamespacePatternMatch; static cl::opt<bool> VerifyPredicateInfo( "verify-predicateinfo", cl::init(false), cl::Hidden, cl::desc("Verify PredicateInfo in legacy printer pass.")); DEBUG_COUNTER(RenameCounter, "predicateinfo-rename", "Controls which variables are renamed with predicateinfo"); // Maximum number of conditions considered for renaming for each branch/assume. // This limits renaming of deep and/or chains. static const unsigned MaxCondsPerBranch = …; namespace { // Given a predicate info that is a type of branching terminator, get the // branching block. const BasicBlock *getBranchBlock(const PredicateBase *PB) { … } // Given a predicate info that is a type of branching terminator, get the // branching terminator. static Instruction *getBranchTerminator(const PredicateBase *PB) { … } // Given a predicate info that is a type of branching terminator, get the // edge this predicate info represents std::pair<BasicBlock *, BasicBlock *> getBlockEdge(const PredicateBase *PB) { … } } namespace llvm { enum LocalNum { … }; // Associate global and local DFS info with defs and uses, so we can sort them // into a global domination ordering. struct ValueDFS { … }; // Perform a strict weak ordering on instructions and arguments. static bool valueComesBefore(const Value *A, const Value *B) { … } // This compares ValueDFS structures. Doing so allows us to walk the minimum // number of instructions necessary to compute our def/use ordering. struct ValueDFS_Compare { … }; class PredicateInfoBuilder { … }; bool PredicateInfoBuilder::stackIsInScope(const ValueDFSStack &Stack, const ValueDFS &VDUse) const { … } void PredicateInfoBuilder::popStackUntilDFSScope(ValueDFSStack &Stack, const ValueDFS &VD) { … } // Convert the uses of Op into a vector of uses, associating global and local // DFS info with each one. void PredicateInfoBuilder::convertUsesToDFSOrdered( Value *Op, SmallVectorImpl<ValueDFS> &DFSOrderedSet) { … } bool shouldRename(Value *V) { … } // Collect relevant operations from Comparison that we may want to insert copies // for. void collectCmpOps(CmpInst *Comparison, SmallVectorImpl<Value *> &CmpOperands) { … } // Add Op, PB to the list of value infos for Op, and mark Op to be renamed. void PredicateInfoBuilder::addInfoFor(SmallVectorImpl<Value *> &OpsToRename, Value *Op, PredicateBase *PB) { … } // Process an assume instruction and place relevant operations we want to rename // into OpsToRename. void PredicateInfoBuilder::processAssume( IntrinsicInst *II, BasicBlock *AssumeBB, SmallVectorImpl<Value *> &OpsToRename) { … } // Process a block terminating branch, and place relevant operations to be // renamed into OpsToRename. void PredicateInfoBuilder::processBranch( BranchInst *BI, BasicBlock *BranchBB, SmallVectorImpl<Value *> &OpsToRename) { … } // Process a block terminating switch, and place relevant operations to be // renamed into OpsToRename. void PredicateInfoBuilder::processSwitch( SwitchInst *SI, BasicBlock *BranchBB, SmallVectorImpl<Value *> &OpsToRename) { … } // Build predicate info for our function void PredicateInfoBuilder::buildPredicateInfo() { … } // Given the renaming stack, make all the operands currently on the stack real // by inserting them into the IR. Return the last operation's value. Value *PredicateInfoBuilder::materializeStack(unsigned int &Counter, ValueDFSStack &RenameStack, Value *OrigOp) { … } // Instead of the standard SSA renaming algorithm, which is O(Number of // instructions), and walks the entire dominator tree, we walk only the defs + // uses. The standard SSA renaming algorithm does not really rely on the // dominator tree except to order the stack push/pops of the renaming stacks, so // that defs end up getting pushed before hitting the correct uses. This does // not require the dominator tree, only the *order* of the dominator tree. The // complete and correct ordering of the defs and uses, in dominator tree is // contained in the DFS numbering of the dominator tree. So we sort the defs and // uses into the DFS ordering, and then just use the renaming stack as per // normal, pushing when we hit a def (which is a predicateinfo instruction), // popping when we are out of the dfs scope for that def, and replacing any uses // with top of stack if it exists. In order to handle liveness without // propagating liveness info, we don't actually insert the predicateinfo // instruction def until we see a use that it would dominate. Once we see such // a use, we materialize the predicateinfo instruction in the right place and // use it. // // TODO: Use this algorithm to perform fast single-variable renaming in // promotememtoreg and memoryssa. void PredicateInfoBuilder::renameUses(SmallVectorImpl<Value *> &OpsToRename) { … } PredicateInfoBuilder::ValueInfo & PredicateInfoBuilder::getOrCreateValueInfo(Value *Operand) { … } const PredicateInfoBuilder::ValueInfo & PredicateInfoBuilder::getValueInfo(Value *Operand) const { … } PredicateInfo::PredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC) : … { … } // Remove all declarations we created . The PredicateInfo consumers are // responsible for remove the ssa_copy calls created. PredicateInfo::~PredicateInfo() { … } std::optional<PredicateConstraint> PredicateBase::getConstraint() const { … } void PredicateInfo::verifyPredicateInfo() const { … } // Replace ssa_copy calls created by PredicateInfo with their operand. static void replaceCreatedSSACopys(PredicateInfo &PredInfo, Function &F) { … } PreservedAnalyses PredicateInfoPrinterPass::run(Function &F, FunctionAnalysisManager &AM) { … } /// An assembly annotator class to print PredicateInfo information in /// comments. class PredicateInfoAnnotatedWriter : public AssemblyAnnotationWriter { … }; void PredicateInfo::print(raw_ostream &OS) const { … } void PredicateInfo::dump() const { … } PreservedAnalyses PredicateInfoVerifierPass::run(Function &F, FunctionAnalysisManager &AM) { … } }