llvm.org GIT mirror llvm / 73d8c2e
[NewGVN] Split OpPHI detection and creation. It also adds a check making sure PHIs for operands are all in the same block. Patch by Daniel Berlin <dberlin@dberlin.org> Reviewers: dberlin, davide Differential Revision: https://reviews.llvm.org/D43865 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@330444 91177308-0d34-0410-b5e6-96231b3b80d8 Florian Hahn 1 year, 6 months ago
2 changed file(s) with 170 addition(s) and 105 deletion(s). Raw diff Collapse all Expand all
27232723 MemAccess->getDefiningAccess()->getBlock() == I->getParent())
27242724 return nullptr;
27252725
2726 // Convert op of phis to phi of ops
27262727 SmallPtrSet VisitedOps;
2727 // Convert op of phis to phi of ops
2728 for (auto *Op : I->operand_values()) {
2728 SmallVector Ops(I->operand_values());
2729 BasicBlock *SamePHIBlock = nullptr;
2730 PHINode *OpPHI = nullptr;
2731 if (!DebugCounter::shouldExecute(PHIOfOpsCounter))
2732 return nullptr;
2733 for (auto *Op : Ops) {
27292734 if (!isa(Op)) {
27302735 auto *ValuePHI = RealToTemp.lookup(Op);
27312736 if (!ValuePHI)
27332738 DEBUG(dbgs() << "Found possible dependent phi of ops\n");
27342739 Op = ValuePHI;
27352740 }
2736 auto *OpPHI = cast(Op);
2741 OpPHI = cast(Op);
2742 if (!SamePHIBlock) {
2743 SamePHIBlock = getBlockForValue(OpPHI);
2744 } else if (SamePHIBlock != getBlockForValue(OpPHI)) {
2745 DEBUG(dbgs()
2746 << "PHIs for operands are not all in the same block, aborting\n");
2747 return nullptr;
2748 }
27372749 // No point in doing this for one-operand phis.
2738 if (OpPHI->getNumOperands() == 1)
2750 if (OpPHI->getNumOperands() == 1) {
2751 OpPHI = nullptr;
27392752 continue;
2740 if (!DebugCounter::shouldExecute(PHIOfOpsCounter))
2741 return nullptr;
2742 SmallVector Ops;
2743 SmallPtrSet Deps;
2744 auto *PHIBlock = getBlockForValue(OpPHI);
2745 RevisitOnReachabilityChange[PHIBlock].reset(InstrToDFSNum(I));
2746 for (unsigned PredNum = 0; PredNum < OpPHI->getNumOperands(); ++PredNum) {
2747 auto *PredBB = OpPHI->getIncomingBlock(PredNum);
2748 Value *FoundVal = nullptr;
2749 // We could just skip unreachable edges entirely but it's tricky to do
2750 // with rewriting existing phi nodes.
2751 if (ReachableEdges.count({PredBB, PHIBlock})) {
2752 // Clone the instruction, create an expression from it that is
2753 // translated back into the predecessor, and see if we have a leader.
2754 Instruction *ValueOp = I->clone();
2755 SmallPtrSet CurrentDeps;
2756 if (MemAccess)
2757 TempToMemory.insert({ValueOp, MemAccess});
2758 bool SafeForPHIOfOps = true;
2759 VisitedOps.clear();
2760 for (auto &Op : ValueOp->operands()) {
2761 auto *OrigOp = &*Op;
2762 // When these operand changes, it could change whether there is a
2763 // leader for us or not, so we have to add additional users.
2764 if (isa(Op)) {
2765 Op = Op->DoPHITranslation(PHIBlock, PredBB);
2766 if (Op != OrigOp && Op != I)
2767 CurrentDeps.insert(Op);
2768 } else if (auto *ValuePHI = RealToTemp.lookup(Op)) {
2769 if (getBlockForValue(ValuePHI) == PHIBlock)
2770 Op = ValuePHI->getIncomingValueForBlock(PredBB);
2771 }
2772 // If we phi-translated the op, it must be safe.
2773 SafeForPHIOfOps =
2774 SafeForPHIOfOps &&
2775 (Op != OrigOp || OpIsSafeForPHIOfOps(Op, PHIBlock, VisitedOps));
2753 }
2754 }
2755
2756 if (!OpPHI)
2757 return nullptr;
2758
2759 SmallVector PHIOps;
2760 SmallPtrSet Deps;
2761 auto *PHIBlock = getBlockForValue(OpPHI);
2762 RevisitOnReachabilityChange[PHIBlock].reset(InstrToDFSNum(I));
2763 for (unsigned PredNum = 0; PredNum < OpPHI->getNumOperands(); ++PredNum) {
2764 auto *PredBB = OpPHI->getIncomingBlock(PredNum);
2765 Value *FoundVal = nullptr;
2766 SmallPtrSet CurrentDeps;
2767 // We could just skip unreachable edges entirely but it's tricky to do
2768 // with rewriting existing phi nodes.
2769 if (ReachableEdges.count({PredBB, PHIBlock})) {
2770 // Clone the instruction, create an expression from it that is
2771 // translated back into the predecessor, and see if we have a leader.
2772 Instruction *ValueOp = I->clone();
2773 if (MemAccess)
2774 TempToMemory.insert({ValueOp, MemAccess});
2775 bool SafeForPHIOfOps = true;
2776 VisitedOps.clear();
2777 for (auto &Op : ValueOp->operands()) {
2778 auto *OrigOp = &*Op;
2779 // When these operand changes, it could change whether there is a
2780 // leader for us or not, so we have to add additional users.
2781 if (isa(Op)) {
2782 Op = Op->DoPHITranslation(PHIBlock, PredBB);
2783 if (Op != OrigOp && Op != I)
2784 CurrentDeps.insert(Op);
2785 } else if (auto *ValuePHI = RealToTemp.lookup(Op)) {
2786 if (getBlockForValue(ValuePHI) == PHIBlock)
2787 Op = ValuePHI->getIncomingValueForBlock(PredBB);
27762788 }
2777 // FIXME: For those things that are not safe we could generate
2778 // expressions all the way down, and see if this comes out to a
2779 // constant. For anything where that is true, and unsafe, we should
2780 // have made a phi-of-ops (or value numbered it equivalent to something)
2781 // for the pieces already.
2782 FoundVal = !SafeForPHIOfOps ? nullptr
2783 : findLeaderForInst(ValueOp, Visited,
2784 MemAccess, I, PredBB);
2785 ValueOp->deleteValue();
2786 if (!FoundVal) {
2787 // We failed to find a leader for the current ValueOp, but this might
2788 // change in case of the translated operands change.
2789 if (SafeForPHIOfOps)
2790 for (auto Dep : CurrentDeps)
2791 addAdditionalUsers(Dep, I);
2792
2793 return nullptr;
2794 }
2795 Deps.insert(CurrentDeps.begin(), CurrentDeps.end());
2796 } else {
2797 DEBUG(dbgs() << "Skipping phi of ops operand for incoming block "
2798 << getBlockName(PredBB)
2799 << " because the block is unreachable\n");
2800 FoundVal = UndefValue::get(I->getType());
2801 RevisitOnReachabilityChange[PHIBlock].set(InstrToDFSNum(I));
2789 // If we phi-translated the op, it must be safe.
2790 SafeForPHIOfOps =
2791 SafeForPHIOfOps &&
2792 (Op != OrigOp || OpIsSafeForPHIOfOps(Op, PHIBlock, VisitedOps));
28022793 }
2803
2804 Ops.push_back({FoundVal, PredBB});
2805 DEBUG(dbgs() << "Found phi of ops operand " << *FoundVal << " in "
2806 << getBlockName(PredBB) << "\n");
2807 }
2808 for (auto Dep : Deps)
2809 addAdditionalUsers(Dep, I);
2810 sortPHIOps(Ops);
2811 auto *E = performSymbolicPHIEvaluation(Ops, I, PHIBlock);
2812 if (isa(E) || isa(E)) {
2813 DEBUG(dbgs()
2814 << "Not creating real PHI of ops because it simplified to existing "
2815 "value or constant\n");
2816 return E;
2817 }
2818 auto *ValuePHI = RealToTemp.lookup(I);
2819 bool NewPHI = false;
2820 if (!ValuePHI) {
2821 ValuePHI =
2822 PHINode::Create(I->getType(), OpPHI->getNumOperands(), "phiofops");
2823 addPhiOfOps(ValuePHI, PHIBlock, I);
2824 NewPHI = true;
2825 NumGVNPHIOfOpsCreated++;
2826 }
2827 if (NewPHI) {
2828 for (auto PHIOp : Ops)
2829 ValuePHI->addIncoming(PHIOp.first, PHIOp.second);
2794 // FIXME: For those things that are not safe we could generate
2795 // expressions all the way down, and see if this comes out to a
2796 // constant. For anything where that is true, and unsafe, we should
2797 // have made a phi-of-ops (or value numbered it equivalent to something)
2798 // for the pieces already.
2799 FoundVal = !SafeForPHIOfOps ? nullptr
2800 : findLeaderForInst(ValueOp, Visited,
2801 MemAccess, I, PredBB);
2802 ValueOp->deleteValue();
2803 if (!FoundVal) {
2804 // We failed to find a leader for the current ValueOp, but this might
2805 // change in case of the translated operands change.
2806 if (SafeForPHIOfOps)
2807 for (auto Dep : CurrentDeps)
2808 addAdditionalUsers(Dep, I);
2809
2810 return nullptr;
2811 }
2812 Deps.insert(CurrentDeps.begin(), CurrentDeps.end());
28302813 } else {
2831 TempToBlock[ValuePHI] = PHIBlock;
2832 unsigned int i = 0;
2833 for (auto PHIOp : Ops) {
2834 ValuePHI->setIncomingValue(i, PHIOp.first);
2835 ValuePHI->setIncomingBlock(i, PHIOp.second);
2836 ++i;
2837 }
2838 }
2839 RevisitOnReachabilityChange[PHIBlock].set(InstrToDFSNum(I));
2840 DEBUG(dbgs() << "Created phi of ops " << *ValuePHI << " for " << *I
2841 << "\n");
2842
2814 DEBUG(dbgs() << "Skipping phi of ops operand for incoming block "
2815 << getBlockName(PredBB)
2816 << " because the block is unreachable\n");
2817 FoundVal = UndefValue::get(I->getType());
2818 RevisitOnReachabilityChange[PHIBlock].set(InstrToDFSNum(I));
2819 }
2820
2821 PHIOps.push_back({FoundVal, PredBB});
2822 DEBUG(dbgs() << "Found phi of ops operand " << *FoundVal << " in "
2823 << getBlockName(PredBB) << "\n");
2824 }
2825 for (auto Dep : Deps)
2826 addAdditionalUsers(Dep, I);
2827 sortPHIOps(PHIOps);
2828 auto *E = performSymbolicPHIEvaluation(PHIOps, I, PHIBlock);
2829 if (isa(E) || isa(E)) {
2830 DEBUG(dbgs()
2831 << "Not creating real PHI of ops because it simplified to existing "
2832 "value or constant\n");
28432833 return E;
28442834 }
2845 return nullptr;
2835 auto *ValuePHI = RealToTemp.lookup(I);
2836 bool NewPHI = false;
2837 if (!ValuePHI) {
2838 ValuePHI =
2839 PHINode::Create(I->getType(), OpPHI->getNumOperands(), "phiofops");
2840 addPhiOfOps(ValuePHI, PHIBlock, I);
2841 NewPHI = true;
2842 NumGVNPHIOfOpsCreated++;
2843 }
2844 if (NewPHI) {
2845 for (auto PHIOp : PHIOps)
2846 ValuePHI->addIncoming(PHIOp.first, PHIOp.second);
2847 } else {
2848 TempToBlock[ValuePHI] = PHIBlock;
2849 unsigned int i = 0;
2850 for (auto PHIOp : PHIOps) {
2851 ValuePHI->setIncomingValue(i, PHIOp.first);
2852 ValuePHI->setIncomingBlock(i, PHIOp.second);
2853 ++i;
2854 }
2855 }
2856 RevisitOnReachabilityChange[PHIBlock].set(InstrToDFSNum(I));
2857 DEBUG(dbgs() << "Created phi of ops " << *ValuePHI << " for " << *I << "\n");
2858
2859 return E;
28462860 }
28472861
28482862 // The algorithm initially places the values of the routine in the TOP
5353 end:
5454 ret void
5555 }
56
57 ; In this test case a temporary PhiOfOps node gets moved to BB with more
58 ; predecessors, so a new one needs to be created.
59 define void @test2() {
60 ; CHECK-LABEL: @test2(
61 ; CHECK-NEXT: br label [[BB1:%.*]]
62 ; CHECK: bb1:
63 ; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[ADD:%.*]], [[CRITEDGE:%.*]] ]
64 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[STOREMERGE]], 0
65 ; CHECK-NEXT: br i1 [[CMP1]], label [[LR_PH:%.*]], label [[CRITEDGE]]
66 ; CHECK: lr.ph:
67 ; CHECK-NEXT: br i1 undef, label [[SPLIT1:%.*]], label [[SPLIT2:%.*]]
68 ; CHECK: split1:
69 ; CHECK-NEXT: br label [[CRITEDGE]]
70 ; CHECK: split2:
71 ; CHECK-NEXT: br label [[CRITEDGE]]
72 ; CHECK: critedge:
73 ; CHECK-NEXT: [[PHIOFOPS1:%.*]] = phi i1 [ false, [[BB1]] ], [ true, [[SPLIT2]] ], [ true, [[SPLIT1]] ]
74 ; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i1 [ [[CMP1]], [[BB1]] ], [ true, [[SPLIT2]] ], [ true, [[SPLIT1]] ]
75 ; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ 0, [[BB1]] ], [ -1, [[SPLIT1]] ], [ -1, [[SPLIT2]] ]
76 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[STOREMERGE]], -1
77 ; CHECK-NEXT: br i1 [[PHIOFOPS]], label [[BB1]], label [[EXIT:%.*]]
78 ; CHECK: exit:
79 ; CHECK-NEXT: ret void
80 ;
81 br label %bb1
82
83 bb1: ; preds = %critedge, %0
84 %storemerge = phi i32 [ 0, %0 ], [ %add, %critedge ]
85 %cmp1 = icmp eq i32 %storemerge, 0
86 br i1 %cmp1, label %lr.ph, label %critedge
87
88 lr.ph: ; preds = %bb1
89 br i1 undef, label %split1, label %split2
90
91 split1: ; preds = %lr.ph
92 br label %critedge
93
94 split2: ; preds = %lr.ph
95 br label %critedge
96
97 critedge: ; preds = %split1, %split2, %bb1
98 %lcssa = phi i32 [ 0, %bb1 ], [ -1, %split1 ], [ -1, %split2 ]
99 %cmp2 = icmp ne i32 %lcssa, 0
100 %brmerge = or i1 %cmp1, %cmp2
101 %add = add nsw i32 %storemerge, -1
102 br i1 %brmerge, label %bb1, label %exit
103
104 exit: ; preds = %critedge
105 ret void
106 }