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
12using namespace llvm;
13
14static cl::opt<bool>
15DisableAddiLoadHeuristic("disable-ppc-sched-addi-load",
16                         cl::desc("Disable scheduling addi instruction before"
17                                  "load for ppc"), cl::Hidden);
18static 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
24static bool isADDIInstr(const GenericScheduler::SchedCandidate &Cand) {
25  return Cand.SU->getInstr()->getOpcode() == PPC::ADDI ||
26         Cand.SU->getInstr()->getOpcode() == PPC::ADDI8;
27}
28
29bool 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
49void 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
68bool 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
80void 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
100void PPCPostRASchedStrategy::enterMBB(MachineBasicBlock *MBB) {
101  // Custom PPC PostRA specific behavior here.
102  PostGenericScheduler::enterMBB(MBB);
103}
104
105void PPCPostRASchedStrategy::leaveMBB() {
106  // Custom PPC PostRA specific behavior here.
107  PostGenericScheduler::leaveMBB();
108}
109
110void PPCPostRASchedStrategy::initialize(ScheduleDAGMI *Dag) {
111  // Custom PPC PostRA specific initialization here.
112  PostGenericScheduler::initialize(Dag);
113}
114
115SUnit *PPCPostRASchedStrategy::pickNode(bool &IsTopNode) {
116  // Custom PPC PostRA specific scheduling here.
117  return PostGenericScheduler::pickNode(IsTopNode);
118}
119
120