llvm.org GIT mirror llvm / d4f7596
Add a really faster pre-RA scheduler (-pre-RA-sched=linearize). It doesn't use any scheduling heuristics nor does it build up any scheduling data structure that other heuristics use. It essentially linearize by doing a DFA walk but it does handle glues correctly. IMPORTANT: it probably can't handle all the physical register dependencies so it's not suitable for x86. It also doesn't deal with dbg_value nodes right now so it's definitely is still WIP. rdar://12474515 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166122 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 7 years ago
4 changed file(s) with 165 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
101101 ScheduleDAGSDNodes *createDefaultScheduler(SelectionDAGISel *IS,
102102 CodeGenOpt::Level OptLevel);
103103
104 /// createDAGLinearizer - This creates a "no-scheduling" scheduler which
105 /// linearize the DAG using topological order.
106 ScheduleDAGSDNodes *createDAGLinearizer(SelectionDAGISel *IS,
107 CodeGenOpt::Level OptLevel);
108
104109 } // end namespace llvm
105110
106111 #endif
1212
1313 #define DEBUG_TYPE "pre-RA-sched"
1414 #include "ScheduleDAGSDNodes.h"
15 #include "InstrEmitter.h"
1516 #include "llvm/InlineAsm.h"
1617 #include "llvm/CodeGen/SchedulerRegistry.h"
1718 #include "llvm/CodeGen/SelectionDAGISel.h"
3334 static RegisterScheduler
3435 fastDAGScheduler("fast", "Fast suboptimal list scheduling",
3536 createFastDAGScheduler);
37 static RegisterScheduler
38 linearizeDAGScheduler("linearize", "Linearize DAG, no scheduling",
39 createDAGLinearizer);
40
3641
3742 namespace {
3843 /// FastPriorityQueue - A degenerate priority queue that considers
628633 #endif
629634 }
630635
636
637 //===----------------------------------------------------------------------===//
638 // ScheduleDAGLinearize - No scheduling scheduler, it simply linearize the
639 // DAG in topological order.
640 // IMPORTANT: this may not work for targets with phyreg dependency.
641 //
642 class ScheduleDAGLinearize : public ScheduleDAGSDNodes {
643 public:
644 ScheduleDAGLinearize(MachineFunction &mf) : ScheduleDAGSDNodes(mf) {}
645
646 void Schedule();
647
648 MachineBasicBlock *EmitSchedule(MachineBasicBlock::iterator &InsertPos);
649
650 private:
651 std::vector Sequence;
652 DenseMap GluedMap; // Cache glue to its user
653
654 void ScheduleNode(SDNode *N);
655 };
656
657 void ScheduleDAGLinearize::ScheduleNode(SDNode *N) {
658 if (N->getNodeId() != 0)
659 llvm_unreachable(0);
660
661 if (!N->isMachineOpcode() &&
662 (N->getOpcode() == ISD::EntryToken || isPassiveNode(N)))
663 // These nodes do not need to be translated into MIs.
664 return;
665
666 DEBUG(dbgs() << "\n*** Scheduling: ");
667 DEBUG(N->dump(DAG));
668 Sequence.push_back(N);
669
670 unsigned NumOps = N->getNumOperands();
671 if (unsigned NumLeft = NumOps) {
672 SDNode *GluedOpN = 0;
673 do {
674 const SDValue &Op = N->getOperand(NumLeft-1);
675 SDNode *OpN = Op.getNode();
676
677 if (NumLeft == NumOps && Op.getValueType() == MVT::Glue) {
678 // Schedule glue operand right above N.
679 GluedOpN = OpN;
680 assert(OpN->getNodeId() != 0 && "Glue operand not ready?");
681 OpN->setNodeId(0);
682 ScheduleNode(OpN);
683 continue;
684 }
685
686 if (OpN == GluedOpN)
687 // Glue operand is already scheduled.
688 continue;
689
690 DenseMap::iterator DI = GluedMap.find(OpN);
691 if (DI != GluedMap.end() && DI->second != N)
692 // Users of glues are counted against the glued users.
693 OpN = DI->second;
694
695 unsigned Degree = OpN->getNodeId();
696 assert(Degree > 0 && "Predecessor over-released!");
697 OpN->setNodeId(--Degree);
698 if (Degree == 0)
699 ScheduleNode(OpN);
700 } while (--NumLeft);
701 }
702 }
703
704 /// findGluedUser - Find the representative use of a glue value by walking
705 /// the use chain.
706 static SDNode *findGluedUser(SDNode *N) {
707 while (SDNode *Glued = N->getGluedUser())
708 N = Glued;
709 return N;
710 }
711
712 void ScheduleDAGLinearize::Schedule() {
713 DEBUG(dbgs() << "********** DAG Linearization **********\n");
714
715 SmallVector Glues;
716 unsigned DAGSize = 0;
717 for (SelectionDAG::allnodes_iterator I = DAG->allnodes_begin(),
718 E = DAG->allnodes_end(); I != E; ++I) {
719 SDNode *N = I;
720
721 // Use node id to record degree.
722 unsigned Degree = N->use_size();
723 N->setNodeId(Degree);
724 unsigned NumVals = N->getNumValues();
725 if (NumVals && N->getValueType(NumVals-1) == MVT::Glue &&
726 N->hasAnyUseOfValue(NumVals-1)) {
727 SDNode *User = findGluedUser(N);
728 if (User) {
729 Glues.push_back(N);
730 GluedMap.insert(std::make_pair(N, User));
731 }
732 }
733
734 if (N->isMachineOpcode() ||
735 (N->getOpcode() != ISD::EntryToken && !isPassiveNode(N)))
736 ++DAGSize;
737 }
738
739 for (unsigned i = 0, e = Glues.size(); i != e; ++i) {
740 SDNode *Glue = Glues[i];
741 SDNode *GUser = GluedMap[Glue];
742 unsigned Degree = Glue->getNodeId();
743 unsigned UDegree = GUser->getNodeId();
744
745 // Glue user must be scheduled together with the glue operand. So other
746 // users of the glue operand must be treated as its users.
747 SDNode *ImmGUser = Glue->getGluedUser();
748 for (SDNode::use_iterator ui = Glue->use_begin(), ue = Glue->use_end();
749 ui != ue; ++ui)
750 if (*ui == ImmGUser)
751 --Degree;
752 GUser->setNodeId(UDegree + Degree);
753 Glue->setNodeId(1);
754 }
755
756 Sequence.reserve(DAGSize);
757 ScheduleNode(DAG->getRoot().getNode());
758 }
759
760 MachineBasicBlock*
761 ScheduleDAGLinearize::EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
762 InstrEmitter Emitter(BB, InsertPos);
763 DenseMap VRBaseMap;
764
765 DEBUG({
766 dbgs() << "\n*** Final schedule ***\n";
767 });
768
769 // FIXME: Handle dbg_values.
770 unsigned NumNodes = Sequence.size();
771 for (unsigned i = 0; i != NumNodes; ++i) {
772 SDNode *N = Sequence[NumNodes-i-1];
773 DEBUG(N->dump(DAG));
774 Emitter.EmitNode(N, false, false, VRBaseMap);
775 }
776
777 DEBUG(dbgs() << '\n');
778
779 InsertPos = Emitter.getInsertPos();
780 return Emitter.getBlock();
781 }
782
631783 //===----------------------------------------------------------------------===//
632784 // Public Constructor Functions
633785 //===----------------------------------------------------------------------===//
636788 llvm::createFastDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) {
637789 return new ScheduleDAGFast(*IS->MF);
638790 }
791
792 llvm::ScheduleDAGSDNodes *
793 llvm::createDAGLinearizer(SelectionDAGISel *IS, CodeGenOpt::Level) {
794 return new ScheduleDAGLinearize(*IS->MF);
795 }
830830 }
831831
832832 SmallVector GluedNodes;
833 for (SDNode *N = SU->getNode()->getGluedNode(); N;
834 N = N->getGluedNode())
833 for (SDNode *N = SU->getNode()->getGluedNode(); N; N = N->getGluedNode())
835834 GluedNodes.push_back(N);
836835 while (!GluedNodes.empty()) {
837836 SDNode *N = GluedNodes.back();
113113 /// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock
114114 /// according to the order specified in Sequence.
115115 ///
116 MachineBasicBlock *EmitSchedule(MachineBasicBlock::iterator &InsertPos);
116 virtual MachineBasicBlock*
117 EmitSchedule(MachineBasicBlock::iterator &InsertPos);
117118
118119 virtual void dumpNode(const SUnit *SU) const;
119120