48#define DEBUG_TYPE "canon-freeze"
52class CanonicalizeFreezeInLoops :
public LoopPass {
56 CanonicalizeFreezeInLoops();
63class CanonicalizeFreezeInLoopsImpl {
68 struct FrozenIndPHIInfo {
75 unsigned StepValIdx = 0;
78 :
PHI(
PHI), StepInst(StepInst) {}
85 auto Opc =
I->getOpcode();
87 return Opc == Instruction::Add || Opc == Instruction::Sub ||
88 Opc == Instruction::Mul;
91 void InsertFreezeAndForgetFromSCEV(
Use &U);
95 : L(L), SE(SE), DT(DT) {}
103void CanonicalizeFreezeInLoopsImpl::InsertFreezeAndForgetFromSCEV(
Use &U) {
104 auto *PH =
L->getLoopPreheader();
106 auto *UserI = cast<Instruction>(
U.getUser());
107 auto *ValueToFr =
U.get();
108 assert(
L->contains(UserI->getParent()) &&
109 "Should not process an instruction that isn't inside the loop");
117 U.set(
new FreezeInst(ValueToFr, ValueToFr->getName() +
".frozen",
118 PH->getTerminator()));
120 SE.forgetValue(UserI);
123bool CanonicalizeFreezeInLoopsImpl::run() {
125 if (!
L->isLoopSimplifyForm())
130 for (
auto &
PHI :
L->getHeader()->phis()) {
136 FrozenIndPHIInfo
Info(&
PHI,
ID.getInductionBinOp());
137 if (!
Info.StepInst || !canHandleInst(
Info.StepInst)) {
143 Info.StepValIdx =
Info.StepInst->getOperand(0) == &
PHI;
145 if (
auto *StepI = dyn_cast<Instruction>(StepV)) {
146 if (
L->contains(StepI->getParent())) {
153 auto Visit = [&](
User *
U) {
154 if (
auto *FI = dyn_cast<FreezeInst>(U)) {
164 if (Candidates.
empty())
168 for (
const auto &Info : Candidates) {
174 assert(StepI &&
"Step instruction should have been found");
180 SE.forgetValue(StepI);
185 unsigned OperandIdx =
186 PHI->getOperandNumForIncomingValue(
PHI->getIncomingValue(0) == StepI);
187 InsertFreezeAndForgetFromSCEV(
PHI->getOperandUse(OperandIdx));
191 for (
const auto &Item : Candidates) {
195 FI->replaceAllUsesWith(FI->getOperand(0));
196 FI->eraseFromParent();
202CanonicalizeFreezeInLoops::CanonicalizeFreezeInLoops() :
LoopPass(
ID) {
206void CanonicalizeFreezeInLoops::getAnalysisUsage(
AnalysisUsage &AU)
const {
221 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
222 auto &DT = getAnalysis<DominatorTreeWrapperPass>().
getDomTree();
223 return CanonicalizeFreezeInLoopsImpl(L, SE, DT).run();
230 if (!CanonicalizeFreezeInLoopsImpl(&L, AR.
SE, AR.
DT).run())
237 "Canonicalize Freeze Instructions in Loops",
false,
false)
245 return new CanonicalizeFreezeInLoops();
248char 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 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...