xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- SystemZSubtarget.cpp - SystemZ subtarget information --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "SystemZSubtarget.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
11*06c3fb27SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
120b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
135ffd83dbSDimitry Andric #include "llvm/Target/TargetMachine.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric using namespace llvm;
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #define DEBUG_TYPE "systemz-subtarget"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC
200b57cec5SDimitry Andric #define GET_SUBTARGETINFO_CTOR
210b57cec5SDimitry Andric #include "SystemZGenSubtargetInfo.inc"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric static cl::opt<bool> UseSubRegLiveness(
240b57cec5SDimitry Andric     "systemz-subreg-liveness",
250b57cec5SDimitry Andric     cl::desc("Enable subregister liveness tracking for SystemZ (experimental)"),
260b57cec5SDimitry Andric     cl::Hidden);
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric // Pin the vtable to this file.
290b57cec5SDimitry Andric void SystemZSubtarget::anchor() {}
300b57cec5SDimitry Andric 
3181ad6265SDimitry Andric SystemZSubtarget &SystemZSubtarget::initializeSubtargetDependencies(
3281ad6265SDimitry Andric     StringRef CPU, StringRef TuneCPU, StringRef FS) {
3381ad6265SDimitry Andric   if (CPU.empty())
3481ad6265SDimitry Andric     CPU = "generic";
3581ad6265SDimitry Andric   if (TuneCPU.empty())
3681ad6265SDimitry Andric     TuneCPU = CPU;
370b57cec5SDimitry Andric   // Parse features string.
3881ad6265SDimitry Andric   ParseSubtargetFeatures(CPU, TuneCPU, FS);
395ffd83dbSDimitry Andric 
405ffd83dbSDimitry Andric   // -msoft-float implies -mno-vx.
415ffd83dbSDimitry Andric   if (HasSoftFloat)
425ffd83dbSDimitry Andric     HasVector = false;
435ffd83dbSDimitry Andric 
44e8d8bef9SDimitry Andric   // -mno-vx implicitly disables all vector-related features.
45e8d8bef9SDimitry Andric   if (!HasVector) {
46e8d8bef9SDimitry Andric     HasVectorEnhancements1 = false;
47e8d8bef9SDimitry Andric     HasVectorEnhancements2 = false;
48e8d8bef9SDimitry Andric     HasVectorPackedDecimal = false;
49e8d8bef9SDimitry Andric     HasVectorPackedDecimalEnhancement = false;
50fe6060f1SDimitry Andric     HasVectorPackedDecimalEnhancement2 = false;
51e8d8bef9SDimitry Andric   }
52e8d8bef9SDimitry Andric 
530b57cec5SDimitry Andric   return *this;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
56fe6060f1SDimitry Andric SystemZCallingConventionRegisters *
57fe6060f1SDimitry Andric SystemZSubtarget::initializeSpecialRegisters() {
58fe6060f1SDimitry Andric   if (isTargetXPLINK64())
59fe6060f1SDimitry Andric     return new SystemZXPLINK64Registers;
60fe6060f1SDimitry Andric   else if (isTargetELF())
61fe6060f1SDimitry Andric     return new SystemZELFRegisters;
62fe6060f1SDimitry Andric   else {
63fe6060f1SDimitry Andric     llvm_unreachable("Invalid Calling Convention. Cannot initialize Special "
64fe6060f1SDimitry Andric                      "Call Registers!");
65fe6060f1SDimitry Andric   }
66fe6060f1SDimitry Andric }
67fe6060f1SDimitry Andric 
680b57cec5SDimitry Andric SystemZSubtarget::SystemZSubtarget(const Triple &TT, const std::string &CPU,
6981ad6265SDimitry Andric                                    const std::string &TuneCPU,
700b57cec5SDimitry Andric                                    const std::string &FS,
710b57cec5SDimitry Andric                                    const TargetMachine &TM)
72bdd1243dSDimitry Andric     : SystemZGenSubtargetInfo(TT, CPU, TuneCPU, FS), TargetTriple(TT),
73fe6060f1SDimitry Andric       SpecialRegisters(initializeSpecialRegisters()),
7481ad6265SDimitry Andric       InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
7581ad6265SDimitry Andric       TLInfo(TM, *this), FrameLowering(SystemZFrameLowering::create(*this)) {}
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric bool SystemZSubtarget::enableSubRegLiveness() const {
780b57cec5SDimitry Andric   return UseSubRegLiveness;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
81*06c3fb27SDimitry Andric bool SystemZSubtarget::isAddressedViaADA(const GlobalValue *GV) const {
82*06c3fb27SDimitry Andric   if (const auto *GO = dyn_cast<GlobalObject>(GV)) {
83*06c3fb27SDimitry Andric     // A R/O variable is placed in code section. If the R/O variable has as
84*06c3fb27SDimitry Andric     // least two byte alignment, then generated code can use relative
85*06c3fb27SDimitry Andric     // instructions to address the variable. Otherwise, use the ADA to address
86*06c3fb27SDimitry Andric     // the variable.
87*06c3fb27SDimitry Andric     if (GO->getAlignment() & 0x1) {
88*06c3fb27SDimitry Andric       return true;
89*06c3fb27SDimitry Andric     }
90*06c3fb27SDimitry Andric 
91*06c3fb27SDimitry Andric     // getKindForGlobal only works with definitions
92*06c3fb27SDimitry Andric     if (GO->isDeclaration()) {
93*06c3fb27SDimitry Andric       return true;
94*06c3fb27SDimitry Andric     }
95*06c3fb27SDimitry Andric 
96*06c3fb27SDimitry Andric     // check AvailableExternallyLinkage here as getKindForGlobal() asserts
97*06c3fb27SDimitry Andric     if (GO->hasAvailableExternallyLinkage()) {
98*06c3fb27SDimitry Andric       return true;
99*06c3fb27SDimitry Andric     }
100*06c3fb27SDimitry Andric 
101*06c3fb27SDimitry Andric     SectionKind GOKind = TargetLoweringObjectFile::getKindForGlobal(
102*06c3fb27SDimitry Andric         GO, TLInfo.getTargetMachine());
103*06c3fb27SDimitry Andric     if (!GOKind.isReadOnly()) {
104*06c3fb27SDimitry Andric       return true;
105*06c3fb27SDimitry Andric     }
106*06c3fb27SDimitry Andric 
107*06c3fb27SDimitry Andric     return false; // R/O variable with multiple of 2 byte alignment
108*06c3fb27SDimitry Andric   }
109*06c3fb27SDimitry Andric   return true;
110*06c3fb27SDimitry Andric }
111*06c3fb27SDimitry Andric 
1120b57cec5SDimitry Andric bool SystemZSubtarget::isPC32DBLSymbol(const GlobalValue *GV,
1130b57cec5SDimitry Andric                                        CodeModel::Model CM) const {
114*06c3fb27SDimitry Andric   if (isTargetzOS())
115*06c3fb27SDimitry Andric     return !isAddressedViaADA(GV);
116*06c3fb27SDimitry Andric 
1175ffd83dbSDimitry Andric   // PC32DBL accesses require the low bit to be clear.
1185ffd83dbSDimitry Andric   //
1195ffd83dbSDimitry Andric   // FIXME: Explicitly check for functions: the datalayout is currently
1205ffd83dbSDimitry Andric   // missing information about function pointers.
1215ffd83dbSDimitry Andric   const DataLayout &DL = GV->getParent()->getDataLayout();
1225ffd83dbSDimitry Andric   if (GV->getPointerAlignment(DL) == 1 && !GV->getValueType()->isFunctionTy())
1230b57cec5SDimitry Andric     return false;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   // For the small model, all locally-binding symbols are in range.
1260b57cec5SDimitry Andric   if (CM == CodeModel::Small)
1270b57cec5SDimitry Andric     return TLInfo.getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV);
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   // For Medium and above, assume that the symbol is not within the 4GB range.
1300b57cec5SDimitry Andric   // Taking the address of locally-defined text would be OK, but that
1310b57cec5SDimitry Andric   // case isn't easy to detect.
1320b57cec5SDimitry Andric   return false;
1330b57cec5SDimitry Andric }
134