LLVM  4.0.0
HexagonSubtarget.cpp
Go to the documentation of this file.
1 //===-- HexagonSubtarget.cpp - Hexagon Subtarget Information --------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the Hexagon specific subclass of TargetSubtarget.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "HexagonSubtarget.h"
15 #include "Hexagon.h"
16 #include "HexagonRegisterInfo.h"
21 #include <map>
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "hexagon-subtarget"
26 
27 #define GET_SUBTARGETINFO_CTOR
28 #define GET_SUBTARGETINFO_TARGET_DESC
29 #include "HexagonGenSubtargetInfo.inc"
30 
31 static cl::opt<bool> EnableMemOps("enable-hexagon-memops",
33  cl::desc("Generate V4 MEMOP in code generation for Hexagon target"));
34 
35 static cl::opt<bool> DisableMemOps("disable-hexagon-memops",
37  cl::desc("Do not generate V4 MEMOP in code generation for Hexagon target"));
38 
39 static cl::opt<bool> EnableIEEERndNear("enable-hexagon-ieee-rnd-near",
41  cl::desc("Generate non-chopped conversion from fp to int."));
42 
43 static cl::opt<bool> EnableBSBSched("enable-bsb-sched",
45 
46 static cl::opt<bool> EnableHexagonHVXDouble("enable-hexagon-hvx-double",
48  cl::desc("Enable Hexagon Double Vector eXtensions"));
49 
50 static cl::opt<bool> EnableHexagonHVX("enable-hexagon-hvx",
52  cl::desc("Enable Hexagon Vector eXtensions"));
53 
54 static cl::opt<bool> EnableTCLatencySched("enable-tc-latency-sched",
56 
57 static cl::opt<bool> EnableDotCurSched("enable-cur-sched",
59  cl::desc("Enable the scheduler to generate .cur"));
60 
61 static cl::opt<bool> EnableVecFrwdSched("enable-evec-frwd-sched",
63 
64 static cl::opt<bool> DisableHexagonMISched("disable-hexagon-misched",
66  cl::desc("Disable Hexagon MI Scheduling"));
67 
68 static cl::opt<bool> EnableSubregLiveness("hexagon-subreg-liveness",
70  cl::desc("Enable subregister liveness tracking for Hexagon"));
71 
72 static cl::opt<bool> OverrideLongCalls("hexagon-long-calls",
74  cl::desc("If present, forces/disables the use of long calls"));
75 
76 void HexagonSubtarget::initializeEnvironment() {
77  UseMemOps = false;
78  ModeIEEERndNear = false;
79  UseBSBScheduling = false;
80 }
81 
84  CPUString = Hexagon_MC::selectHexagonCPU(getTargetTriple(), CPU);
85 
86  static std::map<StringRef, HexagonArchEnum> CpuTable {
87  { "hexagonv4", V4 },
88  { "hexagonv5", V5 },
89  { "hexagonv55", V55 },
90  { "hexagonv60", V60 },
91  };
92 
93  auto foundIt = CpuTable.find(CPUString);
94  if (foundIt != CpuTable.end())
95  HexagonArchVersion = foundIt->second;
96  else
97  llvm_unreachable("Unrecognized Hexagon processor version");
98 
99  UseHVXOps = false;
100  UseHVXDblOps = false;
101  UseLongCalls = false;
102  ParseSubtargetFeatures(CPUString, FS);
103 
104  if (EnableHexagonHVX.getPosition())
105  UseHVXOps = EnableHexagonHVX;
106  if (EnableHexagonHVXDouble.getPosition())
107  UseHVXDblOps = EnableHexagonHVXDouble;
108  if (OverrideLongCalls.getPosition())
109  UseLongCalls = OverrideLongCalls;
110 
111  return *this;
112 }
113 
115  StringRef FS, const TargetMachine &TM)
116  : HexagonGenSubtargetInfo(TT, CPU, FS), CPUString(CPU),
117  InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
118  FrameLowering() {
119 
120  initializeEnvironment();
121 
122  // Initialize scheduling itinerary for the specified CPU.
123  InstrItins = getInstrItineraryForCPU(CPUString);
124 
125  // UseMemOps on by default unless disabled explicitly
126  if (DisableMemOps)
127  UseMemOps = false;
128  else if (EnableMemOps)
129  UseMemOps = true;
130  else
131  UseMemOps = false;
132 
133  if (EnableIEEERndNear)
134  ModeIEEERndNear = true;
135  else
136  ModeIEEERndNear = false;
137 
139 }
140 
141 
143  for (auto &SU : DAG->SUnits) {
144  if (!SU.isInstr())
145  continue;
146  SmallVector<SDep, 4> Erase;
147  for (auto &D : SU.Preds)
148  if (D.getKind() == SDep::Output && D.getReg() == Hexagon::USR_OVF)
149  Erase.push_back(D);
150  for (auto &E : Erase)
151  SU.removePred(E);
152  }
153 
154  for (auto &SU : DAG->SUnits) {
155  // Update the latency of chain edges between v60 vector load or store
156  // instructions to be 1. These instructions cannot be scheduled in the
157  // same packet.
158  MachineInstr &MI1 = *SU.getInstr();
159  auto *QII = static_cast<const HexagonInstrInfo*>(DAG->TII);
160  bool IsStoreMI1 = MI1.mayStore();
161  bool IsLoadMI1 = MI1.mayLoad();
162  if (!QII->isV60VectorInstruction(MI1) || !(IsStoreMI1 || IsLoadMI1))
163  continue;
164  for (auto &SI : SU.Succs) {
165  if (SI.getKind() != SDep::Order || SI.getLatency() != 0)
166  continue;
167  MachineInstr &MI2 = *SI.getSUnit()->getInstr();
168  if (!QII->isV60VectorInstruction(MI2))
169  continue;
170  if ((IsStoreMI1 && MI2.mayStore()) || (IsLoadMI1 && MI2.mayLoad())) {
171  SI.setLatency(1);
172  SU.setHeightDirty();
173  // Change the dependence in the opposite direction too.
174  for (auto &PI : SI.getSUnit()->Preds) {
175  if (PI.getSUnit() != &SU || PI.getKind() != SDep::Order)
176  continue;
177  PI.setLatency(1);
178  SI.getSUnit()->setDepthDirty();
179  }
180  }
181  }
182  }
183 }
184 
185 
187  std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
188  Mutations.push_back(make_unique<HexagonSubtarget::HexagonDAGMutation>());
189 }
190 
192  std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
193  Mutations.push_back(make_unique<HexagonSubtarget::HexagonDAGMutation>());
194 }
195 
196 
197 // Pin the vtable to this file.
198 void HexagonSubtarget::anchor() {}
199 
201  if (DisableHexagonMISched.getNumOccurrences())
202  return !DisableHexagonMISched;
203  return true;
204 }
205 
207  return EnableSubregLiveness;
208 }
209 
210 // This helper function is responsible for increasing the latency only.
211 void HexagonSubtarget::updateLatency(MachineInstr &SrcInst,
212  MachineInstr &DstInst, SDep &Dep) const {
213  if (!hasV60TOps())
214  return;
215 
216  auto &QII = static_cast<const HexagonInstrInfo&>(*getInstrInfo());
217 
218  if (EnableVecFrwdSched && QII.addLatencyToSchedule(SrcInst, DstInst)) {
219  // Vec frwd scheduling.
220  Dep.setLatency(Dep.getLatency() + 1);
221  } else if (useBSBScheduling() &&
222  QII.isLateInstrFeedsEarlyInstr(SrcInst, DstInst)) {
223  // BSB scheduling.
224  Dep.setLatency(Dep.getLatency() + 1);
225  } else if (EnableTCLatencySched) {
226  // TClass latency scheduling.
227  // Check if SrcInst produces in 2C an operand of DstInst taken in stage 2B.
228  if (QII.isTC1(SrcInst) || QII.isTC2(SrcInst))
229  if (!QII.isTC1(DstInst) && !QII.isTC2(DstInst))
230  Dep.setLatency(Dep.getLatency() + 1);
231  }
232 }
233 
234 /// If the SUnit has a zero latency edge, return the other SUnit.
236  for (auto &I : Deps)
237  if (I.isAssignedRegDep() && I.getLatency() == 0 &&
238  !I.getSUnit()->getInstr()->isPseudo())
239  return I.getSUnit();
240  return nullptr;
241 }
242 
243 /// Change the latency between the two SUnits.
244 void HexagonSubtarget::changeLatency(SUnit *Src, SmallVector<SDep, 4> &Deps,
245  SUnit *Dst, unsigned Lat) const {
246  MachineInstr &SrcI = *Src->getInstr();
247  for (auto &I : Deps) {
248  if (I.getSUnit() != Dst)
249  continue;
250  I.setLatency(Lat);
251  SUnit *UpdateDst = I.getSUnit();
252  updateLatency(SrcI, *UpdateDst->getInstr(), I);
253  // Update the latency of opposite edge too.
254  for (auto &PI : UpdateDst->Preds) {
255  if (PI.getSUnit() != Src || !PI.isAssignedRegDep())
256  continue;
257  PI.setLatency(Lat);
258  updateLatency(SrcI, *UpdateDst->getInstr(), PI);
259  }
260  }
261 }
262 
263 // Return true if these are the best two instructions to schedule
264 // together with a zero latency. Only one dependence should have a zero
265 // latency. If there are multiple choices, choose the best, and change
266 // ther others, if needed.
267 bool HexagonSubtarget::isBestZeroLatency(SUnit *Src, SUnit *Dst,
268  const HexagonInstrInfo *TII) const {
269  MachineInstr &SrcInst = *Src->getInstr();
270  MachineInstr &DstInst = *Dst->getInstr();
271 
272  // Ignore Boundary SU nodes as these have null instructions.
273  if (Dst->isBoundaryNode())
274  return false;
275 
276  if (SrcInst.isPHI() || DstInst.isPHI())
277  return false;
278 
279  // Check if the Dst instruction is the best candidate first.
280  SUnit *Best = nullptr;
281  SUnit *DstBest = nullptr;
282  SUnit *SrcBest = getZeroLatency(Dst, Dst->Preds);
283  if (SrcBest == nullptr || Src->NodeNum >= SrcBest->NodeNum) {
284  // Check that Src doesn't have a better candidate.
285  DstBest = getZeroLatency(Src, Src->Succs);
286  if (DstBest == nullptr || Dst->NodeNum <= DstBest->NodeNum)
287  Best = Dst;
288  }
289  if (Best != Dst)
290  return false;
291 
292  // The caller frequents adds the same dependence twice. If so, then
293  // return true for this case too.
294  if (Src == SrcBest && Dst == DstBest)
295  return true;
296 
297  // Reassign the latency for the previous bests, which requires setting
298  // the dependence edge in both directions.
299  if (SrcBest != nullptr)
300  changeLatency(SrcBest, SrcBest->Succs, Dst, 1);
301  if (DstBest != nullptr)
302  changeLatency(Src, Src->Succs, DstBest, 1);
303  // If there is an edge from SrcBest to DstBst, then try to change that
304  // to 0 now.
305  if (SrcBest && DstBest)
306  changeLatency(SrcBest, SrcBest->Succs, DstBest, 0);
307 
308  return true;
309 }
310 
311 // Update the latency of a Phi when the Phi bridges two instructions that
312 // require a multi-cycle latency.
313 void HexagonSubtarget::changePhiLatency(MachineInstr &SrcInst, SUnit *Dst,
314  SDep &Dep) const {
315  if (!SrcInst.isPHI() || Dst->NumPreds == 0 || Dep.getLatency() != 0)
316  return;
317 
318  for (const SDep &PI : Dst->Preds) {
319  if (PI.getLatency() != 0)
320  continue;
321  Dep.setLatency(2);
322  break;
323  }
324 }
325 
326 /// \brief Perform target specific adjustments to the latency of a schedule
327 /// dependency.
329  SDep &Dep) const {
330  MachineInstr *SrcInst = Src->getInstr();
331  MachineInstr *DstInst = Dst->getInstr();
332  if (!Src->isInstr() || !Dst->isInstr())
333  return;
334 
335  const HexagonInstrInfo *QII = static_cast<const HexagonInstrInfo *>(getInstrInfo());
336 
337  // Instructions with .new operands have zero latency.
338  if (QII->canExecuteInBundle(*SrcInst, *DstInst) &&
339  isBestZeroLatency(Src, Dst, QII)) {
340  Dep.setLatency(0);
341  return;
342  }
343 
344  if (!hasV60TOps())
345  return;
346 
347  // Don't adjust the latency of post-increment part of the instruction.
348  if (QII->isPostIncrement(*SrcInst) && Dep.isAssignedRegDep()) {
349  if (SrcInst->mayStore())
350  return;
351  if (Dep.getReg() != SrcInst->getOperand(0).getReg())
352  return;
353  } else if (QII->isPostIncrement(*DstInst) && Dep.getKind() == SDep::Anti) {
354  if (DstInst->mayStore())
355  return;
356  if (Dep.getReg() != DstInst->getOperand(0).getReg())
357  return;
358  } else if (QII->isPostIncrement(*DstInst) && DstInst->mayStore() &&
359  Dep.isAssignedRegDep()) {
360  MachineOperand &Op = DstInst->getOperand(DstInst->getNumOperands() - 1);
361  if (Op.isReg() && Dep.getReg() != Op.getReg())
362  return;
363  }
364 
365  // Check if we need to change any the latency values when Phis are added.
366  if (useBSBScheduling() && SrcInst->isPHI()) {
367  changePhiLatency(*SrcInst, Dst, Dep);
368  return;
369  }
370 
371  // If it's a REG_SEQUENCE, use its destination instruction to determine
372  // the correct latency.
373  if (DstInst->isRegSequence() && Dst->NumSuccs == 1)
374  DstInst = Dst->Succs[0].getSUnit()->getInstr();
375 
376  // Try to schedule uses near definitions to generate .cur.
377  if (EnableDotCurSched && QII->isToBeScheduledASAP(*SrcInst, *DstInst) &&
378  isBestZeroLatency(Src, Dst, QII)) {
379  Dep.setLatency(0);
380  return;
381  }
382 
383  updateLatency(*SrcInst, *DstInst, Dep);
384 }
385 
387  return 32;
388 }
389 
391  return 32;
392 }
393 
unsigned NumPreds
Definition: ScheduleDAG.h:268
static SUnit * getZeroLatency(SUnit *N, SmallVector< SDep, 4 > &Deps)
If the SUnit has a zero latency edge, return the other SUnit.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
Definition: MachineInstr.h:605
MachineInstr * getInstr() const
getInstr - Return the representative MachineInstr for this SUnit.
Definition: ScheduleDAG.h:389
StringRef selectHexagonCPU(const Triple &TT, StringRef CPU)
bool isInstr() const
isInstr - Return true if this SUnit refers to a machine instruction as opposed to an SDNode...
Definition: ScheduleDAG.h:378
static cl::opt< bool > EnableHexagonHVXDouble("enable-hexagon-hvx-double", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Enable Hexagon Double Vector eXtensions"))
void getSMSMutations(std::vector< std::unique_ptr< ScheduleDAGMutation >> &Mutations) const override
static cl::opt< bool > EnableIEEERndNear("enable-hexagon-ieee-rnd-near", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Generate non-chopped conversion from fp to int."))
bool isAssignedRegDep() const
isAssignedRegDep - Test if this is a Data dependence that is associated with a register.
Definition: ScheduleDAG.h:211
HexagonSubtarget & initializeSubtargetDependencies(StringRef CPU, StringRef FS)
SmallVector< SDep, 4 > Preds
Definition: ScheduleDAG.h:258
A register anti-dependedence (aka WAR).
Definition: ScheduleDAG.h:50
static cl::opt< bool > EnableTCLatencySched("enable-tc-latency-sched", cl::Hidden, cl::ZeroOrMore, cl::init(false))
unsigned NumSuccs
Definition: ScheduleDAG.h:269
const HexagonInstrInfo * TII
Kind getKind() const
getKind - Return an enum value representing the kind of the dependence.
Definition: ScheduleDAG.h:509
unsigned getL1CacheLineSize() const
bool isPHI() const
Definition: MachineInstr.h:786
static cl::opt< bool > OverrideLongCalls("hexagon-long-calls", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("If present, forces/disables the use of long calls"))
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
Definition: MachineInstr.h:592
unsigned getNumOperands() const
Access to explicit operands of the instruction.
Definition: MachineInstr.h:277
A register output-dependence (aka WAW).
Definition: ScheduleDAG.h:51
HexagonSubtarget(const Triple &TT, StringRef CPU, StringRef FS, const TargetMachine &TM)
bool canExecuteInBundle(const MachineInstr &First, const MachineInstr &Second) const
Can these instructions execute at the same time in a bundle.
static cl::opt< bool > DisableMemOps("disable-hexagon-memops", cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed, cl::init(false), cl::desc("Do not generate V4 MEMOP in code generation for Hexagon target"))
static cl::opt< bool > EnableMemOps("enable-hexagon-memops", cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed, cl::init(true), cl::desc("Generate V4 MEMOP in code generation for Hexagon target"))
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
SDep - Scheduling dependency.
Definition: ScheduleDAG.h:45
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:395
HexagonArchEnum HexagonArchVersion
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:279
static cl::opt< bool > EnableHexagonHVX("enable-hexagon-hvx", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Enable Hexagon Vector eXtensions"))
unsigned getLatency() const
getLatency - Return the latency value for this edge, which roughly means the minimum number of cycles...
Definition: ScheduleDAG.h:139
static cl::opt< bool > EnableSubregLiveness("hexagon-subreg-liveness", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::desc("Enable subregister liveness tracking for Hexagon"))
bool isToBeScheduledASAP(const MachineInstr &MI1, const MachineInstr &MI2) const
Any other ordering dependency.
Definition: ScheduleDAG.h:52
bool isPostIncrement(const MachineInstr &MI) const override
Return true for post-incremented instructions.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getL1PrefetchDistance() const
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
void apply(ScheduleDAGInstrs *DAG) override
bool useBSBScheduling() const
bool enableMachineScheduler() const override
void getPostRAMutations(std::vector< std::unique_ptr< ScheduleDAGMutation >> &Mutations) const override
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
bool UseBSBScheduling
True if the target should use Back-Skip-Back scheduling.
bool enableSubRegLiveness() const override
void adjustSchedDependency(SUnit *def, SUnit *use, SDep &dep) const override
Perform target specific adjustments to the latency of a schedule dependency.
bool isBoundaryNode() const
Boundary nodes are placeholders for the boundary of the scheduling region.
Definition: ScheduleDAG.h:360
void setLatency(unsigned Lat)
setLatency - Set the latency for this edge.
Definition: ScheduleDAG.h:144
ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of MachineInstrs. ...
Representation of each machine instruction.
Definition: MachineInstr.h:52
void ParseSubtargetFeatures(StringRef CPU, StringRef FS)
ParseSubtargetFeatures - Parses features string setting specified subtarget options.
static cl::opt< bool > EnableVecFrwdSched("enable-evec-frwd-sched", cl::Hidden, cl::ZeroOrMore, cl::init(true))
#define I(x, y, z)
Definition: MD5.cpp:54
#define N
const TargetInstrInfo * TII
Definition: ScheduleDAG.h:579
unsigned NodeNum
Definition: ScheduleDAG.h:266
unsigned getReg() const
getReg - Returns the register number.
const HexagonInstrInfo * getInstrInfo() const override
SmallVector< SDep, 4 > Succs
Definition: ScheduleDAG.h:259
Primary interface to the complete machine description for the target machine.
static cl::opt< bool > EnableBSBSched("enable-bsb-sched", cl::Hidden, cl::ZeroOrMore, cl::init(true))
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
static cl::opt< bool > DisableHexagonMISched("disable-hexagon-misched", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable Hexagon MI Scheduling"))
bool isRegSequence() const
Definition: MachineInstr.h:801
std::vector< SUnit > SUnits
Definition: ScheduleDAG.h:583
unsigned getReg() const
getReg - Return the register associated with this edge.
Definition: ScheduleDAG.h:218
SUnit - Scheduling unit. This is a node in the scheduling DAG.
Definition: ScheduleDAG.h:244
static cl::opt< bool > EnableDotCurSched("enable-cur-sched", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::desc("Enable the scheduler to generate .cur"))