1 //===- PPCMachineScheduler.cpp - MI Scheduler for PowerPC -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PPCMachineScheduler.h" 10 #include "MCTargetDesc/PPCMCTargetDesc.h" 11 12 using namespace llvm; 13 14 static cl::opt<bool> 15 DisableAddiLoadHeuristic("disable-ppc-sched-addi-load", 16 cl::desc("Disable scheduling addi instruction before" 17 "load for ppc"), cl::Hidden); 18 static cl::opt<bool> 19 EnableAddiHeuristic("ppc-postra-bias-addi", 20 cl::desc("Enable scheduling addi instruction as early" 21 "as possible post ra"), 22 cl::Hidden, cl::init(true)); 23 24 static bool isADDIInstr(const GenericScheduler::SchedCandidate &Cand) { 25 return Cand.SU->getInstr()->getOpcode() == PPC::ADDI || 26 Cand.SU->getInstr()->getOpcode() == PPC::ADDI8; 27 } 28 29 bool PPCPreRASchedStrategy::biasAddiLoadCandidate(SchedCandidate &Cand, 30 SchedCandidate &TryCand, 31 SchedBoundary &Zone) const { 32 if (DisableAddiLoadHeuristic) 33 return false; 34 35 SchedCandidate &FirstCand = Zone.isTop() ? TryCand : Cand; 36 SchedCandidate &SecondCand = Zone.isTop() ? Cand : TryCand; 37 if (isADDIInstr(FirstCand) && SecondCand.SU->getInstr()->mayLoad()) { 38 TryCand.Reason = Stall; 39 return true; 40 } 41 if (FirstCand.SU->getInstr()->mayLoad() && isADDIInstr(SecondCand)) { 42 TryCand.Reason = NoCand; 43 return true; 44 } 45 46 return false; 47 } 48 49 void PPCPreRASchedStrategy::tryCandidate(SchedCandidate &Cand, 50 SchedCandidate &TryCand, 51 SchedBoundary *Zone) const { 52 GenericScheduler::tryCandidate(Cand, TryCand, Zone); 53 54 if (!Cand.isValid() || !Zone) 55 return; 56 57 // Add powerpc specific heuristic only when TryCand isn't selected or 58 // selected as node order. 59 if (TryCand.Reason != NodeOrder && TryCand.Reason != NoCand) 60 return; 61 62 // There are some benefits to schedule the ADDI before the load to hide the 63 // latency, as RA may create a true dependency between the load and addi. 64 if (biasAddiLoadCandidate(Cand, TryCand, *Zone)) 65 return; 66 } 67 68 bool PPCPostRASchedStrategy::biasAddiCandidate(SchedCandidate &Cand, 69 SchedCandidate &TryCand) const { 70 if (!EnableAddiHeuristic) 71 return false; 72 73 if (isADDIInstr(TryCand) && !isADDIInstr(Cand)) { 74 TryCand.Reason = Stall; 75 return true; 76 } 77 return false; 78 } 79 80 void PPCPostRASchedStrategy::tryCandidate(SchedCandidate &Cand, 81 SchedCandidate &TryCand) { 82 PostGenericScheduler::tryCandidate(Cand, TryCand); 83 84 if (!Cand.isValid()) 85 return; 86 87 // Add powerpc post ra specific heuristic only when TryCand isn't selected or 88 // selected as node order. 89 if (TryCand.Reason != NodeOrder && TryCand.Reason != NoCand) 90 return; 91 92 // There are some benefits to schedule the ADDI as early as possible post ra 93 // to avoid stalled by vector instructions which take up all the hw units. 94 // And ADDI is usually used to post inc the loop indvar, which matters the 95 // performance. 96 if (biasAddiCandidate(Cand, TryCand)) 97 return; 98 } 99 100 void PPCPostRASchedStrategy::enterMBB(MachineBasicBlock *MBB) { 101 // Custom PPC PostRA specific behavior here. 102 PostGenericScheduler::enterMBB(MBB); 103 } 104 105 void PPCPostRASchedStrategy::leaveMBB() { 106 // Custom PPC PostRA specific behavior here. 107 PostGenericScheduler::leaveMBB(); 108 } 109 110 void PPCPostRASchedStrategy::initialize(ScheduleDAGMI *Dag) { 111 // Custom PPC PostRA specific initialization here. 112 PostGenericScheduler::initialize(Dag); 113 } 114 115 SUnit *PPCPostRASchedStrategy::pickNode(bool &IsTopNode) { 116 // Custom PPC PostRA specific scheduling here. 117 return PostGenericScheduler::pickNode(IsTopNode); 118 } 119 120