49#define DEBUG_TYPE "canon-freeze"
53class CanonicalizeFreezeInLoops :
public LoopPass {
57 CanonicalizeFreezeInLoops();
64class CanonicalizeFreezeInLoopsImpl {
69 struct FrozenIndPHIInfo {
76 unsigned StepValIdx = 0;
79 :
PHI(
PHI), StepInst(StepInst) {}
86 auto Opc =
I->getOpcode();
88 return Opc == Instruction::Add || Opc == Instruction::Sub ||
89 Opc == Instruction::Mul;
92 void InsertFreezeAndForgetFromSCEV(
Use &U);
96 : L(L), SE(SE), DT(DT) {}
104void CanonicalizeFreezeInLoopsImpl::InsertFreezeAndForgetFromSCEV(
Use &U) {
105 auto *PH =
L->getLoopPreheader();
107 auto *UserI = cast<Instruction>(
U.getUser());
108 auto *ValueToFr =
U.get();
109 assert(
L->contains(UserI->getParent()) &&
110 "Should not process an instruction that isn't inside the loop");
118 U.set(
new FreezeInst(ValueToFr, ValueToFr->getName() +
".frozen",
119 PH->getTerminator()));
121 SE.forgetValue(UserI);
124bool CanonicalizeFreezeInLoopsImpl::run() {
126 if (!
L->isLoopSimplifyForm())
131 for (
auto &
PHI :
L->getHeader()->phis()) {
137 FrozenIndPHIInfo
Info(&
PHI,
ID.getInductionBinOp());
138 if (!
Info.StepInst || !canHandleInst(
Info.StepInst)) {
144 Info.StepValIdx =
Info.StepInst->getOperand(0) == &
PHI;
146 if (
auto *StepI = dyn_cast<Instruction>(StepV)) {
147 if (
L->contains(StepI->getParent())) {
154 auto Visit = [&](
User *
U) {
155 if (
auto *FI = dyn_cast<FreezeInst>(U)) {
165 if (Candidates.
empty())
169 for (
const auto &Info : Candidates) {
175 assert(StepI &&
"Step instruction should have been found");
181 SE.forgetValue(StepI);
186 unsigned OperandIdx =
187 PHI->getOperandNumForIncomingValue(
PHI->getIncomingValue(0) == StepI);
188 InsertFreezeAndForgetFromSCEV(
PHI->getOperandUse(OperandIdx));
192 for (
const auto &Item : Candidates) {
196 FI->replaceAllUsesWith(FI->getOperand(0));
197 FI->eraseFromParent();
203CanonicalizeFreezeInLoops::CanonicalizeFreezeInLoops() :
LoopPass(
ID) {
207void CanonicalizeFreezeInLoops::getAnalysisUsage(
AnalysisUsage &AU)
const {
222 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
223 auto &DT = getAnalysis<DominatorTreeWrapperPass>().
getDomTree();
224 return CanonicalizeFreezeInLoopsImpl(L, SE, DT).run();
231 if (!CanonicalizeFreezeInLoopsImpl(&L, AR.
SE, AR.
DT).run())
238 "Canonicalize Freeze Instructions in Loops",
false,
false)
246 return new CanonicalizeFreezeInLoops();
249char CanonicalizeFreezeInLoops::ID = 0;
Analysis containing CSE Info
This header provides classes for managing per-loop analyses.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequiredID(const void *ID)
AnalysisUsage & addPreservedID(const void *ID)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U)
Legacy analysis pass which computes a DominatorTree.
DominatorTree & getDomTree()
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
This class represents a freeze function that returns random concrete value if an operand is either a ...
A struct for saving information about induction variables.
static bool isInductionPHI(PHINode *Phi, const Loop *L, ScalarEvolution *SE, InductionDescriptor &D, const SCEV *Expr=nullptr, SmallVectorImpl< Instruction * > *CastsToIgnore=nullptr)
Returns true if Phi is an induction in the loop L.
void dropPoisonGeneratingFlags()
Drops flags that may cause this instruction to evaluate to poison despite having non-poison inputs.
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
The legacy pass manager's analysis pass to compute loop information.
virtual bool runOnLoop(Loop *L, LPPassManager &LPM)=0
Represents a single loop in the control flow graph.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
The main scalar evolution driver.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
LLVM Value Representation.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
PreservedAnalyses getLoopPassPreservedAnalyses()
Returns the minimum set of Analyses that all loop passes must preserve.
Pass * createCanonicalizeFreezeInLoopsPass()
void initializeCanonicalizeFreezeInLoopsPass(PassRegistry &)
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...