#ifndef LLVM_TRANSFORMS_SCALAR_CONSTANTHOISTING_H
#define LLVM_TRANSFORMS_SCALAR_CONSTANTHOISTING_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/PassManager.h"
#include <algorithm>
#include <vector>
namespace llvm {
class BasicBlock;
class BlockFrequencyInfo;
class Constant;
class ConstantInt;
class ConstantExpr;
class DominatorTree;
class Function;
class GlobalVariable;
class Instruction;
class ProfileSummaryInfo;
class TargetTransformInfo;
namespace consthoist {
struct ConstantUser {
Instruction *Inst;
unsigned OpndIdx;
ConstantUser(Instruction *Inst, unsigned Idx) : Inst(Inst), OpndIdx(Idx) {}
};
using ConstantUseListType = SmallVector<ConstantUser, 8>;
struct ConstantCandidate {
ConstantUseListType Uses;
ConstantInt *ConstInt;
ConstantExpr *ConstExpr;
unsigned CumulativeCost = 0;
ConstantCandidate(ConstantInt *ConstInt, ConstantExpr *ConstExpr=nullptr) :
ConstInt(ConstInt), ConstExpr(ConstExpr) {}
void addUser(Instruction *Inst, unsigned Idx, unsigned Cost) {
CumulativeCost += Cost;
Uses.push_back(ConstantUser(Inst, Idx));
}
};
struct RebasedConstantInfo {
ConstantUseListType Uses;
Constant *Offset;
Type *Ty;
RebasedConstantInfo(ConstantUseListType &&Uses, Constant *Offset,
Type *Ty=nullptr) : Uses(std::move(Uses)), Offset(Offset), Ty(Ty) {}
};
using RebasedConstantListType = SmallVector<RebasedConstantInfo, 4>;
struct ConstantInfo {
ConstantInt *BaseInt;
ConstantExpr *BaseExpr;
RebasedConstantListType RebasedConstants;
};
}
class ConstantHoistingPass : public PassInfoMixin<ConstantHoistingPass> {
public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
bool runImpl(Function &F, TargetTransformInfo &TTI, DominatorTree &DT,
BlockFrequencyInfo *BFI, BasicBlock &Entry,
ProfileSummaryInfo *PSI);
void cleanup() {
ClonedCastMap.clear();
ConstIntCandVec.clear();
for (auto MapEntry : ConstGEPCandMap)
MapEntry.second.clear();
ConstGEPCandMap.clear();
ConstIntInfoVec.clear();
for (auto MapEntry : ConstGEPInfoMap)
MapEntry.second.clear();
ConstGEPInfoMap.clear();
}
private:
using ConstPtrUnionType = PointerUnion<ConstantInt *, ConstantExpr *>;
using ConstCandMapType = DenseMap<ConstPtrUnionType, unsigned>;
const TargetTransformInfo *TTI;
DominatorTree *DT;
BlockFrequencyInfo *BFI;
LLVMContext *Ctx;
const DataLayout *DL;
BasicBlock *Entry;
ProfileSummaryInfo *PSI;
using ConstCandVecType = std::vector<consthoist::ConstantCandidate>;
using GVCandVecMapType = MapVector<GlobalVariable *, ConstCandVecType>;
ConstCandVecType ConstIntCandVec;
GVCandVecMapType ConstGEPCandMap;
using ConstInfoVecType = SmallVector<consthoist::ConstantInfo, 8>;
using GVInfoVecMapType = MapVector<GlobalVariable *, ConstInfoVecType>;
ConstInfoVecType ConstIntInfoVec;
GVInfoVecMapType ConstGEPInfoMap;
MapVector<Instruction *, Instruction *> ClonedCastMap;
Instruction *findMatInsertPt(Instruction *Inst, unsigned Idx = ~0U) const;
SetVector<Instruction *>
findConstantInsertionPoint(const consthoist::ConstantInfo &ConstInfo) const;
void collectConstantCandidates(ConstCandMapType &ConstCandMap,
Instruction *Inst, unsigned Idx,
ConstantInt *ConstInt);
void collectConstantCandidates(ConstCandMapType &ConstCandMap,
Instruction *Inst, unsigned Idx,
ConstantExpr *ConstExpr);
void collectConstantCandidates(ConstCandMapType &ConstCandMap,
Instruction *Inst, unsigned Idx);
void collectConstantCandidates(ConstCandMapType &ConstCandMap,
Instruction *Inst);
void collectConstantCandidates(Function &Fn);
void findAndMakeBaseConstant(ConstCandVecType::iterator S,
ConstCandVecType::iterator E,
SmallVectorImpl<consthoist::ConstantInfo> &ConstInfoVec);
unsigned maximizeConstantsInRange(ConstCandVecType::iterator S,
ConstCandVecType::iterator E,
ConstCandVecType::iterator &MaxCostItr);
void findBaseConstants(GlobalVariable *BaseGV);
void emitBaseConstants(Instruction *Base, Constant *Offset, Type *Ty,
const consthoist::ConstantUser &ConstUser);
bool emitBaseConstants(GlobalVariable *BaseGV);
void deleteDeadCastInst() const;
};
}
#endif