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