Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 026a351

Browse files
committed
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary: After a discussion with Rekka, i believe this (or a small variant) should fix the remaining phi-of-ops problems. Rekka's algorithm for completeness relies on looking up expressions that should have no leader, and expecting it to fail (IE looking up expressions that can't exist in a predecessor, and expecting it to find nothing). Unfortunately, sometimes these expressions can be simplified to constants, but we need the lookup to fail anyway. Additionally, our simplifier outsmarts this by taking these "not quite right" expressions, and simplifying them into other expressions or walking through phis, etc. In the past, we've sometimes been able to find leaders for these expressions, incorrectly. This change causes us to not to try to phi of ops such expressions. We determine safety by seeing if they depend on a phi node in our block. This is not perfect, we can do a bit better, but this should be a "correctness start" that we can then improve. It also requires a bunch of caching that i'll eventually like to eliminate. The right solution, longer term, to the simplifier issues, is to make the query interface for the instruction simplifier/constant folder have the flags we need, so that we can keep most things going, but turn off the possibly-invalid parts (threading through phis, etc). This is an issue in another wrong code bug as well. Reviewers: davide, mcrosier Subscribers: sanjoy, llvm-commits Differential Revision: https://reviews.llvm.org/D37175 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312401 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 5263738 commit 026a351

File tree

6 files changed

+480
-71
lines changed

6 files changed

+480
-71
lines changed

lib/Transforms/Scalar/NewGVN.cpp

Lines changed: 144 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ static cl::opt<bool> EnableStoreRefinement("enable-store-refinement",
128128
cl::init(false), cl::Hidden);
129129

130130
/// Currently, the generation "phi of ops" can result in correctness issues.
131-
static cl::opt<bool> EnablePhiOfOps("enable-phi-of-ops", cl::init(false),
131+
static cl::opt<bool> EnablePhiOfOps("enable-phi-of-ops", cl::init(true),
132132
cl::Hidden);
133133

134134
//===----------------------------------------------------------------------===//
@@ -475,6 +475,7 @@ class NewGVN {
475475
// These mappings just store various data that would normally be part of the
476476
// IR.
477477
DenseSet<const Instruction *> PHINodeUses;
478+
DenseMap<const Value *, bool> OpSafeForPHIOfOps;
478479
// Map a temporary instruction we created to a parent block.
479480
DenseMap<const Value *, BasicBlock *> TempToBlock;
480481
// Map between the already in-program instructions and the temporary phis we
@@ -643,6 +644,14 @@ class NewGVN {
643644
void initializeCongruenceClasses(Function &F);
644645
const Expression *makePossiblePhiOfOps(Instruction *,
645646
SmallPtrSetImpl<Value *> &);
647+
Value *findLeaderForInst(Instruction *ValueOp,
648+
SmallPtrSetImpl<Value *> &Visited,
649+
MemoryAccess *MemAccess, Instruction *OrigInst,
650+
BasicBlock *PredBB);
651+
652+
bool OpIsSafeForPHIOfOps(Value *Op, Instruction *OrigInst,
653+
const BasicBlock *PHIBlock,
654+
SmallPtrSetImpl<const Value *> &);
646655
void addPhiOfOps(PHINode *Op, BasicBlock *BB, Instruction *ExistingValue);
647656
void removePhiOfOps(Instruction *I, PHINode *PHITemp);
648657

@@ -669,6 +678,7 @@ class NewGVN {
669678
// Congruence finding.
670679
bool someEquivalentDominates(const Instruction *, const Instruction *) const;
671680
Value *lookupOperandLeader(Value *) const;
681+
CongruenceClass *getClassForExpression(const Expression *E) const;
672682
void performCongruenceFinding(Instruction *, const Expression *);
673683
void moveValueToNewCongruenceClass(Instruction *, const Expression *,
674684
CongruenceClass *, CongruenceClass *);
@@ -703,8 +713,7 @@ class NewGVN {
703713
void replaceInstruction(Instruction *, Value *);
704714
void markInstructionForDeletion(Instruction *);
705715
void deleteInstructionsInBlock(BasicBlock *);
706-
Value *findPhiOfOpsLeader(const Expression *E, const BasicBlock *BB) const;
707-
716+
Value *findPHIOfOpsLeader(const Expression *E, const BasicBlock *BB) const;
708717
// New instruction creation.
709718
void handleNewInstruction(Instruction *){};
710719

@@ -963,7 +972,9 @@ const Expression *NewGVN::checkSimplificationResults(Expression *E,
963972
CongruenceClass *CC = ValueToClass.lookup(V);
964973
if (CC) {
965974
if (CC->getLeader() && CC->getLeader() != I) {
966-
addAdditionalUsers(V, I);
975+
// Don't add temporary instructions to the user lists.
976+
if (!AllTempInstructions.count(I))
977+
addAdditionalUsers(V, I);
967978
return createVariableOrConstant(CC->getLeader());
968979
}
969980

@@ -988,6 +999,9 @@ const Expression *NewGVN::checkSimplificationResults(Expression *E,
988999
return nullptr;
9891000
}
9901001

1002+
// Create a value expression from the instruction I, replacing operands with
1003+
// their leaders.
1004+
9911005
const Expression *NewGVN::createExpression(Instruction *I) const {
9921006
auto *E = new (ExpressionAllocator) BasicExpression(I->getNumOperands());
9931007

@@ -1002,7 +1016,6 @@ const Expression *NewGVN::createExpression(Instruction *I) const {
10021016
if (shouldSwapOperands(E->getOperand(0), E->getOperand(1)))
10031017
E->swapOperands(0, 1);
10041018
}
1005-
10061019
// Perform simplification.
10071020
if (auto *CI = dyn_cast<CmpInst>(I)) {
10081021
// Sort the operand value numbers so x<y and y>x get the same value
@@ -1389,8 +1402,8 @@ const Expression *NewGVN::performSymbolicLoadEvaluation(Instruction *I) const {
13891402
}
13901403
}
13911404

1392-
const auto *LE = createLoadExpression(LI->getType(), LoadAddressLeader,
1393-
LI, DefiningAccess);
1405+
const auto *LE = createLoadExpression(LI->getType(), LoadAddressLeader, LI,
1406+
DefiningAccess);
13941407
// If our MemoryLeader is not our defining access, add a use to the
13951408
// MemoryLeader, so that we get reprocessed when it changes.
13961409
if (LE->getMemoryLeader() != DefiningAccess)
@@ -2464,6 +2477,92 @@ static bool okayForPHIOfOps(const Instruction *I) {
24642477
isa<LoadInst>(I);
24652478
}
24662479

2480+
// Return true if this operand will be safe to use for phi of ops.
2481+
//
2482+
// The reason some operands are unsafe is that we are not trying to recursively
2483+
// translate everything back through phi nodes. We actually expect some lookups
2484+
// of expressions to fail. In particular, a lookup where the expression cannot
2485+
// exist in the predecessor. This is true even if the expression, as shown, can
2486+
// be determined to be constant.
2487+
bool NewGVN::OpIsSafeForPHIOfOps(Value *V, Instruction *OrigInst,
2488+
const BasicBlock *PHIBlock,
2489+
SmallPtrSetImpl<const Value *> &Visited) {
2490+
if (!isa<Instruction>(V))
2491+
return true;
2492+
auto OISIt = OpSafeForPHIOfOps.find(V);
2493+
if (OISIt != OpSafeForPHIOfOps.end())
2494+
return OISIt->second;
2495+
// Keep walking until we either dominate the phi block, or hit a phi, or run
2496+
// out of things to check.
2497+
if (DT->properlyDominates(getBlockForValue(V), PHIBlock)) {
2498+
OpSafeForPHIOfOps.insert({V, true});
2499+
return true;
2500+
}
2501+
// PHI in the same block.
2502+
if (isa<PHINode>(V) && getBlockForValue(V) == PHIBlock) {
2503+
OpSafeForPHIOfOps.insert({V, false});
2504+
return false;
2505+
}
2506+
for (auto Op : cast<Instruction>(V)->operand_values()) {
2507+
if (!isa<Instruction>(Op))
2508+
continue;
2509+
// See if we already know the answer for this node.
2510+
auto OISIt = OpSafeForPHIOfOps.find(Op);
2511+
if (OISIt != OpSafeForPHIOfOps.end()) {
2512+
if (!OISIt->second) {
2513+
OpSafeForPHIOfOps.insert({V, false});
2514+
return false;
2515+
}
2516+
}
2517+
if (!Visited.insert(Op).second)
2518+
continue;
2519+
if (!OpIsSafeForPHIOfOps(Op, OrigInst, PHIBlock, Visited)) {
2520+
OpSafeForPHIOfOps.insert({V, false});
2521+
return false;
2522+
}
2523+
}
2524+
OpSafeForPHIOfOps.insert({V, true});
2525+
return true;
2526+
}
2527+
2528+
// Try to find a leader for instruction TransInst, which is a phi translated
2529+
// version of something in our original program. Visited is used to ensure we
2530+
// don't infinite loop during translations of cycles. OrigInst is the
2531+
// instruction in the original program, and PredBB is the predecessor we
2532+
// translated it through.
2533+
Value *NewGVN::findLeaderForInst(Instruction *TransInst,
2534+
SmallPtrSetImpl<Value *> &Visited,
2535+
MemoryAccess *MemAccess, Instruction *OrigInst,
2536+
BasicBlock *PredBB) {
2537+
unsigned IDFSNum = InstrToDFSNum(OrigInst);
2538+
// Make sure it's marked as a temporary instruction.
2539+
AllTempInstructions.insert(TransInst);
2540+
// and make sure anything that tries to add it's DFS number is
2541+
// redirected to the instruction we are making a phi of ops
2542+
// for.
2543+
TempToBlock.insert({TransInst, PredBB});
2544+
InstrDFS.insert({TransInst, IDFSNum});
2545+
2546+
const Expression *E = performSymbolicEvaluation(TransInst, Visited);
2547+
InstrDFS.erase(TransInst);
2548+
AllTempInstructions.erase(TransInst);
2549+
TempToBlock.erase(TransInst);
2550+
if (MemAccess)
2551+
TempToMemory.erase(TransInst);
2552+
if (!E)
2553+
return nullptr;
2554+
auto *FoundVal = findPHIOfOpsLeader(E, PredBB);
2555+
if (!FoundVal || FoundVal == OrigInst) {
2556+
ExpressionToPhiOfOps[E].insert(OrigInst);
2557+
DEBUG(dbgs() << "Cannot find phi of ops operand for " << *TransInst
2558+
<< " in block " << getBlockName(PredBB) << "\n");
2559+
return nullptr;
2560+
}
2561+
if (auto *SI = dyn_cast<StoreInst>(FoundVal))
2562+
FoundVal = SI->getValueOperand();
2563+
return FoundVal;
2564+
}
2565+
24672566
// When we see an instruction that is an op of phis, generate the equivalent phi
24682567
// of ops form.
24692568
const Expression *
@@ -2481,7 +2580,6 @@ NewGVN::makePossiblePhiOfOps(Instruction *I,
24812580
if (!isCycleFree(I))
24822581
return nullptr;
24832582

2484-
unsigned IDFSNum = InstrToDFSNum(I);
24852583
SmallPtrSet<const Value *, 8> ProcessedPHIs;
24862584
// TODO: We don't do phi translation on memory accesses because it's
24872585
// complicated. For a load, we'd need to be able to simulate a new memoryuse,
@@ -2494,18 +2592,9 @@ NewGVN::makePossiblePhiOfOps(Instruction *I,
24942592
MemAccess->getDefiningAccess()->getBlock() == I->getParent())
24952593
return nullptr;
24962594

2595+
SmallPtrSet<const Value *, 10> VisitedOps;
24972596
// Convert op of phis to phi of ops
24982597
for (auto &Op : I->operands()) {
2499-
// TODO: We can't handle expressions that must be recursively translated
2500-
// IE
2501-
// a = phi (b, c)
2502-
// f = use a
2503-
// g = f + phi of something
2504-
// To properly make a phi of ops for g, we'd have to properly translate and
2505-
// use the instruction for f. We should add this by splitting out the
2506-
// instruction creation we do below.
2507-
if (isa<Instruction>(Op) && PHINodeUses.count(cast<Instruction>(Op)))
2508-
return nullptr;
25092598
if (!isa<PHINode>(Op))
25102599
continue;
25112600
auto *OpPHI = cast<PHINode>(Op);
@@ -2526,36 +2615,30 @@ NewGVN::makePossiblePhiOfOps(Instruction *I,
25262615
Instruction *ValueOp = I->clone();
25272616
if (MemAccess)
25282617
TempToMemory.insert({ValueOp, MemAccess});
2529-
2618+
bool SafeForPHIOfOps = true;
2619+
VisitedOps.clear();
25302620
for (auto &Op : ValueOp->operands()) {
2621+
auto *OrigOp = &*Op;
25312622
Op = Op->DoPHITranslation(PHIBlock, PredBB);
25322623
// When this operand changes, it could change whether there is a
25332624
// leader for us or not.
25342625
addAdditionalUsers(Op, I);
2626+
// If we phi-translated the op, it must be safe.
2627+
SafeForPHIOfOps = SafeForPHIOfOps &&
2628+
(Op != OrigOp ||
2629+
OpIsSafeForPHIOfOps(Op, I, PHIBlock, VisitedOps));
25352630
}
2536-
// Make sure it's marked as a temporary instruction.
2537-
AllTempInstructions.insert(ValueOp);
2538-
// and make sure anything that tries to add it's DFS number is
2539-
// redirected to the instruction we are making a phi of ops
2540-
// for.
2541-
TempToBlock.insert({ValueOp, PredBB});
2542-
InstrDFS.insert({ValueOp, IDFSNum});
2543-
const Expression *E = performSymbolicEvaluation(ValueOp, Visited);
2544-
InstrDFS.erase(ValueOp);
2545-
AllTempInstructions.erase(ValueOp);
2631+
// FIXME: For those things that are not safe We could generate
2632+
// expressions all the way down, and see if this comes out to a
2633+
// constant. For anything where that is true, and unsafe, we should
2634+
// have made a phi-of-ops (or value numbered it equivalent to something)
2635+
// for the pieces already.
2636+
FoundVal = !SafeForPHIOfOps ? nullptr
2637+
: findLeaderForInst(ValueOp, Visited,
2638+
MemAccess, I, PredBB);
25462639
ValueOp->deleteValue();
2547-
TempToBlock.erase(ValueOp);
2548-
if (MemAccess)
2549-
TempToMemory.erase(ValueOp);
2550-
if (!E)
2551-
return nullptr;
2552-
FoundVal = findPhiOfOpsLeader(E, PredBB);
2553-
if (!FoundVal) {
2554-
ExpressionToPhiOfOps[E].insert(I);
2640+
if (!FoundVal)
25552641
return nullptr;
2556-
}
2557-
if (auto *SI = dyn_cast<StoreInst>(FoundVal))
2558-
FoundVal = SI->getValueOperand();
25592642
} else {
25602643
DEBUG(dbgs() << "Skipping phi of ops operand for incoming block "
25612644
<< getBlockName(PredBB)
@@ -2570,7 +2653,8 @@ NewGVN::makePossiblePhiOfOps(Instruction *I,
25702653
auto *ValuePHI = RealToTemp.lookup(I);
25712654
bool NewPHI = false;
25722655
if (!ValuePHI) {
2573-
ValuePHI = PHINode::Create(I->getType(), OpPHI->getNumOperands());
2656+
ValuePHI =
2657+
PHINode::Create(I->getType(), OpPHI->getNumOperands(), "phiofops");
25742658
addPhiOfOps(ValuePHI, PHIBlock, I);
25752659
NewPHI = true;
25762660
NumGVNPHIOfOpsCreated++;
@@ -2695,6 +2779,8 @@ void NewGVN::cleanupTables() {
26952779
TempToBlock.clear();
26962780
TempToMemory.clear();
26972781
PHIOfOpsPHIs.clear();
2782+
PHINodeUses.clear();
2783+
OpSafeForPHIOfOps.clear();
26982784
ReachableBlocks.clear();
26992785
ReachableEdges.clear();
27002786
#ifndef NDEBUG
@@ -3524,17 +3610,29 @@ class ValueDFSStack {
35243610
};
35253611
}
35263612

3613+
// Given an expression, get the congruence class for it.
3614+
CongruenceClass *NewGVN::getClassForExpression(const Expression *E) const {
3615+
if (auto *VE = dyn_cast<VariableExpression>(E))
3616+
return ValueToClass.lookup(VE->getVariableValue());
3617+
else if (isa<DeadExpression>(E))
3618+
return TOPClass;
3619+
return ExpressionToClass.lookup(E);
3620+
}
3621+
35273622
// Given a value and a basic block we are trying to see if it is available in,
35283623
// see if the value has a leader available in that block.
3529-
Value *NewGVN::findPhiOfOpsLeader(const Expression *E,
3624+
Value *NewGVN::findPHIOfOpsLeader(const Expression *E,
35303625
const BasicBlock *BB) const {
35313626
// It would already be constant if we could make it constant
35323627
if (auto *CE = dyn_cast<ConstantExpression>(E))
35333628
return CE->getConstantValue();
3534-
if (auto *VE = dyn_cast<VariableExpression>(E))
3535-
return VE->getVariableValue();
3629+
if (auto *VE = dyn_cast<VariableExpression>(E)) {
3630+
auto *V = VE->getVariableValue();
3631+
if (alwaysAvailable(V) || DT->dominates(getBlockForValue(V), BB))
3632+
return VE->getVariableValue();
3633+
}
35363634

3537-
auto *CC = ExpressionToClass.lookup(E);
3635+
auto *CC = getClassForExpression(E);
35383636
if (!CC)
35393637
return nullptr;
35403638
if (alwaysAvailable(CC->getLeader()))
@@ -3545,12 +3643,8 @@ Value *NewGVN::findPhiOfOpsLeader(const Expression *E,
35453643
// Anything that isn't an instruction is always available.
35463644
if (!MemberInst)
35473645
return Member;
3548-
// If we are looking for something in the same block as the member, it must
3549-
// be a leader because this function is looking for operands for a phi node.
3550-
if (MemberInst->getParent() == BB ||
3551-
DT->dominates(MemberInst->getParent(), BB)) {
3646+
if (DT->dominates(getBlockForValue(MemberInst), BB))
35523647
return Member;
3553-
}
35543648
}
35553649
return nullptr;
35563650
}

0 commit comments

Comments
 (0)