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