xref: /src/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
159d6cff9SDimitry Andric //===-- SystemZSubtarget.cpp - SystemZ subtarget information --------------===//
259d6cff9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659d6cff9SDimitry Andric //
759d6cff9SDimitry Andric //===----------------------------------------------------------------------===//
859d6cff9SDimitry Andric 
959d6cff9SDimitry Andric #include "SystemZSubtarget.h"
105ca98fd9SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
117fa27ce4SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
1259d6cff9SDimitry Andric #include "llvm/IR/GlobalValue.h"
13cfca06d7SDimitry Andric #include "llvm/Target/TargetMachine.h"
145ca98fd9SDimitry Andric 
155ca98fd9SDimitry Andric using namespace llvm;
165ca98fd9SDimitry Andric 
175ca98fd9SDimitry Andric #define DEBUG_TYPE "systemz-subtarget"
1859d6cff9SDimitry Andric 
1959d6cff9SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC
2059d6cff9SDimitry Andric #define GET_SUBTARGETINFO_CTOR
2159d6cff9SDimitry Andric #include "SystemZGenSubtargetInfo.inc"
2259d6cff9SDimitry Andric 
23d8e91e46SDimitry Andric static cl::opt<bool> UseSubRegLiveness(
24d8e91e46SDimitry Andric     "systemz-subreg-liveness",
25d8e91e46SDimitry Andric     cl::desc("Enable subregister liveness tracking for SystemZ (experimental)"),
26d8e91e46SDimitry Andric     cl::Hidden);
27d8e91e46SDimitry Andric 
285ca98fd9SDimitry Andric // Pin the vtable to this file.
anchor()29f8af5cf6SDimitry Andric void SystemZSubtarget::anchor() {}
30f8af5cf6SDimitry Andric 
initializeSubtargetDependencies(StringRef CPU,StringRef TuneCPU,StringRef FS)31145449b1SDimitry Andric SystemZSubtarget &SystemZSubtarget::initializeSubtargetDependencies(
32145449b1SDimitry Andric     StringRef CPU, StringRef TuneCPU, StringRef FS) {
33145449b1SDimitry Andric   if (CPU.empty())
34145449b1SDimitry Andric     CPU = "generic";
35145449b1SDimitry Andric   if (TuneCPU.empty())
36145449b1SDimitry Andric     TuneCPU = CPU;
3759d6cff9SDimitry Andric   // Parse features string.
38145449b1SDimitry Andric   ParseSubtargetFeatures(CPU, TuneCPU, FS);
39cfca06d7SDimitry Andric 
40cfca06d7SDimitry Andric   // -msoft-float implies -mno-vx.
41cfca06d7SDimitry Andric   if (HasSoftFloat)
42cfca06d7SDimitry Andric     HasVector = false;
43cfca06d7SDimitry Andric 
44b60736ecSDimitry Andric   // -mno-vx implicitly disables all vector-related features.
45b60736ecSDimitry Andric   if (!HasVector) {
46b60736ecSDimitry Andric     HasVectorEnhancements1 = false;
47b60736ecSDimitry Andric     HasVectorEnhancements2 = false;
48b60736ecSDimitry Andric     HasVectorPackedDecimal = false;
49b60736ecSDimitry Andric     HasVectorPackedDecimalEnhancement = false;
50344a3780SDimitry Andric     HasVectorPackedDecimalEnhancement2 = false;
51b60736ecSDimitry Andric   }
52b60736ecSDimitry Andric 
535ca98fd9SDimitry Andric   return *this;
5459d6cff9SDimitry Andric }
5559d6cff9SDimitry Andric 
56344a3780SDimitry Andric SystemZCallingConventionRegisters *
initializeSpecialRegisters()57344a3780SDimitry Andric SystemZSubtarget::initializeSpecialRegisters() {
58344a3780SDimitry Andric   if (isTargetXPLINK64())
59344a3780SDimitry Andric     return new SystemZXPLINK64Registers;
60344a3780SDimitry Andric   else if (isTargetELF())
61344a3780SDimitry Andric     return new SystemZELFRegisters;
62344a3780SDimitry Andric   llvm_unreachable("Invalid Calling Convention. Cannot initialize Special "
63344a3780SDimitry Andric                    "Call Registers!");
64344a3780SDimitry Andric }
65344a3780SDimitry Andric 
SystemZSubtarget(const Triple & TT,const std::string & CPU,const std::string & TuneCPU,const std::string & FS,const TargetMachine & TM)663a0822f0SDimitry Andric SystemZSubtarget::SystemZSubtarget(const Triple &TT, const std::string &CPU,
67145449b1SDimitry Andric                                    const std::string &TuneCPU,
685ca98fd9SDimitry Andric                                    const std::string &FS,
695ca98fd9SDimitry Andric                                    const TargetMachine &TM)
70e3b55780SDimitry Andric     : SystemZGenSubtargetInfo(TT, CPU, TuneCPU, FS), TargetTriple(TT),
71344a3780SDimitry Andric       SpecialRegisters(initializeSpecialRegisters()),
72145449b1SDimitry Andric       InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
73145449b1SDimitry Andric       TLInfo(TM, *this), FrameLowering(SystemZFrameLowering::create(*this)) {}
74d8e91e46SDimitry Andric 
enableSubRegLiveness() const75d8e91e46SDimitry Andric bool SystemZSubtarget::enableSubRegLiveness() const {
76d8e91e46SDimitry Andric   return UseSubRegLiveness;
77d8e91e46SDimitry Andric }
78d8e91e46SDimitry Andric 
isAddressedViaADA(const GlobalValue * GV) const797fa27ce4SDimitry Andric bool SystemZSubtarget::isAddressedViaADA(const GlobalValue *GV) const {
807fa27ce4SDimitry Andric   if (const auto *GO = dyn_cast<GlobalObject>(GV)) {
817fa27ce4SDimitry Andric     // A R/O variable is placed in code section. If the R/O variable has as
827fa27ce4SDimitry Andric     // least two byte alignment, then generated code can use relative
837fa27ce4SDimitry Andric     // instructions to address the variable. Otherwise, use the ADA to address
847fa27ce4SDimitry Andric     // the variable.
857fa27ce4SDimitry Andric     if (GO->getAlignment() & 0x1) {
867fa27ce4SDimitry Andric       return true;
877fa27ce4SDimitry Andric     }
887fa27ce4SDimitry Andric 
897fa27ce4SDimitry Andric     // getKindForGlobal only works with definitions
907fa27ce4SDimitry Andric     if (GO->isDeclaration()) {
917fa27ce4SDimitry Andric       return true;
927fa27ce4SDimitry Andric     }
937fa27ce4SDimitry Andric 
947fa27ce4SDimitry Andric     // check AvailableExternallyLinkage here as getKindForGlobal() asserts
957fa27ce4SDimitry Andric     if (GO->hasAvailableExternallyLinkage()) {
967fa27ce4SDimitry Andric       return true;
977fa27ce4SDimitry Andric     }
987fa27ce4SDimitry Andric 
997fa27ce4SDimitry Andric     SectionKind GOKind = TargetLoweringObjectFile::getKindForGlobal(
1007fa27ce4SDimitry Andric         GO, TLInfo.getTargetMachine());
1017fa27ce4SDimitry Andric     if (!GOKind.isReadOnly()) {
1027fa27ce4SDimitry Andric       return true;
1037fa27ce4SDimitry Andric     }
1047fa27ce4SDimitry Andric 
1057fa27ce4SDimitry Andric     return false; // R/O variable with multiple of 2 byte alignment
1067fa27ce4SDimitry Andric   }
1077fa27ce4SDimitry Andric   return true;
1087fa27ce4SDimitry Andric }
1097fa27ce4SDimitry Andric 
isPC32DBLSymbol(const GlobalValue * GV,CodeModel::Model CM) const11059d6cff9SDimitry Andric bool SystemZSubtarget::isPC32DBLSymbol(const GlobalValue *GV,
11159d6cff9SDimitry Andric                                        CodeModel::Model CM) const {
1127fa27ce4SDimitry Andric   if (isTargetzOS())
1137fa27ce4SDimitry Andric     return !isAddressedViaADA(GV);
1147fa27ce4SDimitry Andric 
115cfca06d7SDimitry Andric   // PC32DBL accesses require the low bit to be clear.
116cfca06d7SDimitry Andric   //
117cfca06d7SDimitry Andric   // FIXME: Explicitly check for functions: the datalayout is currently
118cfca06d7SDimitry Andric   // missing information about function pointers.
119ac9a064cSDimitry Andric   const DataLayout &DL = GV->getDataLayout();
120cfca06d7SDimitry Andric   if (GV->getPointerAlignment(DL) == 1 && !GV->getValueType()->isFunctionTy())
12159d6cff9SDimitry Andric     return false;
12259d6cff9SDimitry Andric 
12359d6cff9SDimitry Andric   // For the small model, all locally-binding symbols are in range.
12459d6cff9SDimitry Andric   if (CM == CodeModel::Small)
125ac9a064cSDimitry Andric     return TLInfo.getTargetMachine().shouldAssumeDSOLocal(GV);
12659d6cff9SDimitry Andric 
12759d6cff9SDimitry Andric   // For Medium and above, assume that the symbol is not within the 4GB range.
12859d6cff9SDimitry Andric   // Taking the address of locally-defined text would be OK, but that
12959d6cff9SDimitry Andric   // case isn't easy to detect.
13059d6cff9SDimitry Andric   return false;
13159d6cff9SDimitry Andric }
132