1 //===-- ARMSubtarget.cpp - ARM Subtarget Information ------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the ARM specific subclass of TargetSubtargetInfo.
12 //===----------------------------------------------------------------------===//
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"
21 #define GET_SUBTARGETINFO_ENUM
22 #define GET_SUBTARGETINFO_MC_DESC
23 #define GET_SUBTARGETINFO_TARGET_DESC
24 #define GET_SUBTARGETINFO_CTOR
25 #include "ARMGenSubtargetInfo.inc"
30 ReserveR9("arm-reserve-r9", cl::Hidden
,
31 cl::desc("Reserve R9, making it unavailable as GPR"));
34 DarwinUseMOVT("arm-darwin-use-movt", cl::init(true), cl::Hidden
);
37 StrictAlign("arm-strict-align", cl::Hidden
,
38 cl::desc("Disallow all unaligned memory accesses"));
40 ARMSubtarget::ARMSubtarget(const std::string
&TT
, const std::string
&CPU
,
41 const std::string
&FS
)
42 : ARMGenSubtargetInfo(TT
, CPU
, FS
)
43 , ARMProcFamily(Others
)
53 , UseNEONForSinglePrecisionFP(false)
55 , HasVMLxForwarding(false)
60 , PostRAScheduler(false)
61 , IsR9Reserved(ReserveR9
)
65 , HasHardwareDivide(false)
66 , HasT2ExtractPack(false)
67 , HasDataBarrier(false)
68 , Pref32BitThumb(false)
69 , AvoidCPSRPartialUpdate(false)
70 , HasMPExtension(false)
72 , AllowsUnalignedMem(false)
77 , TargetABI(ARM_ABI_APCS
) {
78 // Determine default and user specified characteristics
79 if (CPUString
.empty())
80 CPUString
= "generic";
82 // Insert the architecture feature derived from the target triple into the
83 // feature string. This is important for setting features that are implied
84 // based on the architecture version.
85 std::string ArchFS
= ARM_MC::ParseARMTriple(TT
);
88 ArchFS
= ArchFS
+ "," + FS
;
92 ParseSubtargetFeatures(CPUString
, ArchFS
);
94 // Thumb2 implies at least V6T2. FIXME: Fix tests to explicitly specify a
95 // ARM version or CPU and then remove this.
96 if (!HasV6T2Ops
&& hasThumb2())
97 HasV4TOps
= HasV5TOps
= HasV5TEOps
= HasV6Ops
= HasV6T2Ops
= true;
99 // Initialize scheduling itinerary for the specified CPU.
100 InstrItins
= getInstrItineraryForCPU(CPUString
);
102 // After parsing Itineraries, set ItinData.IssueWidth.
105 if (TT
.find("eabi") != std::string::npos
)
106 TargetABI
= ARM_ABI_AAPCS
;
111 if (!isTargetDarwin())
112 UseMovt
= hasV6T2Ops();
114 IsR9Reserved
= ReserveR9
| !HasV6Ops
;
115 UseMovt
= DarwinUseMOVT
&& hasV6T2Ops();
118 if (!isThumb() || hasThumb2())
119 PostRAScheduler
= true;
121 // v6+ may or may not support unaligned mem access depending on the system
123 if (!StrictAlign
&& hasV6Ops() && isTargetDarwin())
124 AllowsUnalignedMem
= true;
127 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
129 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue
*GV
,
130 Reloc::Model RelocM
) const {
131 if (RelocM
== Reloc::Static
)
134 // Materializable GVs (in JIT lazy compilation mode) do not require an extra
136 bool isDecl
= GV
->hasAvailableExternallyLinkage();
137 if (GV
->isDeclaration() && !GV
->isMaterializable())
140 if (!isTargetDarwin()) {
141 // Extra load is needed for all externally visible.
142 if (GV
->hasLocalLinkage() || GV
->hasHiddenVisibility())
146 if (RelocM
== Reloc::PIC_
) {
147 // If this is a strong reference to a definition, it is definitely not
149 if (!isDecl
&& !GV
->isWeakForLinker())
152 // Unless we have a symbol with hidden visibility, we have to go through a
153 // normal $non_lazy_ptr stub because this symbol might be resolved late.
154 if (!GV
->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference.
157 // If symbol visibility is hidden, we have a stub for common symbol
158 // references and external declarations.
159 if (isDecl
|| GV
->hasCommonLinkage())
160 // Hidden $non_lazy_ptr reference.
165 // If this is a strong reference to a definition, it is definitely not
167 if (!isDecl
&& !GV
->isWeakForLinker())
170 // Unless we have a symbol with hidden visibility, we have to go through a
171 // normal $non_lazy_ptr stub because this symbol might be resolved late.
172 if (!GV
->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference.
180 unsigned ARMSubtarget::getMispredictionPenalty() const {
181 // If we have a reasonable estimate of the pipeline depth, then we can
182 // estimate the penalty of a misprediction based on that.
185 else if (isCortexA9())
188 // Otherwise, just return a sensible default.
192 void ARMSubtarget::computeIssueWidth() {
193 unsigned allStage1Units
= 0;
194 for (const InstrItinerary
*itin
= InstrItins
.Itineraries
;
195 itin
->FirstStage
!= ~0U; ++itin
) {
196 const InstrStage
*IS
= InstrItins
.Stages
+ itin
->FirstStage
;
197 allStage1Units
|= IS
->getUnits();
199 InstrItins
.IssueWidth
= 0;
200 while (allStage1Units
) {
201 ++InstrItins
.IssueWidth
;
202 // clear the lowest bit
203 allStage1Units
^= allStage1Units
& ~(allStage1Units
- 1);
205 assert(InstrItins
.IssueWidth
<= 2 && "itinerary bug, too many stage 1 units");
208 bool ARMSubtarget::enablePostRAScheduler(
209 CodeGenOpt::Level OptLevel
,
210 TargetSubtargetInfo::AntiDepBreakMode
& Mode
,
211 RegClassVector
& CriticalPathRCs
) const {
212 Mode
= TargetSubtargetInfo::ANTIDEP_CRITICAL
;
213 CriticalPathRCs
.clear();
214 CriticalPathRCs
.push_back(&ARM::GPRRegClass
);
215 return PostRAScheduler
&& OptLevel
>= CodeGenOpt::Default
;