Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

308 lines
9.5 KiB
C
Raw Normal View History

//===-- PPCSubtarget.h - Define Subtarget for the PPC ----------*- C++ -*--===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the PowerPC specific subclass of TargetSubtargetInfo.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_POWERPC_PPCSUBTARGET_H
#define LLVM_LIB_TARGET_POWERPC_PPCSUBTARGET_H
#include "PPCFrameLowering.h"
#include "PPCISelLowering.h"
#include "PPCInstrInfo.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/RegisterBankInfo.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/TargetParser/Triple.h"
#include <string>
#define GET_SUBTARGETINFO_HEADER
#include "PPCGenSubtargetInfo.inc"
// GCC #defines PPC on Linux but we use it as our namespace name
#undef PPC
namespace llvm {
class StringRef;
namespace PPC {
// -m directive values.
enum {
DIR_NONE,
DIR_32,
DIR_440,
DIR_601,
DIR_602,
DIR_603,
DIR_7400,
DIR_750,
DIR_970,
DIR_A2,
DIR_E500,
DIR_E500mc,
DIR_E5500,
DIR_PWR3,
DIR_PWR4,
DIR_PWR5,
DIR_PWR5X,
DIR_PWR6,
DIR_PWR6X,
DIR_PWR7,
DIR_PWR8,
DIR_PWR9,
DIR_PWR10,
DIR_PWR_FUTURE,
DIR_64
};
}
class GlobalValue;
class PPCSubtarget : public PPCGenSubtargetInfo {
public:
enum POPCNTDKind {
POPCNTD_Unavailable,
POPCNTD_Slow,
POPCNTD_Fast
};
protected:
/// TargetTriple - What processor and OS we're targeting.
Triple TargetTriple;
/// stackAlignment - The minimum alignment known to hold of the stack frame on
/// entry to the function and which must be maintained by every function.
Align StackAlignment;
/// Selected instruction itineraries (one entry per itinerary class.)
InstrItineraryData InstrItins;
// Bool members corresponding to the SubtargetFeatures defined in tablegen.
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
bool ATTRIBUTE = DEFAULT;
#include "PPCGenSubtargetInfo.inc"
/// Which cpu directive was used.
unsigned CPUDirective;
bool IsPPC64;
bool IsLittleEndian;
POPCNTDKind HasPOPCNTD;
const PPCTargetMachine &TM;
PPCFrameLowering FrameLowering;
PPCInstrInfo InstrInfo;
PPCTargetLowering TLInfo;
SelectionDAGTargetInfo TSInfo;
/// GlobalISel related APIs.
std::unique_ptr<CallLowering> CallLoweringInfo;
std::unique_ptr<LegalizerInfo> Legalizer;
std::unique_ptr<RegisterBankInfo> RegBankInfo;
std::unique_ptr<InstructionSelector> InstSelector;
public:
/// This constructor initializes the data members to match that
/// of the specified triple.
///
PPCSubtarget(const Triple &TT, const std::string &CPU,
const std::string &TuneCPU, const std::string &FS,
const PPCTargetMachine &TM);
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
/// getStackAlignment - Returns the minimum alignment known to hold of the
/// stack frame on entry to the function and which must be maintained by every
/// function for this subtarget.
Align getStackAlignment() const { return StackAlignment; }
/// getCPUDirective - Returns the -m directive specified for the cpu.
///
unsigned getCPUDirective() const { return CPUDirective; }
2014-06-13 22:38:48 +00:00
/// getInstrItins - Return the instruction itineraries based on subtarget
/// selection.
const InstrItineraryData *getInstrItineraryData() const override {
return &InstrItins;
}
const PPCFrameLowering *getFrameLowering() const override {
return &FrameLowering;
}
const PPCInstrInfo *getInstrInfo() const override { return &InstrInfo; }
const PPCTargetLowering *getTargetLowering() const override {
return &TLInfo;
}
const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
return &TSInfo;
}
const PPCRegisterInfo *getRegisterInfo() const override {
return &getInstrInfo()->getRegisterInfo();
}
const PPCTargetMachine &getTargetMachine() const { return TM; }
/// initializeSubtargetDependencies - Initializes using a CPU, a TuneCPU, and
/// feature string so that we can use initializer lists for subtarget
/// initialization.
PPCSubtarget &initializeSubtargetDependencies(StringRef CPU,
StringRef TuneCPU,
StringRef FS);
private:
void initializeEnvironment();
void initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
public:
/// isPPC64 - Return true if we are generating code for 64-bit pointer mode.
///
bool isPPC64() const;
// useSoftFloat - Return true if soft-float option is turned on.
bool useSoftFloat() const {
if (isAIXABI() && !HasHardFloat)
report_fatal_error("soft-float is not yet supported on AIX.");
return !HasHardFloat;
}
// isLittleEndian - True if generating little-endian code
bool isLittleEndian() const { return IsLittleEndian; }
// Getters for SubtargetFeatures defined in tablegen.
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
bool GETTER() const { return ATTRIBUTE; }
#include "PPCGenSubtargetInfo.inc"
Align getPlatformStackAlignment() const {
return Align(16);
2015-02-25 01:06:45 +00:00
}
unsigned getRedZoneSize() const {
if (isPPC64())
// 288 bytes = 18*8 (FPRs) + 18*8 (GPRs, GPR13 reserved)
return 288;
// AIX PPC32: 220 bytes = 18*8 (FPRs) + 19*4 (GPRs);
// PPC32 SVR4ABI has no redzone.
return isAIXABI() ? 220 : 0;
}
bool needsSwapsForVSXMemOps() const {
return hasVSX() && isLittleEndian() && !hasP9Vector();
}
2015-02-25 01:06:45 +00:00
POPCNTDKind hasPOPCNTD() const { return HasPOPCNTD; }
const Triple &getTargetTriple() const { return TargetTriple; }
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
bool isAIXABI() const { return TargetTriple.isOSAIX(); }
bool isSVR4ABI() const { return !isAIXABI(); }
bool isELFv2ABI() const;
bool is64BitELFABI() const { return isSVR4ABI() && isPPC64(); }
bool is32BitELFABI() const { return isSVR4ABI() && !isPPC64(); }
bool isUsingPCRelativeCalls() const;
/// Originally, this function return hasISEL(). Now we always enable it,
/// but may expand the ISEL instruction later.
bool enableEarlyIfConversion() const override { return true; }
/// Scheduling customization.
bool enableMachineScheduler() const override;
/// Pipeliner customization.
bool enableMachinePipeliner() const override;
/// Machine Pipeliner customization
bool useDFAforSMS() const override;
/// This overrides the PostRAScheduler bit in the SchedModel for each CPU.
bool enablePostRAScheduler() const override;
AntiDepBreakMode getAntiDepBreakMode() const override;
void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override;
void overrideSchedPolicy(MachineSchedPolicy &Policy,
unsigned NumRegionInstrs) const override;
bool useAA() const override;
bool enableSubRegLiveness() const override;
bool enableSpillageCopyElimination() const override { return true; }
/// True if the GV will be accessed via an indirect symbol.
bool isGVIndirectSymbol(const GlobalValue *GV) const;
/// True if the ABI is descriptor based.
bool usesFunctionDescriptors() const {
// Both 32-bit and 64-bit AIX are descriptor based. For ELF only the 64-bit
// v1 ABI uses descriptors.
return isAIXABI() || (is64BitELFABI() && !isELFv2ABI());
}
[PowerPC] Add Support for indirect calls on AIX. Extends the desciptor-based indirect call support for 32-bit codegen, and enables indirect calls for AIX. In-depth Description: In a function descriptor based ABI, a function pointer points at a descriptor structure as opposed to the function's entry point. The descriptor takes the form of 3 pointers: 1 for the function's entry point, 1 for the TOC anchor of the module containing the function definition, and 1 for the environment pointer: struct FunctionDescriptor { void *EntryPoint; void *TOCAnchor; void *EnvironmentPointer; }; An indirect call has several steps of loading the the information from the descriptor into the proper registers for setting up the call. Namely it has to: 1) Save the caller's TOC pointer into the TOC save slot in the linkage area, and then load the callee's TOC pointer into the TOC register (GPR 2 on AIX). 2) Load the function descriptor's entry point into the count register. 3) Load the environment pointer into the environment pointer register (GPR 11 on AIX). 4) Perform the call by branching on count register. 5) Restore the caller's TOC pointer after returning from the indirect call. A couple important caveats to the above: - There is no way to directly load a value from memory into the count register. Instead we populate the count register by loading the entry point address into a gpr and then moving the gpr to the count register. - The TOC restore has to come immediately after the branch on count register instruction (i.e., the 1st instruction executed after we return from the call). This is an implementation limitation. We could, in theory, schedule the restore elsewhere as long as no uses of the TOC pointer fall in between the call and the restore; however, to keep it simple, we insert a pseudo instruction that represents both the indirect branch instruction and the load instruction that restores the caller's TOC from the linkage area. As they flow through the compiler as a single pseudo instruction, nothing can be inserted between them and the caller's TOC is then valid at any use. Differtential Revision: https://reviews.llvm.org/D70724
2019-12-13 14:34:11 -05:00
unsigned descriptorTOCAnchorOffset() const {
assert(usesFunctionDescriptors() &&
"Should only be called when the target uses descriptors.");
return IsPPC64 ? 8 : 4;
}
unsigned descriptorEnvironmentPointerOffset() const {
assert(usesFunctionDescriptors() &&
"Should only be called when the target uses descriptors.");
return IsPPC64 ? 16 : 8;
}
MCRegister getEnvironmentPointerRegister() const {
assert(usesFunctionDescriptors() &&
"Should only be called when the target uses descriptors.");
return IsPPC64 ? PPC::X11 : PPC::R11;
}
MCRegister getTOCPointerRegister() const {
assert((is64BitELFABI() || isAIXABI()) &&
"Should only be called when the target is a TOC based ABI.");
return IsPPC64 ? PPC::X2 : PPC::R2;
}
MCRegister getStackPointerRegister() const {
return IsPPC64 ? PPC::X1 : PPC::R1;
}
bool isXRaySupported() const override { return IsPPC64 && IsLittleEndian; }
bool isPredictableSelectIsExpensive() const {
return PredictableSelectIsExpensive;
}
// Select allocation orders of GPRC and G8RC. It should be strictly consistent
// with corresponding AltOrders in PPCRegisterInfo.td.
unsigned getGPRAllocationOrderIdx() const {
if (is64BitELFABI())
return 1;
if (isAIXABI())
return 2;
return 0;
}
// GlobalISEL
const CallLowering *getCallLowering() const override;
const RegisterBankInfo *getRegBankInfo() const override;
const LegalizerInfo *getLegalizerInfo() const override;
InstructionSelector *getInstructionSelector() const override;
};
} // End llvm namespace
#endif