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/Analysis/TargetTransformInfo.h"
24 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
25 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
26 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
27 #include "llvm/CodeGen/MachineFunction.h"
28 #include "llvm/CodeGen/RegisterBankInfo.h"
29 #include "llvm/CodeGen/TargetSubtargetInfo.h"
30 #include "llvm/MC/MCInstrItineraries.h"
31 #include "llvm/MC/MCSchedule.h"
32 #include "llvm/Target/TargetMachine.h"
33 #include "llvm/Target/TargetOptions.h"
34 #include "llvm/TargetParser/Triple.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   /// @{
309   /// These functions are obsolete, please consider adding subtarget features
310   /// or properties instead of calling them.
311   bool isCortexA5() const { return ARMProcFamily == CortexA5; }
312   bool isCortexA7() const { return ARMProcFamily == CortexA7; }
313   bool isCortexA8() const { return ARMProcFamily == CortexA8; }
314   bool isCortexA9() const { return ARMProcFamily == CortexA9; }
315   bool isCortexA15() const { return ARMProcFamily == CortexA15; }
316   bool isSwift()    const { return ARMProcFamily == Swift; }
317   bool isCortexM3() const { return ARMProcFamily == CortexM3; }
318   bool isCortexM7() const { return ARMProcFamily == CortexM7; }
319   bool isLikeA9() const { return isCortexA9() || isCortexA15() || isKrait(); }
320   bool isCortexR5() const { return ARMProcFamily == CortexR5; }
321   bool isKrait() const { return ARMProcFamily == Krait; }
322   /// @}
323 
324   bool hasARMOps() const { return !NoARM; }
325 
326   bool useNEONForSinglePrecisionFP() const {
327     return hasNEON() && hasNEONForFP();
328   }
329 
330   bool hasVFP2Base() const { return hasVFPv2SP(); }
331   bool hasVFP3Base() const { return hasVFPv3D16SP(); }
332   bool hasVFP4Base() const { return hasVFPv4D16SP(); }
333   bool hasFPARMv8Base() const { return hasFPARMv8D16SP(); }
334 
335   bool hasAnyDataBarrier() const {
336     return HasDataBarrier || (hasV6Ops() && !isThumb());
337   }
338 
339   bool useMulOps() const { return UseMulOps; }
340   bool useFPVMLx() const { return !SlowFPVMLx; }
341   bool useFPVFMx() const {
342     return !isTargetDarwin() && hasVFP4Base() && !SlowFPVFMx;
343   }
344   bool useFPVFMx16() const { return useFPVFMx() && hasFullFP16(); }
345   bool useFPVFMx64() const { return useFPVFMx() && hasFP64(); }
346   bool useSjLjEH() const { return UseSjLjEH; }
347   bool hasBaseDSP() const {
348     if (isThumb())
349       return hasThumb2() && hasDSP();
350     else
351       return hasV5TEOps();
352   }
353 
354   /// Return true if the CPU supports any kind of instruction fusion.
355   bool hasFusion() const { return hasFuseAES() || hasFuseLiterals(); }
356 
357   const Triple &getTargetTriple() const { return TargetTriple; }
358 
359   bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
360   bool isTargetIOS() const { return TargetTriple.isiOS(); }
361   bool isTargetWatchOS() const { return TargetTriple.isWatchOS(); }
362   bool isTargetWatchABI() const { return TargetTriple.isWatchABI(); }
363   bool isTargetDriverKit() const { return TargetTriple.isDriverKit(); }
364   bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
365   bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
366   bool isTargetNetBSD() const { return TargetTriple.isOSNetBSD(); }
367   bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
368 
369   bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
370   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
371   bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
372 
373   // ARM EABI is the bare-metal EABI described in ARM ABI documents and
374   // can be accessed via -target arm-none-eabi. This is NOT GNUEABI.
375   // FIXME: Add a flag for bare-metal for that target and set Triple::EABI
376   // even for GNUEABI, so we can make a distinction here and still conform to
377   // the EABI on GNU (and Android) mode. This requires change in Clang, too.
378   // FIXME: The Darwin exception is temporary, while we move users to
379   // "*-*-*-macho" triples as quickly as possible.
380   bool isTargetAEABI() const {
381     return (TargetTriple.getEnvironment() == Triple::EABI ||
382             TargetTriple.getEnvironment() == Triple::EABIHF) &&
383            !isTargetDarwin() && !isTargetWindows();
384   }
385   bool isTargetGNUAEABI() const {
386     return (TargetTriple.getEnvironment() == Triple::GNUEABI ||
387             TargetTriple.getEnvironment() == Triple::GNUEABIHF) &&
388            !isTargetDarwin() && !isTargetWindows();
389   }
390   bool isTargetMuslAEABI() const {
391     return (TargetTriple.getEnvironment() == Triple::MuslEABI ||
392             TargetTriple.getEnvironment() == Triple::MuslEABIHF ||
393             TargetTriple.getEnvironment() == Triple::OpenHOS) &&
394            !isTargetDarwin() && !isTargetWindows();
395   }
396 
397   // ARM Targets that support EHABI exception handling standard
398   // Darwin uses SjLj. Other targets might need more checks.
399   bool isTargetEHABICompatible() const {
400     return TargetTriple.isTargetEHABICompatible();
401   }
402 
403   bool isTargetHardFloat() const;
404 
405   bool isReadTPSoft() const {
406     return !(isReadTPTPIDRURW() || isReadTPTPIDRURO() || isReadTPTPIDRPRW());
407   }
408 
409   bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
410 
411   bool isXRaySupported() const override;
412 
413   bool isAPCS_ABI() const;
414   bool isAAPCS_ABI() const;
415   bool isAAPCS16_ABI() const;
416 
417   bool isROPI() const;
418   bool isRWPI() const;
419 
420   bool useMachineScheduler() const { return UseMISched; }
421   bool useMachinePipeliner() const { return UseMIPipeliner; }
422   bool hasMinSize() const { return OptMinSize; }
423   bool isThumb1Only() const { return isThumb() && !hasThumb2(); }
424   bool isThumb2() const { return isThumb() && hasThumb2(); }
425   bool isMClass() const { return ARMProcClass == MClass; }
426   bool isRClass() const { return ARMProcClass == RClass; }
427   bool isAClass() const { return ARMProcClass == AClass; }
428 
429   bool isR9Reserved() const {
430     return isTargetMachO() ? (ReserveR9 || !HasV6Ops) : ReserveR9;
431   }
432 
433   MCPhysReg getFramePointerReg() const {
434     if (isTargetDarwin() ||
435         (!isTargetWindows() && isThumb() && !createAAPCSFrameChain()))
436       return ARM::R7;
437     return ARM::R11;
438   }
439 
440   /// Returns true if the frame setup is split into two separate pushes (first
441   /// r0-r7,lr then r8-r11), principally so that the frame pointer is adjacent
442   /// to lr. This is always required on Thumb1-only targets, as the push and
443   /// pop instructions can't access the high registers.
444   bool splitFramePushPop(const MachineFunction &MF) const {
445     if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress())
446       return true;
447     return (getFramePointerReg() == ARM::R7 &&
448             MF.getTarget().Options.DisableFramePointerElim(MF)) ||
449            isThumb1Only();
450   }
451 
452   bool splitFramePointerPush(const MachineFunction &MF) const;
453 
454   bool useStride4VFPs() const;
455 
456   bool useMovt() const;
457 
458   bool supportsTailCall() const { return SupportsTailCall; }
459 
460   bool allowsUnalignedMem() const { return !StrictAlign; }
461 
462   bool restrictIT() const { return RestrictIT; }
463 
464   const std::string & getCPUString() const { return CPUString; }
465 
466   bool isLittle() const { return IsLittle; }
467 
468   unsigned getMispredictionPenalty() const;
469 
470   /// Returns true if machine scheduler should be enabled.
471   bool enableMachineScheduler() const override;
472 
473   /// Returns true if machine pipeliner should be enabled.
474   bool enableMachinePipeliner() const override;
475   bool useDFAforSMS() const override;
476 
477   /// True for some subtargets at > -O0.
478   bool enablePostRAScheduler() const override;
479 
480   /// True for some subtargets at > -O0.
481   bool enablePostRAMachineScheduler() const override;
482 
483   /// Check whether this subtarget wants to use subregister liveness.
484   bool enableSubRegLiveness() const override;
485 
486   /// Enable use of alias analysis during code generation (during MI
487   /// scheduling, DAGCombine, etc.).
488   bool useAA() const override { return true; }
489 
490   /// getInstrItins - Return the instruction itineraries based on subtarget
491   /// selection.
492   const InstrItineraryData *getInstrItineraryData() const override {
493     return &InstrItins;
494   }
495 
496   /// getStackAlignment - Returns the minimum alignment known to hold of the
497   /// stack frame on entry to the function and which must be maintained by every
498   /// function for this subtarget.
499   Align getStackAlignment() const { return stackAlignment; }
500 
501   // Returns the required alignment for LDRD/STRD instructions
502   Align getDualLoadStoreAlignment() const {
503     return Align(hasV7Ops() || allowsUnalignedMem() ? 4 : 8);
504   }
505 
506   unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; }
507 
508   unsigned getPartialUpdateClearance() const { return PartialUpdateClearance; }
509 
510   ARMLdStMultipleTiming getLdStMultipleTiming() const {
511     return LdStMultipleTiming;
512   }
513 
514   int getPreISelOperandLatencyAdjustment() const {
515     return PreISelOperandLatencyAdjustment;
516   }
517 
518   /// True if the GV will be accessed via an indirect symbol.
519   bool isGVIndirectSymbol(const GlobalValue *GV) const;
520 
521   /// Returns the constant pool modifier needed to access the GV.
522   bool isGVInGOT(const GlobalValue *GV) const;
523 
524   /// True if fast-isel is used.
525   bool useFastISel() const;
526 
527   /// Returns the correct return opcode for the current feature set.
528   /// Use BX if available to allow mixing thumb/arm code, but fall back
529   /// to plain mov pc,lr on ARMv4.
530   unsigned getReturnOpcode() const {
531     if (isThumb())
532       return ARM::tBX_RET;
533     if (hasV4TOps())
534       return ARM::BX_RET;
535     return ARM::MOVPCLR;
536   }
537 
538   /// Allow movt+movw for PIC global address calculation.
539   /// ELF does not have GOT relocations for movt+movw.
540   /// ROPI does not use GOT.
541   bool allowPositionIndependentMovt() const {
542     return isROPI() || !isTargetELF();
543   }
544 
545   unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; }
546 
547   unsigned
548   getMVEVectorCostFactor(TargetTransformInfo::TargetCostKind CostKind) const {
549     if (CostKind == TargetTransformInfo::TCK_CodeSize)
550       return 1;
551     return MVEVectorCostFactor;
552   }
553 
554   bool ignoreCSRForAllocationOrder(const MachineFunction &MF,
555                                    unsigned PhysReg) const override;
556   unsigned getGPRAllocationOrder(const MachineFunction &MF) const;
557 };
558 
559 } // end namespace llvm
560 
561 #endif  // LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H
562