ARMSubtarget.cpp revision 385e930d55f3ecd3c9538823dfa5896a12461845
1//===-- ARMSubtarget.cpp - ARM Subtarget Information ------------*- C++ -*-===//
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 ARM specific subclass of TargetSubtargetInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARMSubtarget.h"
15#include "ARMBaseRegisterInfo.h"
16#include "llvm/GlobalValue.h"
17#include "llvm/Target/TargetSubtargetInfo.h"
18#include "llvm/Support/CommandLine.h"
19#include "llvm/ADT/SmallVector.h"
20
21#define GET_SUBTARGETINFO_CTOR
22#define GET_SUBTARGETINFO_MC_DESC
23#define GET_SUBTARGETINFO_TARGET_DESC
24#include "ARMGenSubtargetInfo.inc"
25
26using namespace llvm;
27
28static cl::opt<bool>
29ReserveR9("arm-reserve-r9", cl::Hidden,
30          cl::desc("Reserve R9, making it unavailable as GPR"));
31
32static cl::opt<bool>
33DarwinUseMOVT("arm-darwin-use-movt", cl::init(true), cl::Hidden);
34
35static cl::opt<bool>
36StrictAlign("arm-strict-align", cl::Hidden,
37            cl::desc("Disallow all unaligned memory accesses"));
38
39ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
40                           const std::string &FS, bool isT)
41  : ARMGenSubtargetInfo()
42  , ARMArchVersion(V4)
43  , ARMProcFamily(Others)
44  , ARMFPUType(None)
45  , UseNEONForSinglePrecisionFP(false)
46  , SlowFPVMLx(false)
47  , HasVMLxForwarding(false)
48  , SlowFPBrcc(false)
49  , IsThumb(isT)
50  , ThumbMode(Thumb1)
51  , NoARM(false)
52  , PostRAScheduler(false)
53  , IsR9Reserved(ReserveR9)
54  , UseMovt(false)
55  , HasFP16(false)
56  , HasD16(false)
57  , HasHardwareDivide(false)
58  , HasT2ExtractPack(false)
59  , HasDataBarrier(false)
60  , Pref32BitThumb(false)
61  , AvoidCPSRPartialUpdate(false)
62  , HasMPExtension(false)
63  , FPOnlySP(false)
64  , AllowsUnalignedMem(false)
65  , Thumb2DSP(false)
66  , stackAlignment(4)
67  , CPUString(CPU)
68  , TargetTriple(TT)
69  , TargetABI(ARM_ABI_APCS) {
70  // Determine default and user specified characteristics
71
72  // When no arch is specified either by CPU or by attributes, make the default
73  // ARMv4T.
74  const char *ARMArchFeature = "";
75  if (CPUString.empty())
76    CPUString = "generic";
77  if (CPUString == "generic" && (FS.empty() || FS == "generic")) {
78    ARMArchVersion = V4T;
79    ARMArchFeature = "+v4t";
80  }
81
82  // Set the boolean corresponding to the current target triple, or the default
83  // if one cannot be determined, to true.
84  unsigned Len = TT.length();
85  unsigned Idx = 0;
86
87  if (Len >= 5 && TT.substr(0, 4) == "armv")
88    Idx = 4;
89  else if (Len >= 6 && TT.substr(0, 5) == "thumb") {
90    IsThumb = true;
91    if (Len >= 7 && TT[5] == 'v')
92      Idx = 6;
93  }
94  if (Idx) {
95    unsigned SubVer = TT[Idx];
96    if (SubVer >= '7' && SubVer <= '9') {
97      ARMArchVersion = V7A;
98      ARMArchFeature = "+v7a";
99      if (Len >= Idx+2 && TT[Idx+1] == 'm') {
100        ARMArchVersion = V7M;
101        ARMArchFeature = "+v7m";
102      } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') {
103        ARMArchVersion = V7EM;
104        ARMArchFeature = "+v7em";
105      }
106    } else if (SubVer == '6') {
107      ARMArchVersion = V6;
108      ARMArchFeature = "+v6";
109      if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') {
110        ARMArchVersion = V6T2;
111        ARMArchFeature = "+v6t2";
112      }
113    } else if (SubVer == '5') {
114      ARMArchVersion = V5T;
115      ARMArchFeature = "+v5t";
116      if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') {
117        ARMArchVersion = V5TE;
118        ARMArchFeature = "+v5te";
119      }
120    } else if (SubVer == '4') {
121      if (Len >= Idx+2 && TT[Idx+1] == 't') {
122        ARMArchVersion = V4T;
123        ARMArchFeature = "+v4t";
124      } else {
125        ARMArchVersion = V4;
126        ARMArchFeature = "";
127      }
128    }
129  }
130
131  if (TT.find("eabi") != std::string::npos)
132    TargetABI = ARM_ABI_AAPCS;
133
134  // Insert the architecture feature derived from the target triple into the
135  // feature string. This is important for setting features that are implied
136  // based on the architecture version.
137  std::string FSWithArch = std::string(ARMArchFeature);
138  if (FSWithArch.empty())
139    FSWithArch = FS;
140  else if (!FS.empty())
141    FSWithArch = FSWithArch + "," + FS;
142  ParseSubtargetFeatures(FSWithArch, CPUString);
143
144  // Initialize scheduling itinerary for the specified CPU.
145  InstrItins = getInstrItineraryForCPU(CPUString);
146
147  // After parsing Itineraries, set ItinData.IssueWidth.
148  computeIssueWidth();
149
150  // Thumb2 implies at least V6T2.
151  if (ARMArchVersion >= V6T2)
152    ThumbMode = Thumb2;
153  else if (ThumbMode >= Thumb2)
154    ARMArchVersion = V6T2;
155
156  if (isAAPCS_ABI())
157    stackAlignment = 8;
158
159  if (!isTargetDarwin())
160    UseMovt = hasV6T2Ops();
161  else {
162    IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
163    UseMovt = DarwinUseMOVT && hasV6T2Ops();
164  }
165
166  if (!isThumb() || hasThumb2())
167    PostRAScheduler = true;
168
169  // v6+ may or may not support unaligned mem access depending on the system
170  // configuration.
171  if (!StrictAlign && hasV6Ops() && isTargetDarwin())
172    AllowsUnalignedMem = true;
173}
174
175/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
176bool
177ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
178                                 Reloc::Model RelocM) const {
179  if (RelocM == Reloc::Static)
180    return false;
181
182  // Materializable GVs (in JIT lazy compilation mode) do not require an extra
183  // load from stub.
184  bool isDecl = GV->hasAvailableExternallyLinkage();
185  if (GV->isDeclaration() && !GV->isMaterializable())
186    isDecl = true;
187
188  if (!isTargetDarwin()) {
189    // Extra load is needed for all externally visible.
190    if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
191      return false;
192    return true;
193  } else {
194    if (RelocM == Reloc::PIC_) {
195      // If this is a strong reference to a definition, it is definitely not
196      // through a stub.
197      if (!isDecl && !GV->isWeakForLinker())
198        return false;
199
200      // Unless we have a symbol with hidden visibility, we have to go through a
201      // normal $non_lazy_ptr stub because this symbol might be resolved late.
202      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
203        return true;
204
205      // If symbol visibility is hidden, we have a stub for common symbol
206      // references and external declarations.
207      if (isDecl || GV->hasCommonLinkage())
208        // Hidden $non_lazy_ptr reference.
209        return true;
210
211      return false;
212    } else {
213      // If this is a strong reference to a definition, it is definitely not
214      // through a stub.
215      if (!isDecl && !GV->isWeakForLinker())
216        return false;
217
218      // Unless we have a symbol with hidden visibility, we have to go through a
219      // normal $non_lazy_ptr stub because this symbol might be resolved late.
220      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
221        return true;
222    }
223  }
224
225  return false;
226}
227
228unsigned ARMSubtarget::getMispredictionPenalty() const {
229  // If we have a reasonable estimate of the pipeline depth, then we can
230  // estimate the penalty of a misprediction based on that.
231  if (isCortexA8())
232    return 13;
233  else if (isCortexA9())
234    return 8;
235
236  // Otherwise, just return a sensible default.
237  return 10;
238}
239
240void ARMSubtarget::computeIssueWidth() {
241  unsigned allStage1Units = 0;
242  for (const InstrItinerary *itin = InstrItins.Itineraries;
243       itin->FirstStage != ~0U; ++itin) {
244    const InstrStage *IS = InstrItins.Stages + itin->FirstStage;
245    allStage1Units |= IS->getUnits();
246  }
247  InstrItins.IssueWidth = 0;
248  while (allStage1Units) {
249    ++InstrItins.IssueWidth;
250    // clear the lowest bit
251    allStage1Units ^= allStage1Units & ~(allStage1Units - 1);
252  }
253  assert(InstrItins.IssueWidth <= 2 && "itinerary bug, too many stage 1 units");
254}
255
256bool ARMSubtarget::enablePostRAScheduler(
257           CodeGenOpt::Level OptLevel,
258           TargetSubtargetInfo::AntiDepBreakMode& Mode,
259           RegClassVector& CriticalPathRCs) const {
260  Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL;
261  CriticalPathRCs.clear();
262  CriticalPathRCs.push_back(&ARM::GPRRegClass);
263  return PostRAScheduler && OptLevel >= CodeGenOpt::Default;
264}
265