• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TARGET_DESC
22  #define GET_SUBTARGETINFO_CTOR
23  #include "ARMGenSubtargetInfo.inc"
24  
25  using namespace llvm;
26  
27  static cl::opt<bool>
28  ReserveR9("arm-reserve-r9", cl::Hidden,
29            cl::desc("Reserve R9, making it unavailable as GPR"));
30  
31  static cl::opt<bool>
32  DarwinUseMOVT("arm-darwin-use-movt", cl::init(true), cl::Hidden);
33  
34  static cl::opt<bool>
35  StrictAlign("arm-strict-align", cl::Hidden,
36              cl::desc("Disallow all unaligned memory accesses"));
37  
ARMSubtarget(const std::string & TT,const std::string & CPU,const std::string & FS)38  ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
39                             const std::string &FS)
40    : ARMGenSubtargetInfo(TT, CPU, FS)
41    , ARMProcFamily(Others)
42    , HasV4TOps(false)
43    , HasV5TOps(false)
44    , HasV5TEOps(false)
45    , HasV6Ops(false)
46    , HasV6T2Ops(false)
47    , HasV7Ops(false)
48    , HasVFPv2(false)
49    , HasVFPv3(false)
50    , HasNEON(false)
51    , UseNEONForSinglePrecisionFP(false)
52    , SlowFPVMLx(false)
53    , HasVMLxForwarding(false)
54    , SlowFPBrcc(false)
55    , InThumbMode(false)
56    , InNaClMode(false)
57    , HasThumb2(false)
58    , IsMClass(false)
59    , NoARM(false)
60    , PostRAScheduler(false)
61    , IsR9Reserved(ReserveR9)
62    , UseMovt(false)
63    , SupportsTailCall(false)
64    , HasFP16(false)
65    , HasD16(false)
66    , HasHardwareDivide(false)
67    , HasT2ExtractPack(false)
68    , HasDataBarrier(false)
69    , Pref32BitThumb(false)
70    , AvoidCPSRPartialUpdate(false)
71    , HasMPExtension(false)
72    , FPOnlySP(false)
73    , AllowsUnalignedMem(false)
74    , Thumb2DSP(false)
75    , stackAlignment(4)
76    , CPUString(CPU)
77    , TargetTriple(TT)
78    , TargetABI(ARM_ABI_APCS) {
79    // Determine default and user specified characteristics
80    if (CPUString.empty())
81      CPUString = "generic";
82  
83    // Insert the architecture feature derived from the target triple into the
84    // feature string. This is important for setting features that are implied
85    // based on the architecture version.
86    std::string ArchFS = ARM_MC::ParseARMTriple(TT);
87    if (!FS.empty()) {
88      if (!ArchFS.empty())
89        ArchFS = ArchFS + "," + FS;
90      else
91        ArchFS = FS;
92    }
93    ParseSubtargetFeatures(CPUString, ArchFS);
94  
95    // Thumb2 implies at least V6T2. FIXME: Fix tests to explicitly specify a
96    // ARM version or CPU and then remove this.
97    if (!HasV6T2Ops && hasThumb2())
98      HasV4TOps = HasV5TOps = HasV5TEOps = HasV6Ops = HasV6T2Ops = true;
99  
100    // Initialize scheduling itinerary for the specified CPU.
101    InstrItins = getInstrItineraryForCPU(CPUString);
102  
103    // After parsing Itineraries, set ItinData.IssueWidth.
104    computeIssueWidth();
105  
106    if (TT.find("eabi") != std::string::npos)
107      TargetABI = ARM_ABI_AAPCS;
108  
109    if (isAAPCS_ABI())
110      stackAlignment = 8;
111  
112    if (!isTargetDarwin())
113      UseMovt = hasV6T2Ops();
114    else {
115      IsR9Reserved = ReserveR9 | !HasV6Ops;
116      UseMovt = DarwinUseMOVT && hasV6T2Ops();
117      const Triple &T = getTargetTriple();
118      SupportsTailCall = T.getOS() == Triple::IOS && !T.isOSVersionLT(5, 0);
119    }
120  
121    if (!isThumb() || hasThumb2())
122      PostRAScheduler = true;
123  
124    // v6+ may or may not support unaligned mem access depending on the system
125    // configuration.
126    if (!StrictAlign && hasV6Ops() && isTargetDarwin())
127      AllowsUnalignedMem = true;
128  }
129  
130  /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
131  bool
GVIsIndirectSymbol(const GlobalValue * GV,Reloc::Model RelocM) const132  ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
133                                   Reloc::Model RelocM) const {
134    if (RelocM == Reloc::Static)
135      return false;
136  
137    // Materializable GVs (in JIT lazy compilation mode) do not require an extra
138    // load from stub.
139    bool isDecl = GV->hasAvailableExternallyLinkage();
140    if (GV->isDeclaration() && !GV->isMaterializable())
141      isDecl = true;
142  
143    if (!isTargetDarwin()) {
144      // Extra load is needed for all externally visible.
145      if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
146        return false;
147      return true;
148    } else {
149      if (RelocM == Reloc::PIC_) {
150        // If this is a strong reference to a definition, it is definitely not
151        // through a stub.
152        if (!isDecl && !GV->isWeakForLinker())
153          return false;
154  
155        // Unless we have a symbol with hidden visibility, we have to go through a
156        // normal $non_lazy_ptr stub because this symbol might be resolved late.
157        if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
158          return true;
159  
160        // If symbol visibility is hidden, we have a stub for common symbol
161        // references and external declarations.
162        if (isDecl || GV->hasCommonLinkage())
163          // Hidden $non_lazy_ptr reference.
164          return true;
165  
166        return false;
167      } else {
168        // If this is a strong reference to a definition, it is definitely not
169        // through a stub.
170        if (!isDecl && !GV->isWeakForLinker())
171          return false;
172  
173        // Unless we have a symbol with hidden visibility, we have to go through a
174        // normal $non_lazy_ptr stub because this symbol might be resolved late.
175        if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
176          return true;
177      }
178    }
179  
180    return false;
181  }
182  
getMispredictionPenalty() const183  unsigned ARMSubtarget::getMispredictionPenalty() const {
184    // If we have a reasonable estimate of the pipeline depth, then we can
185    // estimate the penalty of a misprediction based on that.
186    if (isCortexA8())
187      return 13;
188    else if (isCortexA9())
189      return 8;
190  
191    // Otherwise, just return a sensible default.
192    return 10;
193  }
194  
computeIssueWidth()195  void ARMSubtarget::computeIssueWidth() {
196    unsigned allStage1Units = 0;
197    for (const InstrItinerary *itin = InstrItins.Itineraries;
198         itin->FirstStage != ~0U; ++itin) {
199      const InstrStage *IS = InstrItins.Stages + itin->FirstStage;
200      allStage1Units |= IS->getUnits();
201    }
202    InstrItins.IssueWidth = 0;
203    while (allStage1Units) {
204      ++InstrItins.IssueWidth;
205      // clear the lowest bit
206      allStage1Units ^= allStage1Units & ~(allStage1Units - 1);
207    }
208    assert(InstrItins.IssueWidth <= 2 && "itinerary bug, too many stage 1 units");
209  }
210  
enablePostRAScheduler(CodeGenOpt::Level OptLevel,TargetSubtargetInfo::AntiDepBreakMode & Mode,RegClassVector & CriticalPathRCs) const211  bool ARMSubtarget::enablePostRAScheduler(
212             CodeGenOpt::Level OptLevel,
213             TargetSubtargetInfo::AntiDepBreakMode& Mode,
214             RegClassVector& CriticalPathRCs) const {
215    Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL;
216    CriticalPathRCs.clear();
217    CriticalPathRCs.push_back(&ARM::GPRRegClass);
218    return PostRAScheduler && OptLevel >= CodeGenOpt::Default;
219  }
220