#include "InstCombineInternal.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetFolder.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/Utils/Local.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.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/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/Metadata.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/PatternMatch.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/InitializePasses.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#define DEBUG_TYPE …
#include "llvm/Transforms/Utils/InstructionWorklist.h"
#include <optional>
usingnamespacellvm;
usingnamespacellvm::PatternMatch;
STATISTIC(NumWorklistIterations,
"Number of instruction combining iterations performed");
STATISTIC(NumOneIteration, "Number of functions with one iteration");
STATISTIC(NumTwoIterations, "Number of functions with two iterations");
STATISTIC(NumThreeIterations, "Number of functions with three iterations");
STATISTIC(NumFourOrMoreIterations,
"Number of functions with four or more iterations");
STATISTIC(NumCombined , "Number of insts combined");
STATISTIC(NumConstProp, "Number of constant folds");
STATISTIC(NumDeadInst , "Number of dead inst eliminated");
STATISTIC(NumSunkInst , "Number of instructions sunk");
STATISTIC(NumExpand, "Number of expansions");
STATISTIC(NumFactor , "Number of factorizations");
STATISTIC(NumReassoc , "Number of reassociations");
DEBUG_COUNTER(VisitCounter, "instcombine-visit",
"Controls which instructions are visited");
static cl::opt<bool>
EnableCodeSinking("instcombine-code-sinking", cl::desc("Enable code sinking"),
cl::init(true));
static cl::opt<unsigned> MaxSinkNumUsers(
"instcombine-max-sink-users", cl::init(32),
cl::desc("Maximum number of undroppable users for instruction sinking"));
static cl::opt<unsigned>
MaxArraySize("instcombine-maxarray-size", cl::init(1024),
cl::desc("Maximum array size considered when doing a combine"));
static cl::opt<unsigned> ShouldLowerDbgDeclare("instcombine-lower-dbg-declare",
cl::Hidden, cl::init(true));
std::optional<Instruction *>
InstCombiner::targetInstCombineIntrinsic(IntrinsicInst &II) { … }
std::optional<Value *> InstCombiner::targetSimplifyDemandedUseBitsIntrinsic(
IntrinsicInst &II, APInt DemandedMask, KnownBits &Known,
bool &KnownBitsComputed) { … }
std::optional<Value *> InstCombiner::targetSimplifyDemandedVectorEltsIntrinsic(
IntrinsicInst &II, APInt DemandedElts, APInt &PoisonElts,
APInt &PoisonElts2, APInt &PoisonElts3,
std::function<void(Instruction *, unsigned, APInt, APInt &)>
SimplifyAndSetOp) { … }
bool InstCombiner::isValidAddrSpaceCast(unsigned FromAS, unsigned ToAS) const { … }
Value *InstCombinerImpl::EmitGEPOffset(GEPOperator *GEP, bool RewriteGEP) { … }
bool InstCombinerImpl::isDesirableIntType(unsigned BitWidth) const { … }
bool InstCombinerImpl::shouldChangeType(unsigned FromWidth,
unsigned ToWidth) const { … }
bool InstCombinerImpl::shouldChangeType(Type *From, Type *To) const { … }
static bool maintainNoSignedWrap(BinaryOperator &I, Value *B, Value *C) { … }
static bool hasNoUnsignedWrap(BinaryOperator &I) { … }
static bool hasNoSignedWrap(BinaryOperator &I) { … }
static void ClearSubclassDataAfterReassociation(BinaryOperator &I) { … }
static bool simplifyAssocCastAssoc(BinaryOperator *BinOp1,
InstCombinerImpl &IC) { … }
Value *InstCombinerImpl::simplifyIntToPtrRoundTripCast(Value *Val) { … }
bool InstCombinerImpl::SimplifyAssociativeOrCommutative(BinaryOperator &I) { … }
static bool leftDistributesOverRight(Instruction::BinaryOps LOp,
Instruction::BinaryOps ROp) { … }
static bool rightDistributesOverLeft(Instruction::BinaryOps LOp,
Instruction::BinaryOps ROp) { … }
static Value *getIdentityValue(Instruction::BinaryOps Opcode, Value *V) { … }
static Instruction::BinaryOps
getBinOpsForFactorization(Instruction::BinaryOps TopOpcode, BinaryOperator *Op,
Value *&LHS, Value *&RHS, BinaryOperator *OtherOp) { … }
static Value *tryFactorization(BinaryOperator &I, const SimplifyQuery &SQ,
InstCombiner::BuilderTy &Builder,
Instruction::BinaryOps InnerOpcode, Value *A,
Value *B, Value *C, Value *D) { … }
Instruction *InstCombinerImpl::tryFoldInstWithCtpopWithNot(Instruction *I) { … }
Instruction *InstCombinerImpl::foldBinOpShiftWithShift(BinaryOperator &I) { … }
Instruction *
InstCombinerImpl::foldBinOpOfSelectAndCastOfSelectCondition(BinaryOperator &I) { … }
Value *InstCombinerImpl::tryFactorizationFolds(BinaryOperator &I) { … }
Value *InstCombinerImpl::foldUsingDistributiveLaws(BinaryOperator &I) { … }
static std::optional<std::pair<Value *, Value *>>
matchSymmetricPhiNodesPair(PHINode *LHS, PHINode *RHS) { … }
std::optional<std::pair<Value *, Value *>>
InstCombinerImpl::matchSymmetricPair(Value *LHS, Value *RHS) { … }
Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
Value *LHS,
Value *RHS) { … }
void InstCombinerImpl::freelyInvertAllUsersOf(Value *I, Value *IgnoredUser) { … }
Value *InstCombinerImpl::dyn_castNegVal(Value *V) const { … }
Instruction *InstCombinerImpl::foldFBinOpOfIntCastsFromSign(
BinaryOperator &BO, bool OpsFromSigned, std::array<Value *, 2> IntOps,
Constant *Op1FpC, SmallVectorImpl<WithCache<const Value *>> &OpsKnown) { … }
Instruction *InstCombinerImpl::foldFBinOpOfIntCasts(BinaryOperator &BO) { … }
Instruction *InstCombinerImpl::foldBinopOfSextBoolToSelect(BinaryOperator &BO) { … }
static Constant *constantFoldOperationIntoSelectOperand(Instruction &I,
SelectInst *SI,
bool IsTrueArm) { … }
static Value *foldOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
Value *NewOp, InstCombiner &IC) { … }
Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
bool FoldWithMultiUse) { … }
static Value *simplifyInstructionWithPHI(Instruction &I, PHINode *PN,
Value *InValue, BasicBlock *InBB,
const DataLayout &DL,
const SimplifyQuery SQ) { … }
Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) { … }
Instruction *InstCombinerImpl::foldBinopWithPhiOperands(BinaryOperator &BO) { … }
Instruction *InstCombinerImpl::foldBinOpIntoSelectOrPhi(BinaryOperator &I) { … }
static bool shouldMergeGEPs(GEPOperator &GEP, GEPOperator &Src) { … }
Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) { … }
Instruction *InstCombinerImpl::narrowMathIfNoOverflow(BinaryOperator &BO) { … }
static GEPNoWrapFlags getMergedGEPNoWrapFlags(GEPOperator &GEP1,
GEPOperator &GEP2) { … }
static Instruction *foldSelectGEP(GetElementPtrInst &GEP,
InstCombiner::BuilderTy &Builder) { … }
static Instruction *canonicalizeGEPOfConstGEPI8(GetElementPtrInst &GEP,
GEPOperator *Src,
InstCombinerImpl &IC) { … }
Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
GEPOperator *Src) { … }
Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
BuilderTy *Builder,
bool &DoesConsume, unsigned Depth) { … }
Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) { … }
static bool isNeverEqualToUnescapedAlloc(Value *V, const TargetLibraryInfo &TLI,
Instruction *AI) { … }
static bool isRemovableWrite(CallBase &CB, Value *UsedV,
const TargetLibraryInfo &TLI) { … }
static bool isAllocSiteRemovable(Instruction *AI,
SmallVectorImpl<WeakTrackingVH> &Users,
const TargetLibraryInfo &TLI) { … }
Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { … }
static Instruction *tryToMoveFreeBeforeNullTest(CallInst &FI,
const DataLayout &DL) { … }
Instruction *InstCombinerImpl::visitFree(CallInst &FI, Value *Op) { … }
Instruction *InstCombinerImpl::visitReturnInst(ReturnInst &RI) { … }
bool InstCombinerImpl::removeInstructionsBeforeUnreachable(Instruction &I) { … }
Instruction *InstCombinerImpl::visitUnreachableInst(UnreachableInst &I) { … }
Instruction *InstCombinerImpl::visitUnconditionalBranchInst(BranchInst &BI) { … }
void InstCombinerImpl::addDeadEdge(BasicBlock *From, BasicBlock *To,
SmallVectorImpl<BasicBlock *> &Worklist) { … }
void InstCombinerImpl::handleUnreachableFrom(
Instruction *I, SmallVectorImpl<BasicBlock *> &Worklist) { … }
void InstCombinerImpl::handlePotentiallyDeadBlocks(
SmallVectorImpl<BasicBlock *> &Worklist) { … }
void InstCombinerImpl::handlePotentiallyDeadSuccessors(BasicBlock *BB,
BasicBlock *LiveSucc) { … }
Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) { … }
static Value *simplifySwitchOnSelectUsingRanges(SwitchInst &SI,
SelectInst *Select,
bool IsTrueArm) { … }
Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) { … }
Instruction *
InstCombinerImpl::foldExtractOfOverflowIntrinsic(ExtractValueInst &EV) { … }
Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) { … }
static bool isCatchAll(EHPersonality Personality, Constant *TypeInfo) { … }
static bool shorter_filter(const Value *LHS, const Value *RHS) { … }
Instruction *InstCombinerImpl::visitLandingPadInst(LandingPadInst &LI) { … }
Value *
InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating(FreezeInst &OrigFI) { … }
Instruction *InstCombinerImpl::foldFreezeIntoRecurrence(FreezeInst &FI,
PHINode *PN) { … }
bool InstCombinerImpl::freezeOtherUses(FreezeInst &FI) { … }
static bool isUsedWithinShuffleVector(Value *V) { … }
Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) { … }
static bool SoleWriteToDeadLocal(Instruction *I, TargetLibraryInfo &TLI) { … }
bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
BasicBlock *DestBlock) { … }
void InstCombinerImpl::tryToSinkInstructionDbgValues(
Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
BasicBlock *DestBlock, SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers) { … }
void InstCombinerImpl::tryToSinkInstructionDbgVariableRecords(
Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
BasicBlock *DestBlock,
SmallVectorImpl<DbgVariableRecord *> &DbgVariableRecords) { … }
bool InstCombinerImpl::run() { … }
class AliasScopeTracker { … };
bool InstCombinerImpl::prepareWorklist(Function &F) { … }
void InstCombiner::computeBackEdges() { … }
static bool combineInstructionsOverFunction(
Function &F, InstructionWorklist &Worklist, AliasAnalysis *AA,
AssumptionCache &AC, TargetLibraryInfo &TLI, TargetTransformInfo &TTI,
DominatorTree &DT, OptimizationRemarkEmitter &ORE, BlockFrequencyInfo *BFI,
BranchProbabilityInfo *BPI, ProfileSummaryInfo *PSI,
const InstCombineOptions &Opts) { … }
InstCombinePass::InstCombinePass(InstCombineOptions Opts) : … { … }
void InstCombinePass::printPipeline(
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { … }
PreservedAnalyses InstCombinePass::run(Function &F,
FunctionAnalysisManager &AM) { … }
void InstructionCombiningPass::getAnalysisUsage(AnalysisUsage &AU) const { … }
bool InstructionCombiningPass::runOnFunction(Function &F) { … }
char InstructionCombiningPass::ID = …;
InstructionCombiningPass::InstructionCombiningPass() : … { … }
INITIALIZE_PASS_BEGIN(InstructionCombiningPass, "instcombine",
"Combine redundant instructions", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LazyBlockFrequencyInfoPass)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_END(InstructionCombiningPass, "instcombine",
"Combine redundant instructions", false, false)
void llvm::initializeInstCombine(PassRegistry &Registry) { … }
FunctionPass *llvm::createInstructionCombiningPass() { … }