xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMSubtarget.h (revision ebacd8013fe5f7fdf9f6a5b286f6680dd2891036)
1 //===-- ARMSubtarget.h - Define Subtarget for the ARM ----------*- C++ -*--===//
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 // This file declares the ARM specific subclass of TargetSubtargetInfo.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H
14 #define LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H
15 
16 #include "ARMBaseInstrInfo.h"
17 #include "ARMBaseRegisterInfo.h"
18 #include "ARMConstantPoolValue.h"
19 #include "ARMFrameLowering.h"
20 #include "ARMISelLowering.h"
21 #include "ARMMachineFunctionInfo.h"
22 #include "ARMSelectionDAGInfo.h"
23 #include "llvm/ADT/Triple.h"
24 #include "llvm/Analysis/TargetTransformInfo.h"
25 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
26 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
27 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
28 #include "llvm/CodeGen/MachineFunction.h"
29 #include "llvm/CodeGen/RegisterBankInfo.h"
30 #include "llvm/CodeGen/TargetSubtargetInfo.h"
31 #include "llvm/MC/MCInstrItineraries.h"
32 #include "llvm/MC/MCSchedule.h"
33 #include "llvm/Target/TargetMachine.h"
34 #include "llvm/Target/TargetOptions.h"
35 #include <memory>
36 #include <string>
37 
38 #define GET_SUBTARGETINFO_HEADER
39 #include "ARMGenSubtargetInfo.inc"
40 
41 namespace llvm {
42 
43 class ARMBaseTargetMachine;
44 class GlobalValue;
45 class StringRef;
46 
47 class ARMSubtarget : public ARMGenSubtargetInfo {
48 protected:
49   enum ARMProcFamilyEnum {
50     Others,
51 
52     CortexA12,
53     CortexA15,
54     CortexA17,
55     CortexA32,
56     CortexA35,
57     CortexA5,
58     CortexA53,
59     CortexA55,
60     CortexA57,
61     CortexA7,
62     CortexA72,
63     CortexA73,
64     CortexA75,
65     CortexA76,
66     CortexA77,
67     CortexA78,
68     CortexA78C,
69     CortexA710,
70     CortexA8,
71     CortexA9,
72     CortexM3,
73     CortexM7,
74     CortexR4,
75     CortexR4F,
76     CortexR5,
77     CortexR52,
78     CortexR7,
79     CortexX1,
80     CortexX1C,
81     Exynos,
82     Krait,
83     Kryo,
84     NeoverseN1,
85     NeoverseN2,
86     NeoverseV1,
87     Swift
88   };
89   enum ARMProcClassEnum {
90     None,
91 
92     AClass,
93     MClass,
94     RClass
95   };
96   enum ARMArchEnum {
97     ARMv2,
98     ARMv2a,
99     ARMv3,
100     ARMv3m,
101     ARMv4,
102     ARMv4t,
103     ARMv5,
104     ARMv5t,
105     ARMv5te,
106     ARMv5tej,
107     ARMv6,
108     ARMv6k,
109     ARMv6kz,
110     ARMv6m,
111     ARMv6sm,
112     ARMv6t2,
113     ARMv7a,
114     ARMv7em,
115     ARMv7m,
116     ARMv7r,
117     ARMv7ve,
118     ARMv81a,
119     ARMv82a,
120     ARMv83a,
121     ARMv84a,
122     ARMv85a,
123     ARMv86a,
124     ARMv87a,
125     ARMv88a,
126     ARMv8a,
127     ARMv8mBaseline,
128     ARMv8mMainline,
129     ARMv8r,
130     ARMv81mMainline,
131     ARMv9a,
132     ARMv91a,
133     ARMv92a,
134     ARMv93a,
135   };
136 
137 public:
138   /// What kind of timing do load multiple/store multiple instructions have.
139   enum ARMLdStMultipleTiming {
140     /// Can load/store 2 registers/cycle.
141     DoubleIssue,
142     /// Can load/store 2 registers/cycle, but needs an extra cycle if the access
143     /// is not 64-bit aligned.
144     DoubleIssueCheckUnalignedAccess,
145     /// Can load/store 1 register/cycle.
146     SingleIssue,
147     /// Can load/store 1 register/cycle, but needs an extra cycle for address
148     /// computation and potentially also for register writeback.
149     SingleIssuePlusExtras,
150   };
151 
152 protected:
153 // Bool members corresponding to the SubtargetFeatures defined in tablegen
154 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
155   bool ATTRIBUTE = DEFAULT;
156 #include "ARMGenSubtargetInfo.inc"
157 
158   /// ARMProcFamily - ARM processor family: Cortex-A8, Cortex-A9, and others.
159   ARMProcFamilyEnum ARMProcFamily = Others;
160 
161   /// ARMProcClass - ARM processor class: None, AClass, RClass or MClass.
162   ARMProcClassEnum ARMProcClass = None;
163 
164   /// ARMArch - ARM architecture
165   ARMArchEnum ARMArch = ARMv4t;
166 
167   /// UseMulOps - True if non-microcoded fused integer multiply-add and
168   /// multiply-subtract instructions should be used.
169   bool UseMulOps = false;
170 
171   /// SupportsTailCall - True if the OS supports tail call. The dynamic linker
172   /// must be able to synthesize call stubs for interworking between ARM and
173   /// Thumb.
174   bool SupportsTailCall = false;
175 
176   /// RestrictIT - If true, the subtarget disallows generation of complex IT
177   ///  blocks.
178   bool RestrictIT = false;
179 
180   /// UseSjLjEH - If true, the target uses SjLj exception handling (e.g. iOS).
181   bool UseSjLjEH = false;
182 
183   /// stackAlignment - The minimum alignment known to hold of the stack frame on
184   /// entry to the function and which must be maintained by every function.
185   Align stackAlignment = Align(4);
186 
187   /// CPUString - String name of used CPU.
188   std::string CPUString;
189 
190   unsigned MaxInterleaveFactor = 1;
191 
192   /// Clearance before partial register updates (in number of instructions)
193   unsigned PartialUpdateClearance = 0;
194 
195   /// What kind of timing do load multiple/store multiple have (double issue,
196   /// single issue etc).
197   ARMLdStMultipleTiming LdStMultipleTiming = SingleIssue;
198 
199   /// The adjustment that we need to apply to get the operand latency from the
200   /// operand cycle returned by the itinerary data for pre-ISel operands.
201   int PreISelOperandLatencyAdjustment = 2;
202 
203   /// What alignment is preferred for loop bodies, in log2(bytes).
204   unsigned PrefLoopLogAlignment = 0;
205 
206   /// The cost factor for MVE instructions, representing the multiple beats an
207   // instruction can take. The default is 2, (set in initSubtargetFeatures so
208   // that we can use subtarget features less than 2).
209   unsigned MVEVectorCostFactor = 0;
210 
211   /// OptMinSize - True if we're optimising for minimum code size, equal to
212   /// the function attribute.
213   bool OptMinSize = false;
214 
215   /// IsLittle - The target is Little Endian
216   bool IsLittle;
217 
218   /// TargetTriple - What processor and OS we're targeting.
219   Triple TargetTriple;
220 
221   /// SchedModel - Processor specific instruction costs.
222   MCSchedModel SchedModel;
223 
224   /// Selected instruction itineraries (one entry per itinerary class.)
225   InstrItineraryData InstrItins;
226 
227   /// Options passed via command line that could influence the target
228   const TargetOptions &Options;
229 
230   const ARMBaseTargetMachine &TM;
231 
232 public:
233   /// This constructor initializes the data members to match that
234   /// of the specified triple.
235   ///
236   ARMSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS,
237                const ARMBaseTargetMachine &TM, bool IsLittle,
238                bool MinSize = false);
239 
240   /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size
241   /// that still makes it profitable to inline the call.
242   unsigned getMaxInlineSizeThreshold() const {
243     return 64;
244   }
245 
246   /// getMaxMemcpyTPInlineSizeThreshold - Returns the maximum size
247   /// that still makes it profitable to inline a llvm.memcpy as a Tail
248   /// Predicated loop.
249   /// This threshold should only be used for constant size inputs.
250   unsigned getMaxMemcpyTPInlineSizeThreshold() const { return 128; }
251 
252   /// ParseSubtargetFeatures - Parses features string setting specified
253   /// subtarget options.  Definition of function is auto generated by tblgen.
254   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
255 
256   /// initializeSubtargetDependencies - Initializes using a CPU and feature string
257   /// so that we can use initializer lists for subtarget initialization.
258   ARMSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
259 
260   const ARMSelectionDAGInfo *getSelectionDAGInfo() const override {
261     return &TSInfo;
262   }
263 
264   const ARMBaseInstrInfo *getInstrInfo() const override {
265     return InstrInfo.get();
266   }
267 
268   const ARMTargetLowering *getTargetLowering() const override {
269     return &TLInfo;
270   }
271 
272   const ARMFrameLowering *getFrameLowering() const override {
273     return FrameLowering.get();
274   }
275 
276   const ARMBaseRegisterInfo *getRegisterInfo() const override {
277     return &InstrInfo->getRegisterInfo();
278   }
279 
280   const CallLowering *getCallLowering() const override;
281   InstructionSelector *getInstructionSelector() const override;
282   const LegalizerInfo *getLegalizerInfo() const override;
283   const RegisterBankInfo *getRegBankInfo() const override;
284 
285 private:
286   ARMSelectionDAGInfo TSInfo;
287   // Either Thumb1FrameLowering or ARMFrameLowering.
288   std::unique_ptr<ARMFrameLowering> FrameLowering;
289   // Either Thumb1InstrInfo or Thumb2InstrInfo.
290   std::unique_ptr<ARMBaseInstrInfo> InstrInfo;
291   ARMTargetLowering   TLInfo;
292 
293   /// GlobalISel related APIs.
294   std::unique_ptr<CallLowering> CallLoweringInfo;
295   std::unique_ptr<InstructionSelector> InstSelector;
296   std::unique_ptr<LegalizerInfo> Legalizer;
297   std::unique_ptr<RegisterBankInfo> RegBankInfo;
298 
299   void initializeEnvironment();
300   void initSubtargetFeatures(StringRef CPU, StringRef FS);
301   ARMFrameLowering *initializeFrameLowering(StringRef CPU, StringRef FS);
302 
303   std::bitset<8> CoprocCDE = {};
304 public:
305 // Getters for SubtargetFeatures defined in tablegen
306 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
307   bool GETTER() const { return ATTRIBUTE; }
308 #include "ARMGenSubtargetInfo.inc"
309 
310   void computeIssueWidth();
311 
312   /// @{
313   /// These functions are obsolete, please consider adding subtarget features
314   /// or properties instead of calling them.
315   bool isCortexA5() const { return ARMProcFamily == CortexA5; }
316   bool isCortexA7() const { return ARMProcFamily == CortexA7; }
317   bool isCortexA8() const { return ARMProcFamily == CortexA8; }
318   bool isCortexA9() const { return ARMProcFamily == CortexA9; }
319   bool isCortexA15() const { return ARMProcFamily == CortexA15; }
320   bool isSwift()    const { return ARMProcFamily == Swift; }
321   bool isCortexM3() const { return ARMProcFamily == CortexM3; }
322   bool isCortexM7() const { return ARMProcFamily == CortexM7; }
323   bool isLikeA9() const { return isCortexA9() || isCortexA15() || isKrait(); }
324   bool isCortexR5() const { return ARMProcFamily == CortexR5; }
325   bool isKrait() const { return ARMProcFamily == Krait; }
326   /// @}
327 
328   bool hasARMOps() const { return !NoARM; }
329 
330   bool useNEONForSinglePrecisionFP() const {
331     return hasNEON() && hasNEONForFP();
332   }
333 
334   bool hasVFP2Base() const { return hasVFPv2SP(); }
335   bool hasVFP3Base() const { return hasVFPv3D16SP(); }
336   bool hasVFP4Base() const { return hasVFPv4D16SP(); }
337   bool hasFPARMv8Base() const { return hasFPARMv8D16SP(); }
338 
339   bool hasAnyDataBarrier() const {
340     return HasDataBarrier || (hasV6Ops() && !isThumb());
341   }
342 
343   bool useMulOps() const { return UseMulOps; }
344   bool useFPVMLx() const { return !SlowFPVMLx; }
345   bool useFPVFMx() const {
346     return !isTargetDarwin() && hasVFP4Base() && !SlowFPVFMx;
347   }
348   bool useFPVFMx16() const { return useFPVFMx() && hasFullFP16(); }
349   bool useFPVFMx64() const { return useFPVFMx() && hasFP64(); }
350   bool useSjLjEH() const { return UseSjLjEH; }
351   bool hasBaseDSP() const {
352     if (isThumb())
353       return hasDSP();
354     else
355       return hasV5TEOps();
356   }
357 
358   /// Return true if the CPU supports any kind of instruction fusion.
359   bool hasFusion() const { return hasFuseAES() || hasFuseLiterals(); }
360 
361   const Triple &getTargetTriple() const { return TargetTriple; }
362 
363   bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
364   bool isTargetIOS() const { return TargetTriple.isiOS(); }
365   bool isTargetWatchOS() const { return TargetTriple.isWatchOS(); }
366   bool isTargetWatchABI() const { return TargetTriple.isWatchABI(); }
367   bool isTargetDriverKit() const { return TargetTriple.isDriverKit(); }
368   bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
369   bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
370   bool isTargetNetBSD() const { return TargetTriple.isOSNetBSD(); }
371   bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
372 
373   bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
374   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
375   bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
376 
377   // ARM EABI is the bare-metal EABI described in ARM ABI documents and
378   // can be accessed via -target arm-none-eabi. This is NOT GNUEABI.
379   // FIXME: Add a flag for bare-metal for that target and set Triple::EABI
380   // even for GNUEABI, so we can make a distinction here and still conform to
381   // the EABI on GNU (and Android) mode. This requires change in Clang, too.
382   // FIXME: The Darwin exception is temporary, while we move users to
383   // "*-*-*-macho" triples as quickly as possible.
384   bool isTargetAEABI() const {
385     return (TargetTriple.getEnvironment() == Triple::EABI ||
386             TargetTriple.getEnvironment() == Triple::EABIHF) &&
387            !isTargetDarwin() && !isTargetWindows();
388   }
389   bool isTargetGNUAEABI() const {
390     return (TargetTriple.getEnvironment() == Triple::GNUEABI ||
391             TargetTriple.getEnvironment() == Triple::GNUEABIHF) &&
392            !isTargetDarwin() && !isTargetWindows();
393   }
394   bool isTargetMuslAEABI() const {
395     return (TargetTriple.getEnvironment() == Triple::MuslEABI ||
396             TargetTriple.getEnvironment() == Triple::MuslEABIHF) &&
397            !isTargetDarwin() && !isTargetWindows();
398   }
399 
400   // ARM Targets that support EHABI exception handling standard
401   // Darwin uses SjLj. Other targets might need more checks.
402   bool isTargetEHABICompatible() const {
403     return TargetTriple.isTargetEHABICompatible();
404   }
405 
406   bool isTargetHardFloat() const;
407 
408   bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
409 
410   bool isXRaySupported() const override;
411 
412   bool isAPCS_ABI() const;
413   bool isAAPCS_ABI() const;
414   bool isAAPCS16_ABI() const;
415 
416   bool isROPI() const;
417   bool isRWPI() const;
418 
419   bool useMachineScheduler() const { return UseMISched; }
420   bool useMachinePipeliner() const { return UseMIPipeliner; }
421   bool hasMinSize() const { return OptMinSize; }
422   bool isThumb1Only() const { return isThumb() && !hasThumb2(); }
423   bool isThumb2() const { return isThumb() && hasThumb2(); }
424   bool isMClass() const { return ARMProcClass == MClass; }
425   bool isRClass() const { return ARMProcClass == RClass; }
426   bool isAClass() const { return ARMProcClass == AClass; }
427 
428   bool isR9Reserved() const {
429     return isTargetMachO() ? (ReserveR9 || !HasV6Ops) : ReserveR9;
430   }
431 
432   MCPhysReg getFramePointerReg() const {
433     if (isTargetDarwin() ||
434         (!isTargetWindows() && isThumb() && !createAAPCSFrameChain()))
435       return ARM::R7;
436     return ARM::R11;
437   }
438 
439   /// Returns true if the frame setup is split into two separate pushes (first
440   /// r0-r7,lr then r8-r11), principally so that the frame pointer is adjacent
441   /// to lr. This is always required on Thumb1-only targets, as the push and
442   /// pop instructions can't access the high registers.
443   bool splitFramePushPop(const MachineFunction &MF) const {
444     if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress())
445       return true;
446     return (getFramePointerReg() == ARM::R7 &&
447             MF.getTarget().Options.DisableFramePointerElim(MF)) ||
448            isThumb1Only();
449   }
450 
451   bool splitFramePointerPush(const MachineFunction &MF) const;
452 
453   bool useStride4VFPs() const;
454 
455   bool useMovt() const;
456 
457   bool supportsTailCall() const { return SupportsTailCall; }
458 
459   bool allowsUnalignedMem() const { return !StrictAlign; }
460 
461   bool restrictIT() const { return RestrictIT; }
462 
463   const std::string & getCPUString() const { return CPUString; }
464 
465   bool isLittle() const { return IsLittle; }
466 
467   unsigned getMispredictionPenalty() const;
468 
469   /// Returns true if machine scheduler should be enabled.
470   bool enableMachineScheduler() const override;
471 
472   /// Returns true if machine pipeliner should be enabled.
473   bool enableMachinePipeliner() const override;
474   bool useDFAforSMS() const override;
475 
476   /// True for some subtargets at > -O0.
477   bool enablePostRAScheduler() const override;
478 
479   /// True for some subtargets at > -O0.
480   bool enablePostRAMachineScheduler() const override;
481 
482   /// Check whether this subtarget wants to use subregister liveness.
483   bool enableSubRegLiveness() const override;
484 
485   /// Enable use of alias analysis during code generation (during MI
486   /// scheduling, DAGCombine, etc.).
487   bool useAA() const override { return true; }
488 
489   /// getInstrItins - Return the instruction itineraries based on subtarget
490   /// selection.
491   const InstrItineraryData *getInstrItineraryData() const override {
492     return &InstrItins;
493   }
494 
495   /// getStackAlignment - Returns the minimum alignment known to hold of the
496   /// stack frame on entry to the function and which must be maintained by every
497   /// function for this subtarget.
498   Align getStackAlignment() const { return stackAlignment; }
499 
500   unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; }
501 
502   unsigned getPartialUpdateClearance() const { return PartialUpdateClearance; }
503 
504   ARMLdStMultipleTiming getLdStMultipleTiming() const {
505     return LdStMultipleTiming;
506   }
507 
508   int getPreISelOperandLatencyAdjustment() const {
509     return PreISelOperandLatencyAdjustment;
510   }
511 
512   /// True if the GV will be accessed via an indirect symbol.
513   bool isGVIndirectSymbol(const GlobalValue *GV) const;
514 
515   /// Returns the constant pool modifier needed to access the GV.
516   bool isGVInGOT(const GlobalValue *GV) const;
517 
518   /// True if fast-isel is used.
519   bool useFastISel() const;
520 
521   /// Returns the correct return opcode for the current feature set.
522   /// Use BX if available to allow mixing thumb/arm code, but fall back
523   /// to plain mov pc,lr on ARMv4.
524   unsigned getReturnOpcode() const {
525     if (isThumb())
526       return ARM::tBX_RET;
527     if (hasV4TOps())
528       return ARM::BX_RET;
529     return ARM::MOVPCLR;
530   }
531 
532   /// Allow movt+movw for PIC global address calculation.
533   /// ELF does not have GOT relocations for movt+movw.
534   /// ROPI does not use GOT.
535   bool allowPositionIndependentMovt() const {
536     return isROPI() || !isTargetELF();
537   }
538 
539   unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; }
540 
541   unsigned
542   getMVEVectorCostFactor(TargetTransformInfo::TargetCostKind CostKind) const {
543     if (CostKind == TargetTransformInfo::TCK_CodeSize)
544       return 1;
545     return MVEVectorCostFactor;
546   }
547 
548   bool ignoreCSRForAllocationOrder(const MachineFunction &MF,
549                                    unsigned PhysReg) const override;
550   unsigned getGPRAllocationOrder(const MachineFunction &MF) const;
551 };
552 
553 } // end namespace llvm
554 
555 #endif  // LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H
556