forked from OSchip/llvm-project
NewGVN: Factor out duplicate parts of OpIsSafeForPHIOfOps
llvm-svn: 315040
This commit is contained in:
parent
505260449e
commit
08dd582ea0
|
@ -640,9 +640,10 @@ private:
|
||||||
SmallPtrSetImpl<Value *> &Visited,
|
SmallPtrSetImpl<Value *> &Visited,
|
||||||
MemoryAccess *MemAccess, Instruction *OrigInst,
|
MemoryAccess *MemAccess, Instruction *OrigInst,
|
||||||
BasicBlock *PredBB);
|
BasicBlock *PredBB);
|
||||||
|
bool OpIsSafeForPHIOfOpsHelper(Value *V, const BasicBlock *PHIBlock,
|
||||||
bool OpIsSafeForPHIOfOps(Value *Op, Instruction *OrigInst,
|
SmallPtrSetImpl<const Value *> &Visited,
|
||||||
const BasicBlock *PHIBlock,
|
SmallVectorImpl<Instruction *> &Worklist);
|
||||||
|
bool OpIsSafeForPHIOfOps(Value *Op, const BasicBlock *PHIBlock,
|
||||||
SmallPtrSetImpl<const Value *> &);
|
SmallPtrSetImpl<const Value *> &);
|
||||||
void addPhiOfOps(PHINode *Op, BasicBlock *BB, Instruction *ExistingValue);
|
void addPhiOfOps(PHINode *Op, BasicBlock *BB, Instruction *ExistingValue);
|
||||||
void removePhiOfOps(Instruction *I, PHINode *PHITemp);
|
void removePhiOfOps(Instruction *I, PHINode *PHITemp);
|
||||||
|
@ -2505,22 +2506,19 @@ static bool okayForPHIOfOps(const Instruction *I) {
|
||||||
isa<LoadInst>(I);
|
isa<LoadInst>(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if this operand will be safe to use for phi of ops.
|
bool NewGVN::OpIsSafeForPHIOfOpsHelper(
|
||||||
//
|
Value *V, const BasicBlock *PHIBlock,
|
||||||
// The reason some operands are unsafe is that we are not trying to recursively
|
SmallPtrSetImpl<const Value *> &Visited,
|
||||||
// translate everything back through phi nodes. We actually expect some lookups
|
SmallVectorImpl<Instruction *> &Worklist) {
|
||||||
// of expressions to fail. In particular, a lookup where the expression cannot
|
|
||||||
// exist in the predecessor. This is true even if the expression, as shown, can
|
|
||||||
// be determined to be constant.
|
|
||||||
bool NewGVN::OpIsSafeForPHIOfOps(Value *V, Instruction *OrigInst,
|
|
||||||
const BasicBlock *PHIBlock,
|
|
||||||
SmallPtrSetImpl<const Value *> &Visited) {
|
|
||||||
if (!isa<Instruction>(V))
|
if (!isa<Instruction>(V))
|
||||||
return true;
|
return true;
|
||||||
auto OISIt = OpSafeForPHIOfOps.find(V);
|
auto OISIt = OpSafeForPHIOfOps.find(V);
|
||||||
if (OISIt != OpSafeForPHIOfOps.end())
|
if (OISIt != OpSafeForPHIOfOps.end())
|
||||||
return OISIt->second;
|
return OISIt->second;
|
||||||
|
|
||||||
|
// Keep walking until we either dominate the phi block, or hit a phi, or run
|
||||||
|
// out of things to check.
|
||||||
if (DT->properlyDominates(getBlockForValue(V), PHIBlock)) {
|
if (DT->properlyDominates(getBlockForValue(V), PHIBlock)) {
|
||||||
OpSafeForPHIOfOps.insert({V, true});
|
OpSafeForPHIOfOps.insert({V, true});
|
||||||
return true;
|
return true;
|
||||||
|
@ -2531,7 +2529,6 @@ bool NewGVN::OpIsSafeForPHIOfOps(Value *V, Instruction *OrigInst,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SmallVector<Instruction *, 4> Worklist;
|
|
||||||
auto *OrigI = cast<Instruction>(V);
|
auto *OrigI = cast<Instruction>(V);
|
||||||
for (auto *Op : OrigI->operand_values()) {
|
for (auto *Op : OrigI->operand_values()) {
|
||||||
if (!isa<Instruction>(Op))
|
if (!isa<Instruction>(Op))
|
||||||
|
@ -2545,40 +2542,29 @@ bool NewGVN::OpIsSafeForPHIOfOps(Value *V, Instruction *OrigInst,
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!Visited.insert(Op).second)
|
||||||
|
continue;
|
||||||
Worklist.push_back(cast<Instruction>(Op));
|
Worklist.push_back(cast<Instruction>(Op));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if this operand will be safe to use for phi of ops.
|
||||||
|
//
|
||||||
|
// The reason some operands are unsafe is that we are not trying to recursively
|
||||||
|
// translate everything back through phi nodes. We actually expect some lookups
|
||||||
|
// of expressions to fail. In particular, a lookup where the expression cannot
|
||||||
|
// exist in the predecessor. This is true even if the expression, as shown, can
|
||||||
|
// be determined to be constant.
|
||||||
|
bool NewGVN::OpIsSafeForPHIOfOps(Value *V, const BasicBlock *PHIBlock,
|
||||||
|
SmallPtrSetImpl<const Value *> &Visited) {
|
||||||
|
SmallVector<Instruction *, 4> Worklist;
|
||||||
|
if (!OpIsSafeForPHIOfOpsHelper(V, PHIBlock, Visited, Worklist))
|
||||||
|
return false;
|
||||||
while (!Worklist.empty()) {
|
while (!Worklist.empty()) {
|
||||||
auto *I = Worklist.pop_back_val();
|
auto *I = Worklist.pop_back_val();
|
||||||
// Keep walking until we either dominate the phi block, or hit a phi, or run
|
if (!OpIsSafeForPHIOfOpsHelper(I, PHIBlock, Visited, Worklist))
|
||||||
// out of things to check.
|
|
||||||
//
|
|
||||||
if (DT->properlyDominates(getBlockForValue(I), PHIBlock)) {
|
|
||||||
OpSafeForPHIOfOps.insert({I, true});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// PHI in the same block.
|
|
||||||
if (isa<PHINode>(I) && getBlockForValue(I) == PHIBlock) {
|
|
||||||
OpSafeForPHIOfOps.insert({I, false});
|
|
||||||
OpSafeForPHIOfOps.insert({V, false});
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
for (auto *Op : cast<Instruction>(I)->operand_values()) {
|
|
||||||
if (!isa<Instruction>(Op))
|
|
||||||
continue;
|
|
||||||
// See if we already know the answer for this node.
|
|
||||||
auto OISIt = OpSafeForPHIOfOps.find(Op);
|
|
||||||
if (OISIt != OpSafeForPHIOfOps.end()) {
|
|
||||||
if (!OISIt->second) {
|
|
||||||
OpSafeForPHIOfOps.insert({V, false});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!Visited.insert(Op).second)
|
|
||||||
continue;
|
|
||||||
Worklist.push_back(cast<Instruction>(Op));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
OpSafeForPHIOfOps.insert({V, true});
|
OpSafeForPHIOfOps.insert({V, true});
|
||||||
return true;
|
return true;
|
||||||
|
@ -2697,9 +2683,9 @@ NewGVN::makePossiblePHIOfOps(Instruction *I,
|
||||||
Op = ValuePHI->getIncomingValue(PredNum);
|
Op = ValuePHI->getIncomingValue(PredNum);
|
||||||
}
|
}
|
||||||
// If we phi-translated the op, it must be safe.
|
// If we phi-translated the op, it must be safe.
|
||||||
SafeForPHIOfOps = SafeForPHIOfOps &&
|
SafeForPHIOfOps =
|
||||||
(Op != OrigOp ||
|
SafeForPHIOfOps &&
|
||||||
OpIsSafeForPHIOfOps(Op, I, PHIBlock, VisitedOps));
|
(Op != OrigOp || OpIsSafeForPHIOfOps(Op, PHIBlock, VisitedOps));
|
||||||
}
|
}
|
||||||
// FIXME: For those things that are not safe we could generate
|
// FIXME: For those things that are not safe we could generate
|
||||||
// expressions all the way down, and see if this comes out to a
|
// expressions all the way down, and see if this comes out to a
|
||||||
|
|
Loading…
Reference in New Issue