//===-- Analysis.cpp - CodeGen LLVM IR Analysis Utilities -----------------===// // // 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 defines several CodeGen-specific LLVM IR analysis utilities. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/Analysis.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetMachine.h" usingnamespacellvm; /// Compute the linearized index of a member in a nested aggregate/struct/array /// by recursing and accumulating CurIndex as long as there are indices in the /// index list. unsigned llvm::ComputeLinearIndex(Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, unsigned CurIndex) { … } /// ComputeValueVTs - Given an LLVM IR type, compute a sequence of /// EVTs that represent all the individual underlying /// non-aggregate types that comprise it. /// /// If Offsets is non-null, it points to a vector to be filled in /// with the in-memory offsets of each of the individual values. /// void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl<EVT> &ValueVTs, SmallVectorImpl<EVT> *MemVTs, SmallVectorImpl<TypeSize> *Offsets, TypeSize StartingOffset) { … } void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl<EVT> &ValueVTs, SmallVectorImpl<EVT> *MemVTs, SmallVectorImpl<uint64_t> *FixedOffsets, uint64_t StartingOffset) { … } void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty, SmallVectorImpl<LLT> &ValueTys, SmallVectorImpl<uint64_t> *Offsets, uint64_t StartingOffset) { … } /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. GlobalValue *llvm::ExtractTypeInfo(Value *V) { … } /// getFCmpCondCode - Return the ISD condition code corresponding to /// the given LLVM IR floating-point condition code. This includes /// consideration of global floating-point math flags. /// ISD::CondCode llvm::getFCmpCondCode(FCmpInst::Predicate Pred) { … } ISD::CondCode llvm::getFCmpCodeWithoutNaN(ISD::CondCode CC) { … } ISD::CondCode llvm::getICmpCondCode(ICmpInst::Predicate Pred) { … } ICmpInst::Predicate llvm::getICmpCondCode(ISD::CondCode Pred) { … } static bool isNoopBitcast(Type *T1, Type *T2, const TargetLoweringBase& TLI) { … } /// Look through operations that will be free to find the earliest source of /// this value. /// /// @param ValLoc If V has aggregate type, we will be interested in a particular /// scalar component. This records its address; the reverse of this list gives a /// sequence of indices appropriate for an extractvalue to locate the important /// value. This value is updated during the function and on exit will indicate /// similar information for the Value returned. /// /// @param DataBits If this function looks through truncate instructions, this /// will record the smallest size attained. static const Value *getNoopInput(const Value *V, SmallVectorImpl<unsigned> &ValLoc, unsigned &DataBits, const TargetLoweringBase &TLI, const DataLayout &DL) { … } /// Return true if this scalar return value only has bits discarded on its path /// from the "tail call" to the "ret". This includes the obvious noop /// instructions handled by getNoopInput above as well as free truncations (or /// extensions prior to the call). static bool slotOnlyDiscardsData(const Value *RetVal, const Value *CallVal, SmallVectorImpl<unsigned> &RetIndices, SmallVectorImpl<unsigned> &CallIndices, bool AllowDifferingSizes, const TargetLoweringBase &TLI, const DataLayout &DL) { … } /// For an aggregate type, determine whether a given index is within bounds or /// not. static bool indexReallyValid(Type *T, unsigned Idx) { … } /// Move the given iterators to the next leaf type in depth first traversal. /// /// Performs a depth-first traversal of the type as specified by its arguments, /// stopping at the next leaf node (which may be a legitimate scalar type or an /// empty struct or array). /// /// @param SubTypes List of the partial components making up the type from /// outermost to innermost non-empty aggregate. The element currently /// represented is SubTypes.back()->getTypeAtIndex(Path.back() - 1). /// /// @param Path Set of extractvalue indices leading from the outermost type /// (SubTypes[0]) to the leaf node currently represented. /// /// @returns true if a new type was found, false otherwise. Calling this /// function again on a finished iterator will repeatedly return /// false. SubTypes.back()->getTypeAtIndex(Path.back()) is either an empty /// aggregate or a non-aggregate static bool advanceToNextLeafType(SmallVectorImpl<Type *> &SubTypes, SmallVectorImpl<unsigned> &Path) { … } /// Find the first non-empty, scalar-like type in Next and setup the iterator /// components. /// /// Assuming Next is an aggregate of some kind, this function will traverse the /// tree from left to right (i.e. depth-first) looking for the first /// non-aggregate type which will play a role in function return. /// /// For example, if Next was {[0 x i64], {{}, i32, {}}, i32} then we would setup /// Path as [1, 1] and SubTypes as [Next, {{}, i32, {}}] to represent the first /// i32 in that type. static bool firstRealType(Type *Next, SmallVectorImpl<Type *> &SubTypes, SmallVectorImpl<unsigned> &Path) { … } /// Set the iterator data-structures to the next non-empty, non-aggregate /// subtype. static bool nextRealType(SmallVectorImpl<Type *> &SubTypes, SmallVectorImpl<unsigned> &Path) { … } /// Test if the given instruction is in a position to be optimized /// with a tail-call. This roughly means that it's in a block with /// a return and there's nothing that needs to be scheduled /// between it and the return. /// /// This function only tests target-independent requirements. bool llvm::isInTailCallPosition(const CallBase &Call, const TargetMachine &TM, bool ReturnsFirstArg) { … } bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I, const ReturnInst *Ret, const TargetLoweringBase &TLI, bool *AllowDifferingSizes) { … } bool llvm::returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I, const ReturnInst *Ret, const TargetLoweringBase &TLI, bool ReturnsFirstArg) { … } bool llvm::funcReturnsFirstArgOfCall(const CallInst &CI) { … } static void collectEHScopeMembers( DenseMap<const MachineBasicBlock *, int> &EHScopeMembership, int EHScope, const MachineBasicBlock *MBB) { … } DenseMap<const MachineBasicBlock *, int> llvm::getEHScopeMembership(const MachineFunction &MF) { … }