xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMachineScheduler.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- PPCMachineScheduler.cpp - MI Scheduler for PowerPC -------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "PPCMachineScheduler.h"
10*0b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h"
11*0b57cec5SDimitry Andric 
12*0b57cec5SDimitry Andric using namespace llvm;
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric static cl::opt<bool>
15*0b57cec5SDimitry Andric DisableAddiLoadHeuristic("disable-ppc-sched-addi-load",
16*0b57cec5SDimitry Andric                          cl::desc("Disable scheduling addi instruction before"
17*0b57cec5SDimitry Andric                                   "load for ppc"), cl::Hidden);
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric bool PPCPreRASchedStrategy::biasAddiLoadCandidate(SchedCandidate &Cand,
20*0b57cec5SDimitry Andric                                                   SchedCandidate &TryCand,
21*0b57cec5SDimitry Andric                                                   SchedBoundary &Zone) const {
22*0b57cec5SDimitry Andric   if (DisableAddiLoadHeuristic)
23*0b57cec5SDimitry Andric     return false;
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric   auto isADDIInstr = [&] (const MachineInstr &Inst) {
26*0b57cec5SDimitry Andric     return Inst.getOpcode() == PPC::ADDI || Inst.getOpcode() == PPC::ADDI8;
27*0b57cec5SDimitry Andric   };
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric   SchedCandidate &FirstCand = Zone.isTop() ? TryCand : Cand;
30*0b57cec5SDimitry Andric   SchedCandidate &SecondCand = Zone.isTop() ? Cand : TryCand;
31*0b57cec5SDimitry Andric   if (isADDIInstr(*FirstCand.SU->getInstr()) &&
32*0b57cec5SDimitry Andric       SecondCand.SU->getInstr()->mayLoad()) {
33*0b57cec5SDimitry Andric     TryCand.Reason = Stall;
34*0b57cec5SDimitry Andric     return true;
35*0b57cec5SDimitry Andric   }
36*0b57cec5SDimitry Andric   if (FirstCand.SU->getInstr()->mayLoad() &&
37*0b57cec5SDimitry Andric       isADDIInstr(*SecondCand.SU->getInstr())) {
38*0b57cec5SDimitry Andric     TryCand.Reason = NoCand;
39*0b57cec5SDimitry Andric     return true;
40*0b57cec5SDimitry Andric   }
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric   return false;
43*0b57cec5SDimitry Andric }
44*0b57cec5SDimitry Andric 
45*0b57cec5SDimitry Andric void PPCPreRASchedStrategy::tryCandidate(SchedCandidate &Cand,
46*0b57cec5SDimitry Andric                                          SchedCandidate &TryCand,
47*0b57cec5SDimitry Andric                                          SchedBoundary *Zone) const {
48*0b57cec5SDimitry Andric   GenericScheduler::tryCandidate(Cand, TryCand, Zone);
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric   if (!Cand.isValid() || !Zone)
51*0b57cec5SDimitry Andric     return;
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric   // Add powerpc specific heuristic only when TryCand isn't selected or
54*0b57cec5SDimitry Andric   // selected as node order.
55*0b57cec5SDimitry Andric   if (TryCand.Reason != NodeOrder && TryCand.Reason != NoCand)
56*0b57cec5SDimitry Andric     return;
57*0b57cec5SDimitry Andric 
58*0b57cec5SDimitry Andric   // There are some benefits to schedule the ADDI before the load to hide the
59*0b57cec5SDimitry Andric   // latency, as RA may create a true dependency between the load and addi.
60*0b57cec5SDimitry Andric   if (biasAddiLoadCandidate(Cand, TryCand, *Zone))
61*0b57cec5SDimitry Andric     return;
62*0b57cec5SDimitry Andric }
63*0b57cec5SDimitry Andric 
64*0b57cec5SDimitry Andric void PPCPostRASchedStrategy::enterMBB(MachineBasicBlock *MBB) {
65*0b57cec5SDimitry Andric   // Custom PPC PostRA specific behavior here.
66*0b57cec5SDimitry Andric   PostGenericScheduler::enterMBB(MBB);
67*0b57cec5SDimitry Andric }
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric void PPCPostRASchedStrategy::leaveMBB() {
70*0b57cec5SDimitry Andric   // Custom PPC PostRA specific behavior here.
71*0b57cec5SDimitry Andric   PostGenericScheduler::leaveMBB();
72*0b57cec5SDimitry Andric }
73*0b57cec5SDimitry Andric 
74*0b57cec5SDimitry Andric void PPCPostRASchedStrategy::initialize(ScheduleDAGMI *Dag) {
75*0b57cec5SDimitry Andric   // Custom PPC PostRA specific initialization here.
76*0b57cec5SDimitry Andric   PostGenericScheduler::initialize(Dag);
77*0b57cec5SDimitry Andric }
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric SUnit *PPCPostRASchedStrategy::pickNode(bool &IsTopNode) {
80*0b57cec5SDimitry Andric   // Custom PPC PostRA specific scheduling here.
81*0b57cec5SDimitry Andric   return PostGenericScheduler::pickNode(IsTopNode);
82*0b57cec5SDimitry Andric }
83*0b57cec5SDimitry Andric 
84