50#define DEBUG_TYPE "canon-freeze"
54class CanonicalizeFreezeInLoops :
public LoopPass {
58 CanonicalizeFreezeInLoops();
65class CanonicalizeFreezeInLoopsImpl {
74 auto Opc =
I->getOpcode();
76 return Opc == Instruction::Add || Opc == Instruction::Sub ||
77 Opc == Instruction::Mul;
80 void InsertFreezeAndForgetFromSCEV(
Use &U);
84 : L(L), SE(SE), DT(DT) {}
132void CanonicalizeFreezeInLoopsImpl::InsertFreezeAndForgetFromSCEV(
Use &U) {
133 auto *PH =
L->getLoopPreheader();
135 auto *UserI = cast<Instruction>(
U.getUser());
136 auto *ValueToFr =
U.get();
137 assert(
L->contains(UserI->getParent()) &&
138 "Should not process an instruction that isn't inside the loop");
146 U.set(
new FreezeInst(ValueToFr, ValueToFr->getName() +
".frozen",
147 PH->getTerminator()->getIterator()));
149 SE.forgetValue(UserI);
152bool CanonicalizeFreezeInLoopsImpl::run() {
154 if (!
L->isLoopSimplifyForm())
159 for (
auto &
PHI :
L->getHeader()->phis()) {
166 if (!
Info.StepInst || !canHandleInst(
Info.StepInst)) {
172 Info.StepValIdx =
Info.StepInst->getOperand(0) == &
PHI;
174 if (
auto *StepI = dyn_cast<Instruction>(StepV)) {
175 if (
L->contains(StepI->getParent())) {
182 auto Visit = [&](
User *
U) {
183 if (
auto *FI = dyn_cast<FreezeInst>(U)) {
193 if (Candidates.
empty())
197 for (
const auto &Info : Candidates) {
203 assert(StepI &&
"Step instruction should have been found");
209 SE.forgetValue(StepI);
214 unsigned OperandIdx =
215 PHI->getOperandNumForIncomingValue(
PHI->getIncomingValue(0) == StepI);
216 InsertFreezeAndForgetFromSCEV(
PHI->getOperandUse(OperandIdx));
220 for (
const auto &Item : Candidates) {
224 FI->replaceAllUsesWith(FI->getOperand(0));
225 FI->eraseFromParent();
231CanonicalizeFreezeInLoops::CanonicalizeFreezeInLoops() :
LoopPass(
ID) {
235void CanonicalizeFreezeInLoops::getAnalysisUsage(
AnalysisUsage &AU)
const {
250 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
251 auto &DT = getAnalysis<DominatorTreeWrapperPass>().
getDomTree();
252 return CanonicalizeFreezeInLoopsImpl(L, SE, DT).run();
259 if (!CanonicalizeFreezeInLoopsImpl(&L, AR.
SE, AR.
DT).run())
266 "Canonicalize Freeze Instructions in Loops",
false,
false)
274 return new CanonicalizeFreezeInLoops();
277char CanonicalizeFreezeInLoops::ID = 0;
Analysis containing CSE Info
This file defines DenseMapInfo traits for DenseMap.
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 implements a set that has insertion order iteration characteristics.
This file defines the SmallSet 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.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
A SetVector that performs no allocations if smaller than a certain size.
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.
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 &)
static FrozenIndPHIInfo getEmptyKey()
static FrozenIndPHIInfo getTombstoneKey()
static unsigned getHashValue(const FrozenIndPHIInfo &Val)
static bool isEqual(const FrozenIndPHIInfo &LHS, const FrozenIndPHIInfo &RHS)
An information struct used to provide DenseMap with the various necessary components for a given valu...
FrozenIndPHIInfo(PHINode *PHI, BinaryOperator *StepInst)
bool operator==(const FrozenIndPHIInfo &Other)
BinaryOperator * StepInst
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...