#include "llvm/Transforms/Scalar/ConstraintElimination.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ConstraintSystem.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <cmath>
#include <optional>
#include <string>
usingnamespacellvm;
usingnamespacePatternMatch;
#define DEBUG_TYPE …
STATISTIC(NumCondsRemoved, "Number of instructions removed");
DEBUG_COUNTER(EliminatedCounter, "conds-eliminated",
"Controls which conditions are eliminated");
static cl::opt<unsigned>
MaxRows("constraint-elimination-max-rows", cl::init(500), cl::Hidden,
cl::desc("Maximum number of rows to keep in constraint system"));
static cl::opt<bool> DumpReproducers(
"constraint-elimination-dump-reproducers", cl::init(false), cl::Hidden,
cl::desc("Dump IR to reproduce successful transformations."));
static int64_t MaxConstraintValue = …;
static int64_t MinSignedConstraintValue = …;
static int64_t multiplyWithOverflow(int64_t A, int64_t B) { … }
static int64_t addWithOverflow(int64_t A, int64_t B) { … }
static Instruction *getContextInstForUse(Use &U) { … }
namespace {
struct ConditionTy { … };
struct FactOrCheck { … };
struct State { … };
class ConstraintInfo;
struct StackEntry { … };
struct ConstraintTy { … };
class ConstraintInfo { … };
struct DecompEntry { … };
struct Decomposition { … };
struct OffsetResult { … };
}
static OffsetResult collectOffsets(GEPOperator &GEP, const DataLayout &DL) { … }
static Decomposition decompose(Value *V,
SmallVectorImpl<ConditionTy> &Preconditions,
bool IsSigned, const DataLayout &DL);
static bool canUseSExt(ConstantInt *CI) { … }
static Decomposition decomposeGEP(GEPOperator &GEP,
SmallVectorImpl<ConditionTy> &Preconditions,
bool IsSigned, const DataLayout &DL) { … }
static Decomposition decompose(Value *V,
SmallVectorImpl<ConditionTy> &Preconditions,
bool IsSigned, const DataLayout &DL) { … }
ConstraintTy
ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
SmallVectorImpl<Value *> &NewVariables) const { … }
ConstraintTy ConstraintInfo::getConstraintForSolving(CmpInst::Predicate Pred,
Value *Op0,
Value *Op1) const { … }
bool ConstraintTy::isValid(const ConstraintInfo &Info) const { … }
std::optional<bool>
ConstraintTy::isImpliedBy(const ConstraintSystem &CS) const { … }
bool ConstraintInfo::doesHold(CmpInst::Predicate Pred, Value *A,
Value *B) const { … }
void ConstraintInfo::transferToOtherSystem(
CmpInst::Predicate Pred, Value *A, Value *B, unsigned NumIn,
unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) { … }
#ifndef NDEBUG
static void dumpConstraint(ArrayRef<int64_t> C,
const DenseMap<Value *, unsigned> &Value2Index) {
ConstraintSystem CS(Value2Index);
CS.addVariableRowFill(C);
CS.dump();
}
#endif
void State::addInfoForInductions(BasicBlock &BB) { … }
void State::addInfoFor(BasicBlock &BB) { … }
#ifndef NDEBUG
static void dumpUnpackedICmp(raw_ostream &OS, ICmpInst::Predicate Pred,
Value *LHS, Value *RHS) {
OS << "icmp " << Pred << ' ';
LHS->printAsOperand(OS, true);
OS << ", ";
RHS->printAsOperand(OS, false);
}
#endif
namespace {
struct ReproducerEntry { … };
}
static void generateReproducer(CmpInst *Cond, Module *M,
ArrayRef<ReproducerEntry> Stack,
ConstraintInfo &Info, DominatorTree &DT) { … }
static std::optional<bool> checkCondition(CmpInst::Predicate Pred, Value *A,
Value *B, Instruction *CheckInst,
ConstraintInfo &Info) { … }
static bool checkAndReplaceCondition(
CmpInst *Cmp, ConstraintInfo &Info, unsigned NumIn, unsigned NumOut,
Instruction *ContextInst, Module *ReproducerModule,
ArrayRef<ReproducerEntry> ReproducerCondStack, DominatorTree &DT,
SmallVectorImpl<Instruction *> &ToRemove) { … }
static bool checkAndReplaceMinMax(MinMaxIntrinsic *MinMax, ConstraintInfo &Info,
SmallVectorImpl<Instruction *> &ToRemove) { … }
static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info,
SmallVectorImpl<Instruction *> &ToRemove) { … }
static void
removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
Module *ReproducerModule,
SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
SmallVectorImpl<StackEntry> &DFSInStack) { … }
static bool checkOrAndOpImpliedByOther(
FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule,
SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
SmallVectorImpl<StackEntry> &DFSInStack) { … }
void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B,
unsigned NumIn, unsigned NumOut,
SmallVectorImpl<StackEntry> &DFSInStack) { … }
static bool replaceSubOverflowUses(IntrinsicInst *II, Value *A, Value *B,
SmallVectorImpl<Instruction *> &ToRemove) { … }
static bool
tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info,
SmallVectorImpl<Instruction *> &ToRemove) { … }
static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
ScalarEvolution &SE,
OptimizationRemarkEmitter &ORE) { … }
PreservedAnalyses ConstraintEliminationPass::run(Function &F,
FunctionAnalysisManager &AM) { … }