#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <map>
#include <optional>
#include <utility>
usingnamespacellvm;
usingnamespacellvm::PatternMatch;
extern cl::opt<bool> UseNewDbgInfoFormat;
#define DEBUG_TYPE …
STATISTIC(NumRemoved, "Number of unreachable basic blocks removed");
STATISTIC(NumPHICSEs, "Number of PHI's that got CSE'd");
static cl::opt<bool> PHICSEDebugHash(
"phicse-debug-hash",
#ifdef EXPENSIVE_CHECKS
cl::init(true),
#else
cl::init(false),
#endif
cl::Hidden,
cl::desc("Perform extra assertion checking to verify that PHINodes's hash "
"function is well-behaved w.r.t. its isEqual predicate"));
static cl::opt<unsigned> PHICSENumPHISmallSize(
"phicse-num-phi-smallsize", cl::init(32), cl::Hidden,
cl::desc(
"When the basic block contains not more than this number of PHI nodes, "
"perform a (faster!) exhaustive search instead of set-driven one."));
static cl::opt<unsigned> MaxPhiEntriesIncreaseAfterRemovingEmptyBlock(
"max-phi-entries-increase-after-removing-empty-block", cl::init(1000),
cl::Hidden,
cl::desc("Stop removing an empty block if removing it will introduce more "
"than this number of phi entries in its successor"));
static const unsigned BitPartRecursionMaxDepth = …;
bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
const TargetLibraryInfo *TLI,
DomTreeUpdater *DTU) { … }
bool llvm::isInstructionTriviallyDead(Instruction *I,
const TargetLibraryInfo *TLI) { … }
bool llvm::wouldInstructionBeTriviallyDeadOnUnusedPaths(
Instruction *I, const TargetLibraryInfo *TLI) { … }
bool llvm::wouldInstructionBeTriviallyDead(const Instruction *I,
const TargetLibraryInfo *TLI) { … }
bool llvm::RecursivelyDeleteTriviallyDeadInstructions(
Value *V, const TargetLibraryInfo *TLI, MemorySSAUpdater *MSSAU,
std::function<void(Value *)> AboutToDeleteCallback) { … }
bool llvm::RecursivelyDeleteTriviallyDeadInstructionsPermissive(
SmallVectorImpl<WeakTrackingVH> &DeadInsts, const TargetLibraryInfo *TLI,
MemorySSAUpdater *MSSAU,
std::function<void(Value *)> AboutToDeleteCallback) { … }
void llvm::RecursivelyDeleteTriviallyDeadInstructions(
SmallVectorImpl<WeakTrackingVH> &DeadInsts, const TargetLibraryInfo *TLI,
MemorySSAUpdater *MSSAU,
std::function<void(Value *)> AboutToDeleteCallback) { … }
bool llvm::replaceDbgUsesWithUndef(Instruction *I) { … }
static bool areAllUsesEqual(Instruction *I) { … }
bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN,
const TargetLibraryInfo *TLI,
llvm::MemorySSAUpdater *MSSAU) { … }
static bool
simplifyAndDCEInstruction(Instruction *I,
SmallSetVector<Instruction *, 16> &WorkList,
const DataLayout &DL,
const TargetLibraryInfo *TLI) { … }
bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB,
const TargetLibraryInfo *TLI) { … }
void llvm::MergeBasicBlockIntoOnlyPred(BasicBlock *DestBB,
DomTreeUpdater *DTU) { … }
static bool CanMergeValues(Value *First, Value *Second) { … }
static bool
CanPropagatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ,
const SmallPtrSetImpl<BasicBlock *> &BBPreds) { … }
PredBlockVector;
IncomingValueMap;
static Value *selectIncomingValueForBlock(Value *OldVal, BasicBlock *BB,
IncomingValueMap &IncomingValues) { … }
static void gatherIncomingValuesToPhi(PHINode *PN,
IncomingValueMap &IncomingValues) { … }
static void replaceUndefValuesInPhi(PHINode *PN,
const IncomingValueMap &IncomingValues) { … }
static bool
CanRedirectPredsOfEmptyBBToSucc(BasicBlock *BB, BasicBlock *Succ,
const SmallPtrSetImpl<BasicBlock *> &BBPreds,
BasicBlock *&CommonPred) { … }
static bool introduceTooManyPhiEntries(BasicBlock *BB, BasicBlock *Succ) { … }
static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
const PredBlockVector &BBPreds,
PHINode *PN,
BasicBlock *CommonPred) { … }
bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
DomTreeUpdater *DTU) { … }
static bool
EliminateDuplicatePHINodesNaiveImpl(BasicBlock *BB,
SmallPtrSetImpl<PHINode *> &ToRemove) { … }
static bool
EliminateDuplicatePHINodesSetBasedImpl(BasicBlock *BB,
SmallPtrSetImpl<PHINode *> &ToRemove) { … }
bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB,
SmallPtrSetImpl<PHINode *> &ToRemove) { … }
bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB) { … }
Align llvm::tryEnforceAlignment(Value *V, Align PrefAlign,
const DataLayout &DL) { … }
Align llvm::getOrEnforceKnownAlignment(Value *V, MaybeAlign PrefAlign,
const DataLayout &DL,
const Instruction *CxtI,
AssumptionCache *AC,
const DominatorTree *DT) { … }
static bool PhiHasDebugValue(DILocalVariable *DIVar,
DIExpression *DIExpr,
PHINode *APN) { … }
static bool valueCoversEntireFragment(Type *ValTy, DbgVariableIntrinsic *DII) { … }
static bool valueCoversEntireFragment(Type *ValTy, DbgVariableRecord *DVR) { … }
static void insertDbgValueOrDbgVariableRecord(DIBuilder &Builder, Value *DV,
DILocalVariable *DIVar,
DIExpression *DIExpr,
const DebugLoc &NewLoc,
BasicBlock::iterator Instr) { … }
static void insertDbgValueOrDbgVariableRecordAfter(
DIBuilder &Builder, Value *DV, DILocalVariable *DIVar, DIExpression *DIExpr,
const DebugLoc &NewLoc, BasicBlock::iterator Instr) { … }
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
StoreInst *SI, DIBuilder &Builder) { … }
static DIExpression *dropInitialDeref(const DIExpression *DIExpr) { … }
void llvm::InsertDebugValueAtStoreLoc(DbgVariableIntrinsic *DII, StoreInst *SI,
DIBuilder &Builder) { … }
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
LoadInst *LI, DIBuilder &Builder) { … }
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR,
StoreInst *SI, DIBuilder &Builder) { … }
void llvm::InsertDebugValueAtStoreLoc(DbgVariableRecord *DVR, StoreInst *SI,
DIBuilder &Builder) { … }
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
PHINode *APN, DIBuilder &Builder) { … }
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, LoadInst *LI,
DIBuilder &Builder) { … }
static bool isArray(AllocaInst *AI) { … }
static bool isStructure(AllocaInst *AI) { … }
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, PHINode *APN,
DIBuilder &Builder) { … }
bool llvm::LowerDbgDeclare(Function &F) { … }
static void
insertDbgVariableRecordsForPHIs(BasicBlock *BB,
SmallVectorImpl<PHINode *> &InsertedPHIs) { … }
void llvm::insertDebugValuesForPHIs(BasicBlock *BB,
SmallVectorImpl<PHINode *> &InsertedPHIs) { … }
bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress,
DIBuilder &Builder, uint8_t DIExprFlags,
int Offset) { … }
static void updateOneDbgValueForAlloca(const DebugLoc &Loc,
DILocalVariable *DIVar,
DIExpression *DIExpr, Value *NewAddress,
DbgValueInst *DVI,
DbgVariableRecord *DVR,
DIBuilder &Builder, int Offset) { … }
void llvm::replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
DIBuilder &Builder, int Offset) { … }
void llvm::salvageDebugInfo(Instruction &I) { … }
template <typename T> static void salvageDbgAssignAddress(T *Assign) { … }
void llvm::salvageDebugInfoForDbgValues(
Instruction &I, ArrayRef<DbgVariableIntrinsic *> DbgUsers,
ArrayRef<DbgVariableRecord *> DPUsers) { … }
Value *getSalvageOpsForGEP(GetElementPtrInst *GEP, const DataLayout &DL,
uint64_t CurrentLocOps,
SmallVectorImpl<uint64_t> &Opcodes,
SmallVectorImpl<Value *> &AdditionalValues) { … }
uint64_t getDwarfOpForBinOp(Instruction::BinaryOps Opcode) { … }
static void handleSSAValueOperands(uint64_t CurrentLocOps,
SmallVectorImpl<uint64_t> &Opcodes,
SmallVectorImpl<Value *> &AdditionalValues,
Instruction *I) { … }
Value *getSalvageOpsForBinOp(BinaryOperator *BI, uint64_t CurrentLocOps,
SmallVectorImpl<uint64_t> &Opcodes,
SmallVectorImpl<Value *> &AdditionalValues) { … }
uint64_t getDwarfOpForIcmpPred(CmpInst::Predicate Pred) { … }
Value *getSalvageOpsForIcmpOp(ICmpInst *Icmp, uint64_t CurrentLocOps,
SmallVectorImpl<uint64_t> &Opcodes,
SmallVectorImpl<Value *> &AdditionalValues) { … }
Value *llvm::salvageDebugInfoImpl(Instruction &I, uint64_t CurrentLocOps,
SmallVectorImpl<uint64_t> &Ops,
SmallVectorImpl<Value *> &AdditionalValues) { … }
DbgValReplacement;
static bool rewriteDebugUsers(
Instruction &From, Value &To, Instruction &DomPoint, DominatorTree &DT,
function_ref<DbgValReplacement(DbgVariableIntrinsic &DII)> RewriteExpr,
function_ref<DbgValReplacement(DbgVariableRecord &DVR)> RewriteDVRExpr) { … }
static bool isBitCastSemanticsPreserving(const DataLayout &DL, Type *FromTy,
Type *ToTy) { … }
bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To,
Instruction &DomPoint, DominatorTree &DT) { … }
bool llvm::handleUnreachableTerminator(
Instruction *I, SmallVectorImpl<Value *> &PoisonedValues) { … }
std::pair<unsigned, unsigned>
llvm::removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB) { … }
unsigned llvm::changeToUnreachable(Instruction *I, bool PreserveLCSSA,
DomTreeUpdater *DTU,
MemorySSAUpdater *MSSAU) { … }
CallInst *llvm::createCallMatchingInvoke(InvokeInst *II) { … }
CallInst *llvm::changeToCall(InvokeInst *II, DomTreeUpdater *DTU) { … }
BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
BasicBlock *UnwindEdge,
DomTreeUpdater *DTU) { … }
static bool markAliveBlocks(Function &F,
SmallPtrSetImpl<BasicBlock *> &Reachable,
DomTreeUpdater *DTU = nullptr) { … }
Instruction *llvm::removeUnwindEdge(BasicBlock *BB, DomTreeUpdater *DTU) { … }
bool llvm::removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU,
MemorySSAUpdater *MSSAU) { … }
void llvm::combineMetadata(Instruction *K, const Instruction *J,
ArrayRef<unsigned> KnownIDs, bool DoesKMove) { … }
void llvm::combineMetadataForCSE(Instruction *K, const Instruction *J,
bool KDominatesJ) { … }
void llvm::copyMetadataForLoad(LoadInst &Dest, const LoadInst &Source) { … }
void llvm::patchReplacementInstruction(Instruction *I, Value *Repl) { … }
template <typename RootType, typename ShouldReplaceFn>
static unsigned replaceDominatedUsesWith(Value *From, Value *To,
const RootType &Root,
const ShouldReplaceFn &ShouldReplace) { … }
unsigned llvm::replaceNonLocalUsesWith(Instruction *From, Value *To) { … }
unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To,
DominatorTree &DT,
const BasicBlockEdge &Root) { … }
unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To,
DominatorTree &DT,
const BasicBlock *BB) { … }
unsigned llvm::replaceDominatedUsesWithIf(
Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Root,
function_ref<bool(const Use &U, const Value *To)> ShouldReplace) { … }
unsigned llvm::replaceDominatedUsesWithIf(
Value *From, Value *To, DominatorTree &DT, const BasicBlock *BB,
function_ref<bool(const Use &U, const Value *To)> ShouldReplace) { … }
bool llvm::callsGCLeafFunction(const CallBase *Call,
const TargetLibraryInfo &TLI) { … }
void llvm::copyNonnullMetadata(const LoadInst &OldLI, MDNode *N,
LoadInst &NewLI) { … }
void llvm::copyRangeMetadata(const DataLayout &DL, const LoadInst &OldLI,
MDNode *N, LoadInst &NewLI) { … }
void llvm::dropDebugUsers(Instruction &I) { … }
void llvm::hoistAllInstructionsInto(BasicBlock *DomBlock, Instruction *InsertPt,
BasicBlock *BB) { … }
DIExpression *llvm::getExpressionForConstant(DIBuilder &DIB, const Constant &C,
Type &Ty) { … }
void llvm::remapDebugVariable(ValueToValueMapTy &Mapping, Instruction *Inst) { … }
namespace {
struct BitPart { … };
}
static const std::optional<BitPart> &
collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
std::map<Value *, std::optional<BitPart>> &BPS, int Depth,
bool &FoundRoot) { … }
static bool bitTransformIsCorrectForBSwap(unsigned From, unsigned To,
unsigned BitWidth) { … }
static bool bitTransformIsCorrectForBitReverse(unsigned From, unsigned To,
unsigned BitWidth) { … }
bool llvm::recognizeBSwapOrBitReverseIdiom(
Instruction *I, bool MatchBSwaps, bool MatchBitReversals,
SmallVectorImpl<Instruction *> &InsertedInsts) { … }
void llvm::maybeMarkSanitizerLibraryCallNoBuiltin(
CallInst *CI, const TargetLibraryInfo *TLI) { … }
bool llvm::canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx) { … }
Value *llvm::invertCondition(Value *Condition) { … }
bool llvm::inferAttributesFromOthers(Function &F) { … }