@@ -128,7 +128,7 @@ static cl::opt<bool> EnableStoreRefinement("enable-store-refinement",
128
128
cl::init (false ), cl::Hidden);
129
129
130
130
// / 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 ),
132
132
cl::Hidden);
133
133
134
134
// ===----------------------------------------------------------------------===//
@@ -475,6 +475,7 @@ class NewGVN {
475
475
// These mappings just store various data that would normally be part of the
476
476
// IR.
477
477
DenseSet<const Instruction *> PHINodeUses;
478
+ DenseMap<const Value *, bool > OpSafeForPHIOfOps;
478
479
// Map a temporary instruction we created to a parent block.
479
480
DenseMap<const Value *, BasicBlock *> TempToBlock;
480
481
// Map between the already in-program instructions and the temporary phis we
@@ -643,6 +644,14 @@ class NewGVN {
643
644
void initializeCongruenceClasses (Function &F);
644
645
const Expression *makePossiblePhiOfOps (Instruction *,
645
646
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 *> &);
646
655
void addPhiOfOps (PHINode *Op, BasicBlock *BB, Instruction *ExistingValue);
647
656
void removePhiOfOps (Instruction *I, PHINode *PHITemp);
648
657
@@ -669,6 +678,7 @@ class NewGVN {
669
678
// Congruence finding.
670
679
bool someEquivalentDominates (const Instruction *, const Instruction *) const ;
671
680
Value *lookupOperandLeader (Value *) const ;
681
+ CongruenceClass *getClassForExpression (const Expression *E) const ;
672
682
void performCongruenceFinding (Instruction *, const Expression *);
673
683
void moveValueToNewCongruenceClass (Instruction *, const Expression *,
674
684
CongruenceClass *, CongruenceClass *);
@@ -703,8 +713,7 @@ class NewGVN {
703
713
void replaceInstruction (Instruction *, Value *);
704
714
void markInstructionForDeletion (Instruction *);
705
715
void deleteInstructionsInBlock (BasicBlock *);
706
- Value *findPhiOfOpsLeader (const Expression *E, const BasicBlock *BB) const ;
707
-
716
+ Value *findPHIOfOpsLeader (const Expression *E, const BasicBlock *BB) const ;
708
717
// New instruction creation.
709
718
void handleNewInstruction (Instruction *){};
710
719
@@ -963,7 +972,9 @@ const Expression *NewGVN::checkSimplificationResults(Expression *E,
963
972
CongruenceClass *CC = ValueToClass.lookup (V);
964
973
if (CC) {
965
974
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);
967
978
return createVariableOrConstant (CC->getLeader ());
968
979
}
969
980
@@ -988,6 +999,9 @@ const Expression *NewGVN::checkSimplificationResults(Expression *E,
988
999
return nullptr ;
989
1000
}
990
1001
1002
+ // Create a value expression from the instruction I, replacing operands with
1003
+ // their leaders.
1004
+
991
1005
const Expression *NewGVN::createExpression (Instruction *I) const {
992
1006
auto *E = new (ExpressionAllocator) BasicExpression (I->getNumOperands ());
993
1007
@@ -1002,7 +1016,6 @@ const Expression *NewGVN::createExpression(Instruction *I) const {
1002
1016
if (shouldSwapOperands (E->getOperand (0 ), E->getOperand (1 )))
1003
1017
E->swapOperands (0 , 1 );
1004
1018
}
1005
-
1006
1019
// Perform simplification.
1007
1020
if (auto *CI = dyn_cast<CmpInst>(I)) {
1008
1021
// 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 {
1389
1402
}
1390
1403
}
1391
1404
1392
- const auto *LE = createLoadExpression (LI->getType (), LoadAddressLeader,
1393
- LI, DefiningAccess);
1405
+ const auto *LE = createLoadExpression (LI->getType (), LoadAddressLeader, LI,
1406
+ DefiningAccess);
1394
1407
// If our MemoryLeader is not our defining access, add a use to the
1395
1408
// MemoryLeader, so that we get reprocessed when it changes.
1396
1409
if (LE->getMemoryLeader () != DefiningAccess)
@@ -2464,6 +2477,92 @@ static bool okayForPHIOfOps(const Instruction *I) {
2464
2477
isa<LoadInst>(I);
2465
2478
}
2466
2479
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
+
2467
2566
// When we see an instruction that is an op of phis, generate the equivalent phi
2468
2567
// of ops form.
2469
2568
const Expression *
@@ -2481,7 +2580,6 @@ NewGVN::makePossiblePhiOfOps(Instruction *I,
2481
2580
if (!isCycleFree (I))
2482
2581
return nullptr ;
2483
2582
2484
- unsigned IDFSNum = InstrToDFSNum (I);
2485
2583
SmallPtrSet<const Value *, 8 > ProcessedPHIs;
2486
2584
// TODO: We don't do phi translation on memory accesses because it's
2487
2585
// complicated. For a load, we'd need to be able to simulate a new memoryuse,
@@ -2494,18 +2592,9 @@ NewGVN::makePossiblePhiOfOps(Instruction *I,
2494
2592
MemAccess->getDefiningAccess ()->getBlock () == I->getParent ())
2495
2593
return nullptr ;
2496
2594
2595
+ SmallPtrSet<const Value *, 10 > VisitedOps;
2497
2596
// Convert op of phis to phi of ops
2498
2597
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 ;
2509
2598
if (!isa<PHINode>(Op))
2510
2599
continue ;
2511
2600
auto *OpPHI = cast<PHINode>(Op);
@@ -2526,36 +2615,30 @@ NewGVN::makePossiblePhiOfOps(Instruction *I,
2526
2615
Instruction *ValueOp = I->clone ();
2527
2616
if (MemAccess)
2528
2617
TempToMemory.insert ({ValueOp, MemAccess});
2529
-
2618
+ bool SafeForPHIOfOps = true ;
2619
+ VisitedOps.clear ();
2530
2620
for (auto &Op : ValueOp->operands ()) {
2621
+ auto *OrigOp = &*Op;
2531
2622
Op = Op->DoPHITranslation (PHIBlock, PredBB);
2532
2623
// When this operand changes, it could change whether there is a
2533
2624
// leader for us or not.
2534
2625
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));
2535
2630
}
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);
2546
2639
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)
2555
2641
return nullptr ;
2556
- }
2557
- if (auto *SI = dyn_cast<StoreInst>(FoundVal))
2558
- FoundVal = SI->getValueOperand ();
2559
2642
} else {
2560
2643
DEBUG (dbgs () << " Skipping phi of ops operand for incoming block "
2561
2644
<< getBlockName (PredBB)
@@ -2570,7 +2653,8 @@ NewGVN::makePossiblePhiOfOps(Instruction *I,
2570
2653
auto *ValuePHI = RealToTemp.lookup (I);
2571
2654
bool NewPHI = false ;
2572
2655
if (!ValuePHI) {
2573
- ValuePHI = PHINode::Create (I->getType (), OpPHI->getNumOperands ());
2656
+ ValuePHI =
2657
+ PHINode::Create (I->getType (), OpPHI->getNumOperands (), " phiofops" );
2574
2658
addPhiOfOps (ValuePHI, PHIBlock, I);
2575
2659
NewPHI = true ;
2576
2660
NumGVNPHIOfOpsCreated++;
@@ -2695,6 +2779,8 @@ void NewGVN::cleanupTables() {
2695
2779
TempToBlock.clear ();
2696
2780
TempToMemory.clear ();
2697
2781
PHIOfOpsPHIs.clear ();
2782
+ PHINodeUses.clear ();
2783
+ OpSafeForPHIOfOps.clear ();
2698
2784
ReachableBlocks.clear ();
2699
2785
ReachableEdges.clear ();
2700
2786
#ifndef NDEBUG
@@ -3524,17 +3610,29 @@ class ValueDFSStack {
3524
3610
};
3525
3611
}
3526
3612
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
+
3527
3622
// Given a value and a basic block we are trying to see if it is available in,
3528
3623
// 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,
3530
3625
const BasicBlock *BB) const {
3531
3626
// It would already be constant if we could make it constant
3532
3627
if (auto *CE = dyn_cast<ConstantExpression>(E))
3533
3628
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
+ }
3536
3634
3537
- auto *CC = ExpressionToClass. lookup (E);
3635
+ auto *CC = getClassForExpression (E);
3538
3636
if (!CC)
3539
3637
return nullptr ;
3540
3638
if (alwaysAvailable (CC->getLeader ()))
@@ -3545,12 +3643,8 @@ Value *NewGVN::findPhiOfOpsLeader(const Expression *E,
3545
3643
// Anything that isn't an instruction is always available.
3546
3644
if (!MemberInst)
3547
3645
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))
3552
3647
return Member;
3553
- }
3554
3648
}
3555
3649
return nullptr ;
3556
3650
}
0 commit comments