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"
1106c3fb27SDimitry 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.
anchor()290b57cec5SDimitry Andric void SystemZSubtarget::anchor() {}
300b57cec5SDimitry Andric
initializeSubtargetDependencies(StringRef CPU,StringRef TuneCPU,StringRef FS)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 *
initializeSpecialRegisters()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 llvm_unreachable("Invalid Calling Convention. Cannot initialize Special "
63fe6060f1SDimitry Andric "Call Registers!");
64fe6060f1SDimitry Andric }
65fe6060f1SDimitry Andric
SystemZSubtarget(const Triple & TT,const std::string & CPU,const std::string & TuneCPU,const std::string & FS,const TargetMachine & TM)660b57cec5SDimitry Andric SystemZSubtarget::SystemZSubtarget(const Triple &TT, const std::string &CPU,
6781ad6265SDimitry Andric const std::string &TuneCPU,
680b57cec5SDimitry Andric const std::string &FS,
690b57cec5SDimitry Andric const TargetMachine &TM)
70bdd1243dSDimitry Andric : SystemZGenSubtargetInfo(TT, CPU, TuneCPU, FS), TargetTriple(TT),
71fe6060f1SDimitry Andric SpecialRegisters(initializeSpecialRegisters()),
7281ad6265SDimitry Andric InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
7381ad6265SDimitry Andric TLInfo(TM, *this), FrameLowering(SystemZFrameLowering::create(*this)) {}
740b57cec5SDimitry Andric
enableSubRegLiveness() const750b57cec5SDimitry Andric bool SystemZSubtarget::enableSubRegLiveness() const {
760b57cec5SDimitry Andric return UseSubRegLiveness;
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric
isAddressedViaADA(const GlobalValue * GV) const7906c3fb27SDimitry Andric bool SystemZSubtarget::isAddressedViaADA(const GlobalValue *GV) const {
8006c3fb27SDimitry Andric if (const auto *GO = dyn_cast<GlobalObject>(GV)) {
8106c3fb27SDimitry Andric // A R/O variable is placed in code section. If the R/O variable has as
8206c3fb27SDimitry Andric // least two byte alignment, then generated code can use relative
8306c3fb27SDimitry Andric // instructions to address the variable. Otherwise, use the ADA to address
8406c3fb27SDimitry Andric // the variable.
8506c3fb27SDimitry Andric if (GO->getAlignment() & 0x1) {
8606c3fb27SDimitry Andric return true;
8706c3fb27SDimitry Andric }
8806c3fb27SDimitry Andric
8906c3fb27SDimitry Andric // getKindForGlobal only works with definitions
9006c3fb27SDimitry Andric if (GO->isDeclaration()) {
9106c3fb27SDimitry Andric return true;
9206c3fb27SDimitry Andric }
9306c3fb27SDimitry Andric
9406c3fb27SDimitry Andric // check AvailableExternallyLinkage here as getKindForGlobal() asserts
9506c3fb27SDimitry Andric if (GO->hasAvailableExternallyLinkage()) {
9606c3fb27SDimitry Andric return true;
9706c3fb27SDimitry Andric }
9806c3fb27SDimitry Andric
9906c3fb27SDimitry Andric SectionKind GOKind = TargetLoweringObjectFile::getKindForGlobal(
10006c3fb27SDimitry Andric GO, TLInfo.getTargetMachine());
10106c3fb27SDimitry Andric if (!GOKind.isReadOnly()) {
10206c3fb27SDimitry Andric return true;
10306c3fb27SDimitry Andric }
10406c3fb27SDimitry Andric
10506c3fb27SDimitry Andric return false; // R/O variable with multiple of 2 byte alignment
10606c3fb27SDimitry Andric }
10706c3fb27SDimitry Andric return true;
10806c3fb27SDimitry Andric }
10906c3fb27SDimitry Andric
isPC32DBLSymbol(const GlobalValue * GV,CodeModel::Model CM) const1100b57cec5SDimitry Andric bool SystemZSubtarget::isPC32DBLSymbol(const GlobalValue *GV,
1110b57cec5SDimitry Andric CodeModel::Model CM) const {
11206c3fb27SDimitry Andric if (isTargetzOS())
11306c3fb27SDimitry Andric return !isAddressedViaADA(GV);
11406c3fb27SDimitry Andric
1155ffd83dbSDimitry Andric // PC32DBL accesses require the low bit to be clear.
1165ffd83dbSDimitry Andric //
1175ffd83dbSDimitry Andric // FIXME: Explicitly check for functions: the datalayout is currently
1185ffd83dbSDimitry Andric // missing information about function pointers.
119*0fca6ea1SDimitry Andric const DataLayout &DL = GV->getDataLayout();
1205ffd83dbSDimitry Andric if (GV->getPointerAlignment(DL) == 1 && !GV->getValueType()->isFunctionTy())
1210b57cec5SDimitry Andric return false;
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric // For the small model, all locally-binding symbols are in range.
1240b57cec5SDimitry Andric if (CM == CodeModel::Small)
125*0fca6ea1SDimitry Andric return TLInfo.getTargetMachine().shouldAssumeDSOLocal(GV);
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric // For Medium and above, assume that the symbol is not within the 4GB range.
1280b57cec5SDimitry Andric // Taking the address of locally-defined text would be OK, but that
1290b57cec5SDimitry Andric // case isn't easy to detect.
1300b57cec5SDimitry Andric return false;
1310b57cec5SDimitry Andric }
132