#include "llvm/Transforms/Scalar/GuardWidening.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/GuardUtils.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.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/KnownBits.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/GuardUtils.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include <functional>
usingnamespacellvm;
#define DEBUG_TYPE …
STATISTIC(GuardsEliminated, "Number of eliminated guards");
STATISTIC(CondBranchEliminated, "Number of eliminated conditional branches");
STATISTIC(FreezeAdded, "Number of freeze instruction introduced");
static cl::opt<bool>
WidenBranchGuards("guard-widening-widen-branch-guards", cl::Hidden,
cl::desc("Whether or not we should widen guards "
"expressed as branches by widenable conditions"),
cl::init(true));
namespace {
static Value *getCondition(Instruction *I) { … }
static void setCondition(Instruction *I, Value *NewCond) { … }
static void eliminateGuard(Instruction *GuardInst, MemorySSAUpdater *MSSAU) { … }
static std::optional<BasicBlock::iterator>
findInsertionPointForWideCondition(Instruction *WCOrGuard) { … }
class GuardWideningImpl { … };
}
static bool isSupportedGuardInstruction(const Instruction *Insn) { … }
bool GuardWideningImpl::run() { … }
bool GuardWideningImpl::eliminateInstrViaWidening(
Instruction *Instr, const df_iterator<DomTreeNode *> &DFSI,
const DenseMap<BasicBlock *, SmallVector<Instruction *, 8>>
&GuardsInBlock) { … }
GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
Instruction *DominatedInstr, Instruction *ToWiden,
BasicBlock::iterator WideningPoint, SmallVectorImpl<Value *> &ChecksToHoist,
SmallVectorImpl<Value *> &ChecksToWiden) { … }
bool GuardWideningImpl::canBeHoistedTo(
const Value *V, BasicBlock::iterator Loc,
SmallPtrSetImpl<const Instruction *> &Visited) const { … }
void GuardWideningImpl::makeAvailableAt(Value *V,
BasicBlock::iterator Loc) const { … }
static std::optional<BasicBlock::iterator>
getFreezeInsertPt(Value *V, const DominatorTree &DT) { … }
Value *GuardWideningImpl::freezeAndPush(Value *Orig,
BasicBlock::iterator InsertPt) { … }
std::optional<Value *>
GuardWideningImpl::mergeChecks(SmallVectorImpl<Value *> &ChecksToHoist,
SmallVectorImpl<Value *> &ChecksToWiden,
std::optional<BasicBlock::iterator> InsertPt) { … }
Value *GuardWideningImpl::hoistChecks(SmallVectorImpl<Value *> &ChecksToHoist,
Value *OldCondition,
BasicBlock::iterator InsertPt) { … }
bool GuardWideningImpl::parseRangeChecks(
Value *CheckCond, SmallVectorImpl<GuardWideningImpl::RangeCheck> &Checks) { … }
bool GuardWideningImpl::combineRangeChecks(
SmallVectorImpl<GuardWideningImpl::RangeCheck> &Checks,
SmallVectorImpl<GuardWideningImpl::RangeCheck> &RangeChecksOut) const { … }
#ifndef NDEBUG
StringRef GuardWideningImpl::scoreTypeToString(WideningScore WS) {
switch (WS) {
case WS_IllegalOrNegative:
return "IllegalOrNegative";
case WS_Neutral:
return "Neutral";
case WS_Positive:
return "Positive";
case WS_VeryPositive:
return "VeryPositive";
}
llvm_unreachable("Fully covered switch above!");
}
#endif
PreservedAnalyses GuardWideningPass::run(Function &F,
FunctionAnalysisManager &AM) { … }
PreservedAnalyses GuardWideningPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &U) { … }