#include "PPC.h"
#include "PPCSubtarget.h"
#include "PPCTargetMachine.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/IntrinsicsPowerPC.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
#include <cassert>
#include <cmath>
#include <iterator>
#include <utility>
#define DEBUG_TYPE …
usingnamespacellvm;
static cl::opt<unsigned>
MaxVarsPrep("ppc-formprep-max-vars", cl::Hidden, cl::init(24),
cl::desc("Potential common base number threshold per function "
"for PPC loop prep"));
static cl::opt<bool> PreferUpdateForm("ppc-formprep-prefer-update",
cl::init(true), cl::Hidden,
cl::desc("prefer update form when ds form is also a update form"));
static cl::opt<bool> EnableUpdateFormForNonConstInc(
"ppc-formprep-update-nonconst-inc", cl::init(false), cl::Hidden,
cl::desc("prepare update form when the load/store increment is a loop "
"invariant non-const value."));
static cl::opt<bool> EnableChainCommoning(
"ppc-formprep-chain-commoning", cl::init(false), cl::Hidden,
cl::desc("Enable chain commoning in PPC loop prepare pass."));
static cl::opt<unsigned> MaxVarsUpdateForm("ppc-preinc-prep-max-vars",
cl::Hidden, cl::init(3),
cl::desc("Potential PHI threshold per loop for PPC loop prep of update "
"form"));
static cl::opt<unsigned> MaxVarsDSForm("ppc-dsprep-max-vars",
cl::Hidden, cl::init(3),
cl::desc("Potential PHI threshold per loop for PPC loop prep of DS form"));
static cl::opt<unsigned> MaxVarsDQForm("ppc-dqprep-max-vars",
cl::Hidden, cl::init(8),
cl::desc("Potential PHI threshold per loop for PPC loop prep of DQ form"));
static cl::opt<unsigned> MaxVarsChainCommon(
"ppc-chaincommon-max-vars", cl::Hidden, cl::init(4),
cl::desc("Bucket number per loop for PPC loop chain common"));
static cl::opt<unsigned> DispFormPrepMinThreshold("ppc-dispprep-min-threshold",
cl::Hidden, cl::init(2),
cl::desc("Minimal common base load/store instructions triggering DS/DQ form "
"preparation"));
static cl::opt<unsigned> ChainCommonPrepMinThreshold(
"ppc-chaincommon-min-threshold", cl::Hidden, cl::init(4),
cl::desc("Minimal common base load/store instructions triggering chain "
"commoning preparation. Must be not smaller than 4"));
STATISTIC(PHINodeAlreadyExistsUpdate, "PHI node already in pre-increment form");
STATISTIC(PHINodeAlreadyExistsDS, "PHI node already in DS form");
STATISTIC(PHINodeAlreadyExistsDQ, "PHI node already in DQ form");
STATISTIC(DSFormChainRewritten, "Num of DS form chain rewritten");
STATISTIC(DQFormChainRewritten, "Num of DQ form chain rewritten");
STATISTIC(UpdFormChainRewritten, "Num of update form chain rewritten");
STATISTIC(ChainCommoningRewritten, "Num of commoning chains");
namespace {
struct BucketElement { … };
struct Bucket { … };
enum PrepForm { … };
class PPCLoopInstrFormPrep : public FunctionPass { … };
}
char PPCLoopInstrFormPrep::ID = …;
static const char *name = …;
INITIALIZE_PASS_BEGIN(PPCLoopInstrFormPrep, DEBUG_TYPE, name, false, false)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
INITIALIZE_PASS_END(PPCLoopInstrFormPrep, DEBUG_TYPE, name, false, false)
static constexpr StringRef PHINodeNameSuffix = …;
static constexpr StringRef CastNodeNameSuffix = …;
static constexpr StringRef GEPNodeIncNameSuffix = …;
static constexpr StringRef GEPNodeOffNameSuffix = …;
FunctionPass *llvm::createPPCLoopInstrFormPrepPass(PPCTargetMachine &TM) { … }
static bool IsPtrInBounds(Value *BasePtr) { … }
static std::string getInstrName(const Value *I, StringRef Suffix) { … }
static Value *getPointerOperandAndType(Value *MemI,
Type **PtrElementType = nullptr) { … }
bool PPCLoopInstrFormPrep::runOnFunction(Function &F) { … }
bool PPCLoopInstrFormPrep::prepareBasesForCommoningChains(Bucket &CBucket) { … }
bool PPCLoopInstrFormPrep::chainCommoning(Loop *L,
SmallVector<Bucket, 16> &Buckets) { … }
bool PPCLoopInstrFormPrep::rewriteLoadStoresForCommoningChains(
Loop *L, Bucket &Bucket, SmallSet<BasicBlock *, 16> &BBChanged) { … }
std::pair<Instruction *, Instruction *>
PPCLoopInstrFormPrep::rewriteForBase(Loop *L, const SCEVAddRecExpr *BasePtrSCEV,
Instruction *BaseMemI, bool CanPreInc,
PrepForm Form, SCEVExpander &SCEVE,
SmallPtrSet<Value *, 16> &DeletedPtrs) { … }
Instruction *PPCLoopInstrFormPrep::rewriteForBucketElement(
std::pair<Instruction *, Instruction *> Base, const BucketElement &Element,
Value *OffToBase, SmallPtrSet<Value *, 16> &DeletedPtrs) { … }
void PPCLoopInstrFormPrep::addOneCandidate(
Instruction *MemI, const SCEV *LSCEV, SmallVector<Bucket, 16> &Buckets,
std::function<bool(const SCEV *)> isValidDiff, unsigned MaxCandidateNum) { … }
SmallVector<Bucket, 16> PPCLoopInstrFormPrep::collectCandidates(
Loop *L,
std::function<bool(const Instruction *, Value *, const Type *)>
isValidCandidate,
std::function<bool(const SCEV *)> isValidDiff, unsigned MaxCandidateNum) { … }
bool PPCLoopInstrFormPrep::prepareBaseForDispFormChain(Bucket &BucketChain,
PrepForm Form) { … }
bool PPCLoopInstrFormPrep::prepareBaseForUpdateFormChain(Bucket &BucketChain) { … }
bool PPCLoopInstrFormPrep::rewriteLoadStores(
Loop *L, Bucket &BucketChain, SmallSet<BasicBlock *, 16> &BBChanged,
PrepForm Form) { … }
bool PPCLoopInstrFormPrep::updateFormPrep(Loop *L,
SmallVector<Bucket, 16> &Buckets) { … }
bool PPCLoopInstrFormPrep::dispFormPrep(Loop *L,
SmallVector<Bucket, 16> &Buckets,
PrepForm Form) { … }
Value *PPCLoopInstrFormPrep::getNodeForInc(Loop *L, Instruction *MemI,
const SCEV *BasePtrIncSCEV) { … }
bool PPCLoopInstrFormPrep::alreadyPrepared(Loop *L, Instruction *MemI,
const SCEV *BasePtrStartSCEV,
const SCEV *BasePtrIncSCEV,
PrepForm Form) { … }
bool PPCLoopInstrFormPrep::runOnLoop(Loop *L) { … }