Go to the documentation of this file.
48 #define DEBUG_TYPE "canon-freeze"
52 class CanonicalizeFreezeInLoops :
public LoopPass {
56 CanonicalizeFreezeInLoops();
63 class CanonicalizeFreezeInLoopsImpl {
68 struct FrozenIndPHIInfo {
75 unsigned StepValIdx = 0;
78 :
PHI(
PHI), StepInst(StepInst) {}
85 auto Opc =
I->getOpcode();
91 void InsertFreezeAndForgetFromSCEV(
Use &U);
95 : L(L), SE(SE), DT(DT) {}
103 void 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);
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)) {
157 Candidates.push_back(
Info);
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();
202 CanonicalizeFreezeInLoops::CanonicalizeFreezeInLoops() :
LoopPass(
ID) {
206 void 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();
A set of analyses that are preserved following a run of a transformation pass.
This is an optimization pass for GlobalISel generic memory operations.
Represents a single loop in the control flow graph.
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.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The main scalar evolution driver.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
The legacy pass manager's analysis pass to compute loop information.
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const Use & getOperandUse(unsigned i) const
A struct for saving information about induction variables.
Represent the analysis usage information of a pass.
The object format emitted by the WebAssembly backed is documented in
INITIALIZE_PASS_BEGIN(CanonicalizeFreezeInLoops, "canon-freeze", "Canonicalize Freeze Instructions in Loops", false, false) INITIALIZE_PASS_END(CanonicalizeFreezeInLoops
Legacy analysis pass which computes a DominatorTree.
User * getUser() const
Returns the User that contains this Use.
Analysis containing CSE Info
void initializeCanonicalizeFreezeInLoopsPass(PassRegistry &)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
Pass * createCanonicalizeFreezeInLoopsPass()
PreservedAnalyses getLoopPassPreservedAnalyses()
Returns the minimum set of Analyses that all loop passes must preserve.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
canon Canonicalize Freeze Instructions in Loops
AnalysisUsage & addPreservedID(const void *ID)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
DominatorTree & getDomTree()
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Pass interface - Implemented by all 'passes'.
This class represents a freeze function that returns random concrete value if an operand is either a ...
A container for analyses that lazily runs them and caches their results.
AnalysisUsage & addRequiredID(const void *ID)
AnalysisUsage & addRequired()
LLVM Value Representation.
void dropPoisonGeneratingFlags()
Drops flags that may cause this instruction to evaluate to poison despite having non-poison inputs.
A Use represents the edge between a Value definition and its users.