diff --git a/llvm/lib/Target/VE/CMakeLists.txt b/llvm/lib/Target/VE/CMakeLists.txt --- a/llvm/lib/Target/VE/CMakeLists.txt +++ b/llvm/lib/Target/VE/CMakeLists.txt @@ -1,8 +1,25 @@ set(LLVM_TARGET_DEFINITIONS VE.td) +tablegen(LLVM VEGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM VEGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM VEGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM VEGenDAGISel.inc -gen-dag-isel) +tablegen(LLVM VEGenSubtargetInfo.inc -gen-subtarget) +tablegen(LLVM VEGenCallingConv.inc -gen-callingconv) +add_public_tablegen_target(VECommonTableGen) + add_llvm_target(VECodeGen + VEAsmPrinter.cpp + VEFrameLowering.cpp + VEISelDAGToDAG.cpp + VEISelLowering.cpp + VEInstrInfo.cpp + VEMCInstLower.cpp + VERegisterInfo.cpp + VESubtarget.cpp VETargetMachine.cpp ) +add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) diff --git a/llvm/lib/Target/VE/InstPrinter/CMakeLists.txt b/llvm/lib/Target/VE/InstPrinter/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/InstPrinter/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_component_library(LLVMVEAsmPrinter + VEInstPrinter.cpp + ) diff --git a/llvm/lib/Target/VE/MCTargetDesc/LLVMBuild.txt b/llvm/lib/Target/VE/InstPrinter/LLVMBuild.txt copy from llvm/lib/Target/VE/MCTargetDesc/LLVMBuild.txt copy to llvm/lib/Target/VE/InstPrinter/LLVMBuild.txt --- a/llvm/lib/Target/VE/MCTargetDesc/LLVMBuild.txt +++ b/llvm/lib/Target/VE/InstPrinter/LLVMBuild.txt @@ -1,4 +1,4 @@ -;===- ./lib/Target/VE/MCTargetDesc/LLVMBuild.txt ---------------*- Conf -*--===; +;===- ./lib/Target/VE/InstPrinter/LLVMBuild.txt ----------------*- Conf -*--===; ; ; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ; See https://llvm.org/LICENSE.txt for license information. @@ -16,7 +16,7 @@ [component_0] type = Library -name = VEDesc +name = VEAsmPrinter parent = VE -required_libraries = MC VEInfo Support +required_libraries = MC Support add_to_library_groups = VE diff --git a/llvm/lib/Target/VE/InstPrinter/VEInstPrinter.h b/llvm/lib/Target/VE/InstPrinter/VEInstPrinter.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/InstPrinter/VEInstPrinter.h @@ -0,0 +1,49 @@ +//===-- VEInstPrinter.h - Convert VE MCInst to assembly syntax ------------===// +// +// 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 class prints an VE MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_INSTPRINTER_VEINSTPRINTER_H +#define LLVM_LIB_TARGET_VE_INSTPRINTER_VEINSTPRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { + +class VEInstPrinter : public MCInstPrinter { +public: + VEInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + void printRegName(raw_ostream &OS, unsigned RegNo) const override; + void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, + const MCSubtargetInfo &STI, raw_ostream &OS) override; + + // Autogenerated by tblgen. + bool printAliasInstr(const MCInst *, const MCSubtargetInfo &, raw_ostream &); + void printInstruction(const MCInst *, uint64_t, const MCSubtargetInfo &, + raw_ostream &); + static const char *getRegisterName(unsigned RegNo); + + void printOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI, + raw_ostream &OS); + void printMemASXOperand(const MCInst *MI, int opNum, + const MCSubtargetInfo &STI, raw_ostream &OS, + const char *Modifier = nullptr); + void printMemASOperand(const MCInst *MI, int opNum, + const MCSubtargetInfo &STI, raw_ostream &OS, + const char *Modifier = nullptr); + void printCCOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI, + raw_ostream &OS); +}; +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/VE/InstPrinter/VEInstPrinter.cpp b/llvm/lib/Target/VE/InstPrinter/VEInstPrinter.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/InstPrinter/VEInstPrinter.cpp @@ -0,0 +1,118 @@ +//===-- VEInstPrinter.cpp - Convert VE MCInst to assembly syntax -----------==// +// +// 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 class prints an VE MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#include "VEInstPrinter.h" +#include "VE.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "ve-asmprinter" + +// The generated AsmMatcher VEGenAsmWriter uses "VE" as the target +// namespace. +namespace llvm { +namespace VE { +using namespace VE; +} +} // namespace llvm + +#define GET_INSTRUCTION_NAME +#define PRINT_ALIAS_INSTR +#include "VEGenAsmWriter.inc" + +void VEInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { + OS << '%' << StringRef(getRegisterName(RegNo)).lower(); +} + +void VEInstPrinter::printInst(const MCInst *MI, uint64_t Address, + StringRef Annot, const MCSubtargetInfo &STI, + raw_ostream &OS) { + if (!printAliasInstr(MI, STI, OS)) + printInstruction(MI, Address, STI, OS); + printAnnotation(OS, Annot); +} + +void VEInstPrinter::printOperand(const MCInst *MI, int opNum, + const MCSubtargetInfo &STI, raw_ostream &O) { + const MCOperand &MO = MI->getOperand(opNum); + + if (MO.isReg()) { + printRegName(O, MO.getReg()); + return; + } + + if (MO.isImm()) { + switch (MI->getOpcode()) { + default: + O << (int)MO.getImm(); + return; + } + } + + assert(MO.isExpr() && "Unknown operand kind in printOperand"); + MO.getExpr()->print(O, &MAI); +} + +void VEInstPrinter::printMemASXOperand(const MCInst *MI, int opNum, + const MCSubtargetInfo &STI, + raw_ostream &O, const char *Modifier) { + // If this is an ADD operand, emit it like normal operands. + if (Modifier && !strcmp(Modifier, "arith")) { + printOperand(MI, opNum, STI, O); + O << ", "; + printOperand(MI, opNum + 1, STI, O); + return; + } + + const MCOperand &MO = MI->getOperand(opNum + 1); + if (MO.isImm() && MO.getImm() == 0) { + // don't print "+0" + } else { + printOperand(MI, opNum + 1, STI, O); + } + O << "(,"; + printOperand(MI, opNum, STI, O); + O << ")"; +} + +void VEInstPrinter::printMemASOperand(const MCInst *MI, int opNum, + const MCSubtargetInfo &STI, + raw_ostream &O, const char *Modifier) { + // If this is an ADD operand, emit it like normal operands. + if (Modifier && !strcmp(Modifier, "arith")) { + printOperand(MI, opNum, STI, O); + O << ", "; + printOperand(MI, opNum + 1, STI, O); + return; + } + + const MCOperand &MO = MI->getOperand(opNum + 1); + if (MO.isImm() && MO.getImm() == 0) { + // don't print "+0" + } else { + printOperand(MI, opNum + 1, STI, O); + } + O << "("; + printOperand(MI, opNum, STI, O); + O << ")"; +} + +void VEInstPrinter::printCCOperand(const MCInst *MI, int opNum, + const MCSubtargetInfo &STI, raw_ostream &O) { + int CC = (int)MI->getOperand(opNum).getImm(); + O << VECondCodeToString((VECC::CondCodes)CC); +} diff --git a/llvm/lib/Target/VE/LLVMBuild.txt b/llvm/lib/Target/VE/LLVMBuild.txt --- a/llvm/lib/Target/VE/LLVMBuild.txt +++ b/llvm/lib/Target/VE/LLVMBuild.txt @@ -15,19 +15,20 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = MCTargetDesc TargetInfo +subdirectories = InstPrinter MCTargetDesc TargetInfo [component_0] type = TargetGroup name = VE parent = Target has_asmparser = 0 -has_asmprinter = 0 +has_asmprinter = 1 [component_1] type = Library name = VECodeGen parent = VE -required_libraries = Analysis AsmPrinter CodeGen Core MC SelectionDAG +required_libraries = Analysis AsmPrinter CodeGen Core + MC SelectionDAG VEAsmPrinter VEDesc VEInfo Support Target add_to_library_groups = VE diff --git a/llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt --- a/llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt @@ -1,3 +1,5 @@ -add_llvm_library(LLVMVEDesc +add_llvm_component_library(LLVMVEDesc + VEMCAsmInfo.cpp VEMCTargetDesc.cpp + VETargetStreamer.cpp ) diff --git a/llvm/lib/Target/VE/MCTargetDesc/LLVMBuild.txt b/llvm/lib/Target/VE/MCTargetDesc/LLVMBuild.txt --- a/llvm/lib/Target/VE/MCTargetDesc/LLVMBuild.txt +++ b/llvm/lib/Target/VE/MCTargetDesc/LLVMBuild.txt @@ -18,5 +18,5 @@ type = Library name = VEDesc parent = VE -required_libraries = MC VEInfo Support +required_libraries = MC VEAsmPrinter VEInfo Support add_to_library_groups = VE diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCAsmInfo.h b/llvm/lib/Target/VE/MCTargetDesc/VEMCAsmInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCAsmInfo.h @@ -0,0 +1,31 @@ +//===- VEMCAsmInfo.h - VE asm properties -----------------------*- 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 contains the declaration of the VEMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_MCTARGETDESC_VEMCASMINFO_H +#define LLVM_LIB_TARGET_VE_MCTARGETDESC_VEMCASMINFO_H + +#include "llvm/MC/MCAsmInfoELF.h" + +namespace llvm { + +class Triple; + +class VEELFMCAsmInfo : public MCAsmInfoELF { + void anchor() override; + +public: + explicit VEELFMCAsmInfo(const Triple &TheTriple); +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_VE_MCTARGETDESC_VEMCASMINFO_H diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCAsmInfo.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCAsmInfo.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCAsmInfo.cpp @@ -0,0 +1,40 @@ +//===- VEMCAsmInfo.cpp - VE asm properties --------------------------------===// +// +// 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 contains the declarations of the VEMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "VEMCAsmInfo.h" +#include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCTargetOptions.h" + +using namespace llvm; + +void VEELFMCAsmInfo::anchor() {} + +VEELFMCAsmInfo::VEELFMCAsmInfo(const Triple &TheTriple) { + + CodePointerSize = CalleeSaveStackSlotSize = 8; + MaxInstLength = MinInstAlignment = 8; + + // VE uses ".*byte" directive for unaligned data. + Data8bitsDirective = "\t.byte\t"; + Data16bitsDirective = "\t.2byte\t"; + Data32bitsDirective = "\t.4byte\t"; + Data64bitsDirective = "\t.8byte\t"; + + // Uses '.section' before '.bss' directive. VE requires this although + // assembler manual says sinple '.bss' is supported. + UsesELFSectionDirectiveForBSS = true; + + SupportsDebugInformation = true; +} diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h b/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h --- a/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h +++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h @@ -18,10 +18,36 @@ #include namespace llvm { - +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectWriter; +class MCRegisterInfo; +class MCSubtargetInfo; +class MCTargetOptions; class Target; +class Triple; +class StringRef; +class raw_pwrite_stream; +class raw_ostream; + Target &getTheVETarget(); -} // end llvm namespace +} // namespace llvm + +// Defines symbolic names for VE registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "VEGenRegisterInfo.inc" + +// Defines symbolic names for the VE instructions. +// +#define GET_INSTRINFO_ENUM +#include "VEGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "VEGenSubtargetInfo.inc" #endif diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp --- a/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp +++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp @@ -11,9 +11,96 @@ //===----------------------------------------------------------------------===// #include "VEMCTargetDesc.h" +#include "InstPrinter/VEInstPrinter.h" +#include "VEMCAsmInfo.h" +#include "VETargetStreamer.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; +#define GET_INSTRINFO_MC_DESC +#include "VEGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "VEGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "VEGenRegisterInfo.inc" + +static MCAsmInfo *createVEMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TT, + const MCTargetOptions &Options) { + MCAsmInfo *MAI = new VEELFMCAsmInfo(TT); + unsigned Reg = MRI.getDwarfRegNum(VE::SX11, true); + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, Reg, 0); + MAI->addInitialFrameState(Inst); + return MAI; +} + +static MCInstrInfo *createVEMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitVEMCInstrInfo(X); + return X; +} + +static MCRegisterInfo *createVEMCRegisterInfo(const Triple &TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitVEMCRegisterInfo(X, VE::SX10); + return X; +} + +static MCSubtargetInfo *createVEMCSubtargetInfo(const Triple &TT, StringRef CPU, + StringRef FS) { + if (CPU.empty()) + CPU = "ve"; + return createVEMCSubtargetInfoImpl(TT, CPU, FS); +} + +static MCTargetStreamer * +createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { + return new VETargetELFStreamer(S); +} + +static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool isVerboseAsm) { + return new VETargetAsmStreamer(S, OS); +} + +static MCInstPrinter *createVEMCInstPrinter(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + return new VEInstPrinter(MAI, MII, MRI); +} + extern "C" void LLVMInitializeVETargetMC() { - // TODO + // Register the MC asm info. + RegisterMCAsmInfoFn X(getTheVETarget(), createVEMCAsmInfo); + + for (Target *T : {&getTheVETarget()}) { + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(*T, createVEMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(*T, createVEMCRegisterInfo); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(*T, createVEMCSubtargetInfo); + + // Register the object target streamer. + TargetRegistry::RegisterObjectTargetStreamer(*T, + createObjectTargetStreamer); + + // Register the asm streamer. + TargetRegistry::RegisterAsmTargetStreamer(*T, createTargetAsmStreamer); + + // Register the MCInstPrinter + TargetRegistry::RegisterMCInstPrinter(*T, createVEMCInstPrinter); + } } diff --git a/llvm/lib/Target/VE/MCTargetDesc/VETargetStreamer.h b/llvm/lib/Target/VE/MCTargetDesc/VETargetStreamer.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/MCTargetDesc/VETargetStreamer.h @@ -0,0 +1,47 @@ +//===-- VETargetStreamer.h - VE Target Streamer ----------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_VETARGETSTREAMER_H +#define LLVM_LIB_TARGET_VE_VETARGETSTREAMER_H + +#include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class VETargetStreamer : public MCTargetStreamer { + virtual void anchor(); + +public: + VETargetStreamer(MCStreamer &S); + /// Emit ".register , #ignore". + virtual void emitVERegisterIgnore(unsigned reg) = 0; + /// Emit ".register , #scratch". + virtual void emitVERegisterScratch(unsigned reg) = 0; +}; + +// This part is for ascii assembly output +class VETargetAsmStreamer : public VETargetStreamer { + formatted_raw_ostream &OS; + +public: + VETargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); + void emitVERegisterIgnore(unsigned reg) override; + void emitVERegisterScratch(unsigned reg) override; +}; + +// This part is for ELF object output +class VETargetELFStreamer : public VETargetStreamer { +public: + VETargetELFStreamer(MCStreamer &S); + MCELFStreamer &getStreamer(); + void emitVERegisterIgnore(unsigned reg) override {} + void emitVERegisterScratch(unsigned reg) override {} +}; +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/VE/MCTargetDesc/VETargetStreamer.cpp b/llvm/lib/Target/VE/MCTargetDesc/VETargetStreamer.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/MCTargetDesc/VETargetStreamer.cpp @@ -0,0 +1,44 @@ +//===-- VETargetStreamer.cpp - VE Target Streamer Methods -----------------===// +// +// 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 provides VE specific target streamer methods. +// +//===----------------------------------------------------------------------===// + +#include "VETargetStreamer.h" +#include "InstPrinter/VEInstPrinter.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; + +// pin vtable to this file +VETargetStreamer::VETargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} + +void VETargetStreamer::anchor() {} + +VETargetAsmStreamer::VETargetAsmStreamer(MCStreamer &S, + formatted_raw_ostream &OS) + : VETargetStreamer(S), OS(OS) {} + +void VETargetAsmStreamer::emitVERegisterIgnore(unsigned reg) { + OS << "\t.register " + << "%" << StringRef(VEInstPrinter::getRegisterName(reg)).lower() + << ", #ignore\n"; +} + +void VETargetAsmStreamer::emitVERegisterScratch(unsigned reg) { + OS << "\t.register " + << "%" << StringRef(VEInstPrinter::getRegisterName(reg)).lower() + << ", #scratch\n"; +} + +VETargetELFStreamer::VETargetELFStreamer(MCStreamer &S) : VETargetStreamer(S) {} + +MCELFStreamer &VETargetELFStreamer::getStreamer() { + return static_cast(Streamer); +} diff --git a/llvm/lib/Target/VE/VE.h b/llvm/lib/Target/VE/VE.h --- a/llvm/lib/Target/VE/VE.h +++ b/llvm/lib/Target/VE/VE.h @@ -15,5 +15,92 @@ #define LLVM_LIB_TARGET_VE_VE_H #include "MCTargetDesc/VEMCTargetDesc.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetMachine.h" +namespace llvm { +class FunctionPass; +class VETargetMachine; +class formatted_raw_ostream; +class AsmPrinter; +class MCInst; +class MachineInstr; + +FunctionPass *createVEISelDag(VETargetMachine &TM); +FunctionPass *createVEPromoteToI1Pass(); + +void LowerVEMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, + AsmPrinter &AP); +} // namespace llvm + +namespace llvm { +// Enums corresponding to VE condition codes, both icc's and fcc's. These +// values must be kept in sync with the ones in the .td file. +namespace VECC { +enum CondCodes { + // Integer comparison + CC_IG = 0, // Greater + CC_IL = 1, // Less + CC_INE = 2, // Not Equal + CC_IEQ = 3, // Equal + CC_IGE = 4, // Greater or Equal + CC_ILE = 5, // Less or Equal + + // Floating point comparison + CC_AF = 0 + 6, // Never + CC_G = 1 + 6, // Greater + CC_L = 2 + 6, // Less + CC_NE = 3 + 6, // Not Equal + CC_EQ = 4 + 6, // Equal + CC_GE = 5 + 6, // Greater or Equal + CC_LE = 6 + 6, // Less or Equal + CC_NUM = 7 + 6, // Number + CC_NAN = 8 + 6, // NaN + CC_GNAN = 9 + 6, // Greater or NaN + CC_LNAN = 10 + 6, // Less or NaN + CC_NENAN = 11 + 6, // Not Equal or NaN + CC_EQNAN = 12 + 6, // Equal or NaN + CC_GENAN = 13 + 6, // Greater or Equal or NaN + CC_LENAN = 14 + 6, // Less or Equal or NaN + CC_AT = 15 + 6, // Always +}; +} + +inline static const char *VECondCodeToString(VECC::CondCodes CC) { + switch (CC) { + case VECC::CC_IG: return "gt"; + case VECC::CC_IL: return "lt"; + case VECC::CC_INE: return "ne"; + case VECC::CC_IEQ: return "eq"; + case VECC::CC_IGE: return "ge"; + case VECC::CC_ILE: return "le"; + case VECC::CC_AF: return "af"; + case VECC::CC_G: return "gt"; + case VECC::CC_L: return "lt"; + case VECC::CC_NE: return "ne"; + case VECC::CC_EQ: return "eq"; + case VECC::CC_GE: return "ge"; + case VECC::CC_LE: return "le"; + case VECC::CC_NUM: return "num"; + case VECC::CC_NAN: return "nan"; + case VECC::CC_GNAN: return "gtnan"; + case VECC::CC_LNAN: return "ltnan"; + case VECC::CC_NENAN: return "nenan"; + case VECC::CC_EQNAN: return "eqnan"; + case VECC::CC_GENAN: return "genan"; + case VECC::CC_LENAN: return "lenan"; + case VECC::CC_AT: return "at"; + } + llvm_unreachable("Invalid cond code"); +} + +inline static unsigned HI32(int64_t imm) { + return (unsigned)((imm >> 32) & 0xFFFFFFFF); +} + +inline static unsigned LO32(int64_t imm) { + return (unsigned)(imm & 0xFFFFFFFF); +} + +} // namespace llvm #endif diff --git a/llvm/lib/Target/VE/VE.td b/llvm/lib/Target/VE/VE.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VE.td @@ -0,0 +1,56 @@ +//===-- VE.td - Describe the VE Target Machine -------------*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// VE Subtarget features. +// + +//===----------------------------------------------------------------------===// +// Register File, Calling Conv, Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "VERegisterInfo.td" +include "VECallingConv.td" +include "VEInstrInfo.td" + +def VEInstrInfo : InstrInfo; + +//===----------------------------------------------------------------------===// +// VE processors supported. +//===----------------------------------------------------------------------===// + +class Proc Features> + : Processor; + +def : Proc<"ve", []>; + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def VEAsmWriter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; + int PassSubtarget = 1; + int Variant = 0; +} + +def VE : Target { + // Pull in Instruction Info: + let InstructionSet = VEInstrInfo; + let AssemblyWriters = [VEAsmWriter]; + let AllowRegisterRenaming = 1; +} diff --git a/llvm/lib/Target/VE/VEAsmPrinter.cpp b/llvm/lib/Target/VE/VEAsmPrinter.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEAsmPrinter.cpp @@ -0,0 +1,78 @@ +//===-- VEAsmPrinter.cpp - VE LLVM assembly writer ------------------------===// +// +// 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 contains a printer that converts from our internal representation +// of machine-dependent LLVM code to GAS-format VE assembly language. +// +//===----------------------------------------------------------------------===// + +#include "InstPrinter/VEInstPrinter.h" +#include "MCTargetDesc/VETargetStreamer.h" +#include "VE.h" +#include "VEInstrInfo.h" +#include "VETargetMachine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/IR/Mangler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstBuilder.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "ve-asmprinter" + +namespace { +class VEAsmPrinter : public AsmPrinter { + VETargetStreamer &getTargetStreamer() { + return static_cast(*OutStreamer->getTargetStreamer()); + } + +public: + explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)) {} + + StringRef getPassName() const override { return "VE Assembly Printer"; } + + void EmitInstruction(const MachineInstr *MI) override; + + static const char *getRegisterName(unsigned RegNo) { + return VEInstPrinter::getRegisterName(RegNo); + } +}; +} // end of anonymous namespace + +void VEAsmPrinter::EmitInstruction(const MachineInstr *MI) { + + switch (MI->getOpcode()) { + default: + break; + case TargetOpcode::DBG_VALUE: + // FIXME: Debug Value. + return; + } + MachineBasicBlock::const_instr_iterator I = MI->getIterator(); + MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); + do { + MCInst TmpInst; + LowerVEMachineInstrToMCInst(&*I, TmpInst, *this); + EmitToStreamer(*OutStreamer, TmpInst); + } while ((++I != E) && I->isInsideBundle()); // Delay slot check. +} + +// Force static initialization. +extern "C" void LLVMInitializeVEAsmPrinter() { + RegisterAsmPrinter X(getTheVETarget()); +} diff --git a/llvm/lib/Target/VE/VECallingConv.td b/llvm/lib/Target/VE/VECallingConv.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VECallingConv.td @@ -0,0 +1,19 @@ +//===-- VECallingConv.td - Calling Conventions VE ----------*- tablegen -*-===// +// +// 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 describes the calling conventions for the VE architectures. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Aurora VE +//===----------------------------------------------------------------------===// + +// Callee-saved registers +def CSR : CalleeSavedRegs<(add (sequence "SX%u", 18, 33))>; +def CSR_NoRegs : CalleeSavedRegs<(add)>; diff --git a/llvm/lib/Target/VE/VEFrameLowering.h b/llvm/lib/Target/VE/VEFrameLowering.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEFrameLowering.h @@ -0,0 +1,81 @@ +//===-- VEFrameLowering.h - Define frame lowering for VE --*- 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 +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_VEFRAMELOWERING_H +#define LLVM_LIB_TARGET_VE_VEFRAMELOWERING_H + +#include "VE.h" +#include "llvm/CodeGen/TargetFrameLowering.h" + +namespace llvm { + +class VESubtarget; +class VEFrameLowering : public TargetFrameLowering { +public: + explicit VEFrameLowering(const VESubtarget &ST); + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitPrologueInsns(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, int NumBytes, + bool RequireFPUpdate) const; + void emitEpilogueInsns(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, int NumBytes, + bool RequireFPUpdate) const; + + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; + + bool hasReservedCallFrame(const MachineFunction &MF) const override; + bool hasFP(const MachineFunction &MF) const override; + void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, + RegScavenger *RS = nullptr) const override; + + int getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const override; + + const SpillSlot * + getCalleeSavedSpillSlots(unsigned &NumEntries) const override { + static const SpillSlot Offsets[] = { + {VE::SX17, 40}, {VE::SX18, 48}, {VE::SX19, 56}, {VE::SX20, 64}, + {VE::SX21, 72}, {VE::SX22, 80}, {VE::SX23, 88}, {VE::SX24, 96}, + {VE::SX25, 104}, {VE::SX26, 112}, {VE::SX27, 120}, {VE::SX28, 128}, + {VE::SX29, 136}, {VE::SX30, 144}, {VE::SX31, 152}, {VE::SX32, 160}, + {VE::SX33, 168}}; + NumEntries = array_lengthof(Offsets); + return Offsets; + } + + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + bool targetHandlesStackFrameRounding() const override { return true; } + +private: + // Returns true if MF is a leaf procedure. + bool isLeafProc(MachineFunction &MF) const; + + // Emits code for adjusting SP in function prologue/epilogue. + void emitSPAdjustment(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, int NumBytes) const; + + // Emits code for extending SP in function prologue/epilogue. + void emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, int NumBytes) const; +}; + +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/VE/VEFrameLowering.cpp b/llvm/lib/Target/VE/VEFrameLowering.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEFrameLowering.cpp @@ -0,0 +1,319 @@ +//===-- VEFrameLowering.cpp - VE Frame Information ------------------------===// +// +// 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 contains the VE implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "VEFrameLowering.h" +#include "VEInstrInfo.h" +#include "VESubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +VEFrameLowering::VEFrameLowering(const VESubtarget &ST) + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0, + Align(16)) {} + +void VEFrameLowering::emitPrologueInsns(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes, + bool RequireFPUpdate) const { + + DebugLoc dl; + const VEInstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + // Insert following codes here as prologue + // + // st %fp, 0(,%sp) + // st %lr, 8(,%sp) + // st %got, 24(,%sp) + // st %plt, 32(,%sp) + // or %fp, 0, %sp + + BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) + .addReg(VE::SX11) + .addImm(0) + .addReg(VE::SX9); + BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) + .addReg(VE::SX11) + .addImm(8) + .addReg(VE::SX10); + BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) + .addReg(VE::SX11) + .addImm(24) + .addReg(VE::SX15); + BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) + .addReg(VE::SX11) + .addImm(32) + .addReg(VE::SX16); + BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX9).addReg(VE::SX11).addImm(0); +} + +void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes, + bool RequireFPUpdate) const { + + DebugLoc dl; + const VEInstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + // Insert following codes here as epilogue + // + // or %sp, 0, %fp + // ld %got, 32(,%sp) + // ld %plt, 24(,%sp) + // ld %lr, 8(,%sp) + // ld %fp, 0(,%sp) + + BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX11).addReg(VE::SX9).addImm(0); + BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX16) + .addReg(VE::SX11) + .addImm(32); + BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX15) + .addReg(VE::SX11) + .addImm(24); + BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX10) + .addReg(VE::SX11) + .addImm(8); + BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX9) + .addReg(VE::SX11) + .addImm(0); +} + +void VEFrameLowering::emitSPAdjustment(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes) const { + DebugLoc dl; + const VEInstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + + if (NumBytes >= -64 && NumBytes < 63) { + BuildMI(MBB, MBBI, dl, TII.get(VE::ADXri), VE::SX11) + .addReg(VE::SX11) + .addImm(NumBytes); + return; + } + + // Emit following codes. This clobbers SX13 which we always know is + // available here. + // lea %s13,%lo(NumBytes) + // and %s13,%s13,(32)0 + // lea.sl %sp,%hi(NumBytes)(%sp, %s13) + BuildMI(MBB, MBBI, dl, TII.get(VE::LEAzzi), VE::SX13).addImm(LO32(NumBytes)); + BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm0), VE::SX13) + .addReg(VE::SX13) + .addImm(32); + BuildMI(MBB, MBBI, dl, TII.get(VE::LEASLrri), VE::SX11) + .addReg(VE::SX11) + .addReg(VE::SX13) + .addImm(HI32(NumBytes)); +} + +void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes) const { + DebugLoc dl; + const VEInstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + + // Emit following codes. It is not possible to insert multiple + // BasicBlocks in PEI pass, so we emit two pseudo instructions here. + // + // EXTEND_STACK // pseudo instrcution + // EXTEND_STACK_GUARD // pseudo instrcution + // + // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into + // following instructions with multiple basic blocks later. + // + // thisBB: + // brge.l.t %sp, %sl, sinkBB + // syscallBB: + // ld %s61, 0x18(, %tp) // load param area + // or %s62, 0, %s0 // spill the value of %s0 + // lea %s63, 0x13b // syscall # of grow + // shm.l %s63, 0x0(%s61) // store syscall # at addr:0 + // shm.l %sl, 0x8(%s61) // store old limit at addr:8 + // shm.l %sp, 0x10(%s61) // store new limit at addr:16 + // monc // call monitor + // or %s0, 0, %s62 // restore the value of %s0 + // sinkBB: + // + // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA + // pass. This pseudo is required to be at the next of EXTEND_STACK + // pseudo in order to protect iteration loop in ExpandPostRA. + + BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK)); + BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK_GUARD)); +} + +void VEFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); + MachineFrameInfo &MFI = MF.getFrameInfo(); + const VESubtarget &Subtarget = MF.getSubtarget(); + const VEInstrInfo &TII = + *static_cast(Subtarget.getInstrInfo()); + const VERegisterInfo &RegInfo = + *static_cast(Subtarget.getRegisterInfo()); + MachineBasicBlock::iterator MBBI = MBB.begin(); + // Debug location must be unknown since the first debug location is used + // to determine the end of the prologue. + DebugLoc dl; + bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); + + // FIXME: unfortunately, returning false from canRealignStack + // actually just causes needsStackRealignment to return false, + // rather than reporting an error, as would be sensible. This is + // poor, but fixing that bogosity is going to be a large project. + // For now, just see if it's lied, and report an error here. + if (!NeedsStackRealignment && MFI.getMaxAlignment() > getStackAlignment()) + report_fatal_error("Function \"" + Twine(MF.getName()) + + "\" required " + "stack re-alignment, but LLVM couldn't handle it " + "(probably because it has a dynamic alloca)."); + + // Get the number of bytes to allocate from the FrameInfo + int NumBytes = (int)MFI.getStackSize(); + // The VE ABI requires a reserved 176-byte area in the user's stack, starting + // at %sp + 16. This is for the callee Register Save Area (RSA). + // + // We therefore need to add that offset to the total stack size + // after all the stack objects are placed by + // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack + // needs to be aligned *after* the extra size is added, we need to disable + // calculateFrameObjectOffsets's built-in stack alignment, by having + // targetHandlesStackFrameRounding return true. + + // Add the extra call frame stack size, if needed. (This is the same + // code as in PrologEpilogInserter, but also gets disabled by + // targetHandlesStackFrameRounding) + if (MFI.adjustsStack() && hasReservedCallFrame(MF)) + NumBytes += MFI.getMaxCallFrameSize(); + + // Adds the VE subtarget-specific spill area to the stack + // size. Also ensures target-required alignment. + NumBytes = Subtarget.getAdjustedFrameSize(NumBytes); + + // Finally, ensure that the size is sufficiently aligned for the + // data on the stack. + if (MFI.getMaxAlignment() > 0) { + NumBytes = alignTo(NumBytes, MFI.getMaxAlignment()); + } + + // Update stack size with corrected value. + MFI.setStackSize(NumBytes); + + // emit Prologue instructions to save %lr + emitPrologueInsns(MF, MBB, MBBI, NumBytes, true); + + // emit stack adjust instructions + emitSPAdjustment(MF, MBB, MBBI, -NumBytes); + + // emit stack extend instructions + emitSPExtend(MF, MBB, MBBI, -NumBytes); + + unsigned regFP = RegInfo.getDwarfRegNum(VE::SX9, true); + + // Emit ".cfi_def_cfa_register 30". + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP)); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + + // Emit ".cfi_window_save". + CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); +} + +MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (!hasReservedCallFrame(MF)) { + MachineInstr &MI = *I; + int Size = MI.getOperand(0).getImm(); + if (MI.getOpcode() == VE::ADJCALLSTACKDOWN) + Size = -Size; + + if (Size) + emitSPAdjustment(MF, MBB, I, Size); + } + return MBB.erase(I); +} + +void VEFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + DebugLoc dl = MBBI->getDebugLoc(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + + int NumBytes = (int)MFI.getStackSize(); + + // emit Epilogue instructions to restore %lr + emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true); +} + +bool VEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { + // Reserve call frame if there are no variable sized objects on the stack. + return !MF.getFrameInfo().hasVarSizedObjects(); +} + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +bool VEFrameLowering::hasFP(const MachineFunction &MF) const { + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + + const MachineFrameInfo &MFI = MF.getFrameInfo(); + return MF.getTarget().Options.DisableFramePointerElim(MF) || + RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || + MFI.isFrameAddressTaken(); +} + +int VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const { + // Addressable stack objects are accessed using neg. offsets from + // %fp, or positive offsets from %sp. + int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI); + FrameReg = VE::SX11; // %sp + return FrameOffset + MF.getFrameInfo().getStackSize(); +} + +bool VEFrameLowering::isLeafProc(MachineFunction &MF) const { + + MachineRegisterInfo &MRI = MF.getRegInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + + return !(MFI.hasCalls() // has calls + || MRI.isPhysRegUsed(VE::SX18) // Too many registers needed + // (s18 is first CSR) + || MRI.isPhysRegUsed(VE::SX11) // %sp is used + || hasFP(MF)); // need %fp +} + +void VEFrameLowering::determineCalleeSaves(MachineFunction &MF, + BitVector &SavedRegs, + RegScavenger *RS) const { + TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); + + assert(isLeafProc(MF) && "TODO implement for non-leaf procs"); +} diff --git a/llvm/lib/Target/VE/VEISelDAGToDAG.cpp b/llvm/lib/Target/VE/VEISelDAGToDAG.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEISelDAGToDAG.cpp @@ -0,0 +1,70 @@ +//===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===// +// +// 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 defines an instruction selector for the VE target. +// +//===----------------------------------------------------------------------===// + +#include "VETargetMachine.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------===// +/// VEDAGToDAGISel - VE specific code to select VE machine +/// instructions for SelectionDAG operations. +/// +namespace { +class VEDAGToDAGISel : public SelectionDAGISel { + /// Subtarget - Keep a pointer to the VE Subtarget around so that we can + /// make the right decision when generating code for different targets. + const VESubtarget *Subtarget; + +public: + explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {} + + bool runOnMachineFunction(MachineFunction &MF) override { + Subtarget = &MF.getSubtarget(); + return SelectionDAGISel::runOnMachineFunction(MF); + } + + void Select(SDNode *N) override; + + StringRef getPassName() const override { + return "VE DAG->DAG Pattern Instruction Selection"; + } + + // Include the pieces autogenerated from the target description. +#include "VEGenDAGISel.inc" +}; +} // end anonymous namespace + +void VEDAGToDAGISel::Select(SDNode *N) { + SDLoc dl(N); + if (N->isMachineOpcode()) { + N->setNodeId(-1); + return; // Already selected. + } + + SelectCode(N); +} + +/// createVEISelDag - This pass converts a legalized DAG into a +/// VE-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) { + return new VEDAGToDAGISel(TM); +} diff --git a/llvm/lib/Target/VE/VEISelLowering.h b/llvm/lib/Target/VE/VEISelLowering.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEISelLowering.h @@ -0,0 +1,62 @@ +//===-- VEISelLowering.h - VE DAG Lowering Interface ------------*- 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 defines the interfaces that VE uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_VEISELLOWERING_H +#define LLVM_LIB_TARGET_VE_VEISELLOWERING_H + +#include "VE.h" +#include "llvm/CodeGen/TargetLowering.h" + +namespace llvm { +class VESubtarget; + +namespace VEISD { +enum NodeType : unsigned { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + RET_FLAG, // Return with a flag operand. +}; +} + +class VETargetLowering : public TargetLowering { + const VESubtarget *Subtarget; + +public: + VETargetLowering(const TargetMachine &TM, const VESubtarget &STI); + + const char *getTargetNodeName(unsigned Opcode) const override; + + Register getRegisterByName(const char *RegName, LLT VT, + const MachineFunction &MF) const override; + + /// getSetCCResultType - Return the ISD::SETCC ValueType + EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, + EVT VT) const override; + + SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl &Ins, + const SDLoc &dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const override; + + bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, + bool isVarArg, + const SmallVectorImpl &ArgsFlags, + LLVMContext &Context) const override; + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, const SDLoc &dl, + SelectionDAG &DAG) const override; +}; +} // namespace llvm + +#endif // VE_ISELLOWERING_H diff --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEISelLowering.cpp @@ -0,0 +1,138 @@ +//===-- VEISelLowering.cpp - VE DAG Lowering Implementation ---------------===// +// +// 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 implements the interfaces that VE uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "VEISelLowering.h" +#include "VERegisterInfo.h" +#include "VETargetMachine.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/KnownBits.h" +using namespace llvm; + +#define DEBUG_TYPE "ve-lower" + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "VEGenCallingConv.inc" + +bool VETargetLowering::CanLowerReturn( + CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, + const SmallVectorImpl &Outs, LLVMContext &Context) const { + assert(!IsVarArg && "TODO implement var args"); + assert(Outs.empty() && "TODO implement return values"); + return true; // TODO support more than 'ret void' +} + +SDValue +VETargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SDLoc &DL, SelectionDAG &DAG) const { + assert(!IsVarArg && "TODO implement var args"); + assert(Outs.empty() && "TODO implement return values"); + assert(OutVals.empty() && "TODO implement return values"); + + // SDValue Flag; + SmallVector RetOps(1, Chain); + RetOps[0] = Chain; // Update chain. + return DAG.getNode(VEISD::RET_FLAG, DL, MVT::Other, RetOps); +} + +SDValue VETargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl &InVals) const { + assert(!IsVarArg && "TODO implement var args"); + assert(Ins.empty() && "TODO implement input arguments"); + return Chain; +} + +// FIXME? Maybe this could be a TableGen attribute on some registers and +// this table could be generated automatically from RegInfo. +Register VETargetLowering::getRegisterByName(const char *RegName, LLT VT, + const MachineFunction &MF) const { + unsigned Reg = StringSwitch(RegName) + .Case("sp", VE::SX11) // Stack pointer + .Case("fp", VE::SX9) // Frame pointer + .Case("sl", VE::SX8) // Stack limit + .Case("lr", VE::SX10) // Link regsiter + .Case("tp", VE::SX14) // Thread pointer + .Case("outer", VE::SX12) // Outer regiser + .Case("info", VE::SX17) // Info area register + .Case("got", VE::SX15) // Global offset table register + .Case("plt", VE::SX16) // Procedure linkage table register + .Default(0); + + if (Reg) + return Reg; + + report_fatal_error("Invalid register name global variable"); +} + +//===----------------------------------------------------------------------===// +// TargetLowering Implementation +//===----------------------------------------------------------------------===// + +VETargetLowering::VETargetLowering(const TargetMachine &TM, + const VESubtarget &STI) + : TargetLowering(TM), Subtarget(&STI) { + // Instructions which use registers as conditionals examine all the + // bits (as does the pseudo SELECT_CC expansion). I don't think it + // matters much whether it's ZeroOrOneBooleanContent, or + // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the + // former. + setBooleanContents(ZeroOrOneBooleanContent); + setBooleanVectorContents(ZeroOrOneBooleanContent); + + // Set up the register classes. + addRegisterClass(MVT::i64, &VE::I64RegClass); + + setStackPointerRegisterToSaveRestore(VE::SX11); + + // Set function alignment to 16 bytes + setMinFunctionAlignment(Align(16)); + + // VE stores all argument by 8 bytes alignment + setMinStackArgumentAlignment(Align(8)); + + computeRegisterProperties(Subtarget->getRegisterInfo()); +} + +const char *VETargetLowering::getTargetNodeName(unsigned Opcode) const { + switch ((VEISD::NodeType)Opcode) { + case VEISD::FIRST_NUMBER: + break; + case VEISD::RET_FLAG: + return "VEISD::RET_FLAG"; + } + return nullptr; +} + +EVT VETargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, + EVT VT) const { + return MVT::i64; +} diff --git a/llvm/lib/Target/VE/VEInstrFormats.td b/llvm/lib/Target/VE/VEInstrFormats.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEInstrFormats.td @@ -0,0 +1,75 @@ +//===-- VEInstrFormats.td - VE Instruction Formats ---------*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +class InstVE pattern> + : Instruction { + field bits<64> Inst; + + let Namespace = "VE"; + let Size = 8; + + bits<8> op; + let Inst{0-7} = op; + + dag OutOperandList = outs; + dag InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; + + let DecoderNamespace = "VE"; + field bits<64> SoftFail = 0; +} + +class RMopVal, dag outs, dag ins, string asmstr, list pattern=[]> + : InstVE { + bits<1> cx = 0; + bits<7> sx; + bits<1> cy = 0; + bits<7> sy; + bits<1> cz = 0; + bits<7> sz; + bits<32> imm32 = 0; + let op = opVal; + let Inst{15} = cx; + let Inst{14-8} = sx; + let Inst{23} = cy; + let Inst{22-16} = sy; + let Inst{31} = cz; + let Inst{30-24} = sz; + let Inst{63-32} = imm32; +} + +class RRopVal, dag outs, dag ins, string asmstr> + : RM { + bits<1> cw = 0; + bits<1> cw2 = 0; + bits<4> cfw = 0; + let imm32{0-23} = 0; + let imm32{24} = cw; + let imm32{25} = cw2; + let imm32{26-27} = 0; + let imm32{28-31} = cfw; +} + +class CFopVal, dag outs, dag ins, string asmstr, list pattern=[]> + : RM { + bits<1> cx2; + bits<2> bpf; + bits<4> cf; + let cx = 0; + let sx{6} = cx2; + let sx{5-4} = bpf; + let sx{3-0} = cf; +} + +// Pseudo instructions. +class Pseudo pattern=[]> + : InstVE { + let isCodeGenOnly = 1; + let isPseudo = 1; +} diff --git a/llvm/lib/Target/VE/VEInstrInfo.h b/llvm/lib/Target/VE/VEInstrInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEInstrInfo.h @@ -0,0 +1,48 @@ +//===-- VEInstrInfo.h - VE Instruction Information --------------*- 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 contains the VE implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_VEINSTRINFO_H +#define LLVM_LIB_TARGET_VE_VEINSTRINFO_H + +#include "VERegisterInfo.h" +#include "llvm/CodeGen/TargetInstrInfo.h" + +#define GET_INSTRINFO_HEADER +#include "VEGenInstrInfo.inc" + +namespace llvm { + +class VESubtarget; + +class VEInstrInfo : public VEGenInstrInfo { + const VERegisterInfo RI; + const VESubtarget &Subtarget; + virtual void anchor(); + +public: + explicit VEInstrInfo(VESubtarget &ST); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + const VERegisterInfo &getRegisterInfo() const { return RI; } + + // Lower pseudo instructions after register allocation. + bool expandPostRAPseudo(MachineInstr &MI) const override; + + bool expandExtendStackPseudo(MachineInstr &MI) const; +}; + +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/VE/VEInstrInfo.cpp b/llvm/lib/Target/VE/VEInstrInfo.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEInstrInfo.cpp @@ -0,0 +1,126 @@ +//===-- VEInstrInfo.cpp - VE Instruction Information ----------------------===// +// +// 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 contains the VE implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "VEInstrInfo.h" +#include "VE.h" +#include "VESubtarget.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" + +#define DEBUG_TYPE "ve" + +using namespace llvm; + +#define GET_INSTRINFO_CTOR_DTOR +#include "VEGenInstrInfo.inc" + +// Pin the vtable to this file. +void VEInstrInfo::anchor() {} + +VEInstrInfo::VEInstrInfo(VESubtarget &ST) + : VEGenInstrInfo(VE::ADJCALLSTACKDOWN, VE::ADJCALLSTACKUP), RI(), + Subtarget(ST) {} + +bool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { + switch (MI.getOpcode()) { + case VE::EXTEND_STACK: { + return expandExtendStackPseudo(MI); + } + case VE::EXTEND_STACK_GUARD: { + MI.eraseFromParent(); // The pseudo instruction is gone now. + return true; + } + } + return false; +} + +bool VEInstrInfo::expandExtendStackPseudo(MachineInstr &MI) const { + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + const VEInstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + DebugLoc dl = MBB.findDebugLoc(MI); + + // Create following instructions and multiple basic blocks. + // + // thisBB: + // brge.l.t %sp, %sl, sinkBB + // syscallBB: + // ld %s61, 0x18(, %tp) // load param area + // or %s62, 0, %s0 // spill the value of %s0 + // lea %s63, 0x13b // syscall # of grow + // shm.l %s63, 0x0(%s61) // store syscall # at addr:0 + // shm.l %sl, 0x8(%s61) // store old limit at addr:8 + // shm.l %sp, 0x10(%s61) // store new limit at addr:16 + // monc // call monitor + // or %s0, 0, %s62 // restore the value of %s0 + // sinkBB: + + // Create new MBB + MachineBasicBlock *BB = &MBB; + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineBasicBlock *syscallMBB = MF.CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = MF.CreateMachineBasicBlock(LLVM_BB); + MachineFunction::iterator It = ++(BB->getIterator()); + MF.insert(It, syscallMBB); + MF.insert(It, sinkMBB); + + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), BB, + std::next(std::next(MachineBasicBlock::iterator(MI))), + BB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(BB); + + // Next, add the true and fallthrough blocks as its successors. + BB->addSuccessor(syscallMBB); + BB->addSuccessor(sinkMBB); + BuildMI(BB, dl, TII.get(VE::BCRLrr)) + .addImm(VECC::CC_IGE) + .addReg(VE::SX11) // %sp + .addReg(VE::SX8) // %sl + .addMBB(sinkMBB); + + BB = syscallMBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + BuildMI(BB, dl, TII.get(VE::LDSri), VE::SX61).addReg(VE::SX14).addImm(0x18); + BuildMI(BB, dl, TII.get(VE::ORri), VE::SX62).addReg(VE::SX0).addImm(0); + BuildMI(BB, dl, TII.get(VE::LEAzzi), VE::SX63).addImm(0x13b); + BuildMI(BB, dl, TII.get(VE::SHMri)) + .addReg(VE::SX61) + .addImm(0) + .addReg(VE::SX63); + BuildMI(BB, dl, TII.get(VE::SHMri)) + .addReg(VE::SX61) + .addImm(8) + .addReg(VE::SX8); + BuildMI(BB, dl, TII.get(VE::SHMri)) + .addReg(VE::SX61) + .addImm(16) + .addReg(VE::SX11); + BuildMI(BB, dl, TII.get(VE::MONC)); + + BuildMI(BB, dl, TII.get(VE::ORri), VE::SX0).addReg(VE::SX62).addImm(0); + + MI.eraseFromParent(); // The pseudo instruction is gone now. + return true; +} diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEInstrInfo.td @@ -0,0 +1,298 @@ +//===-- VEInstrInfo.td - Target Description for VE Target -----------------===// +// +// 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 describes the VE instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// + +include "VEInstrFormats.td" + +//===----------------------------------------------------------------------===// +// Feature predicates. +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction Pattern Stuff +//===----------------------------------------------------------------------===// + +def simm7 : PatLeaf<(imm), [{ return isInt<7>(N->getSExtValue()); }]>; +def simm32 : PatLeaf<(imm), [{ return isInt<32>(N->getSExtValue()); }]>; +def uimm6 : PatLeaf<(imm), [{ return isUInt<6>(N->getZExtValue()); }]>; +def LO32 : SDNodeXFormgetTargetConstant((unsigned)(N->getZExtValue() & 0xffffffff), + SDLoc(N), MVT::i32); +}]>; + +def HI32 : SDNodeXFormgetTargetConstant((unsigned)(N->getZExtValue() >> 32), + SDLoc(N), MVT::i32); +}]>; + +// ASX format of memory address +def MEMri : Operand { + let PrintMethod = "printMemASXOperand"; + let MIOperandInfo = (ops ptr_rc, i64imm); +} + +// AS format of memory address +def MEMASri : Operand { + let PrintMethod = "printMemASOperand"; + let MIOperandInfo = (ops ptr_rc, i64imm); +} + +// Branch targets have OtherVT type. +def brtarget32 : Operand { + let EncoderMethod = "getBranchTarget32OpValue"; +} + +def simm7Op64 : Operand { + let DecoderMethod = "DecodeSIMM7"; +} + +def simm32Op64 : Operand { + let DecoderMethod = "DecodeSIMM32"; +} + +def uimm6Op64 : Operand { + let DecoderMethod = "DecodeUIMM6"; +} + +// Operand for printing out a condition code. +let PrintMethod = "printCCOperand" in + def CCOp : Operand; + +// These are target-independent nodes, but have target-specific formats. +def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i64>, + SDTCisVT<1, i64> ]>; +def SDT_SPCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i64>, + SDTCisVT<1, i64> ]>; + +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_SPCallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_SPCallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +// def SDT_SPCall : SDTypeProfile<0, -1, [SDTCisVT<0, i64>]>; + +def retflag : SDNode<"VEISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +//===----------------------------------------------------------------------===// +// VE Flag Conditions +//===----------------------------------------------------------------------===// + +// Note that these values must be kept in sync with the CCOp::CondCode enum +// values. +class CC_VAL : PatLeaf<(i32 N)>; +def CC_IG : CC_VAL< 0>; // Greater +def CC_IL : CC_VAL< 1>; // Less +def CC_INE : CC_VAL< 2>; // Not Equal +def CC_IEQ : CC_VAL< 3>; // Equal +def CC_IGE : CC_VAL< 4>; // Greater or Equal +def CC_ILE : CC_VAL< 5>; // Less or Equal +def CC_AF : CC_VAL< 6>; // Always false +def CC_G : CC_VAL< 7>; // Greater +def CC_L : CC_VAL< 8>; // Less +def CC_NE : CC_VAL< 9>; // Not Equal +def CC_EQ : CC_VAL<10>; // Equal +def CC_GE : CC_VAL<11>; // Greater or Equal +def CC_LE : CC_VAL<12>; // Less or Equal +def CC_NUM : CC_VAL<13>; // Number +def CC_NAN : CC_VAL<14>; // NaN +def CC_GNAN : CC_VAL<15>; // Greater or NaN +def CC_LNAN : CC_VAL<16>; // Less or NaN +def CC_NENAN : CC_VAL<17>; // Not Equal or NaN +def CC_EQNAN : CC_VAL<18>; // Equal or NaN +def CC_GENAN : CC_VAL<19>; // Greater or Equal or NaN +def CC_LENAN : CC_VAL<20>; // Less or Equal or NaN +def CC_AT : CC_VAL<21>; // Always true + +//===----------------------------------------------------------------------===// +// VE Multiclasses for common instruction formats +//===----------------------------------------------------------------------===// + +multiclass RMmopc, + RegisterClass RC, ValueType Ty, Operand immOp, Operand immOp2> { + def rri : RM< + opc, (outs RC:$sx), (ins RC:$sy, RC:$sz, immOp2:$imm32), + !strconcat(opcStr, " $sx, ${imm32}($sy, ${sz})")> { + let cy = 1; + let cz = 1; + let hasSideEffects = 0; + } + def zzi : RM< + opc, (outs RC:$sx), (ins immOp2:$imm32), + !strconcat(opcStr, " $sx, $imm32")> { + let cy = 0; + let sy = 0; + let cz = 0; + let sz = 0; + let hasSideEffects = 0; + } +} + +// Multiclass for RR type instructions + +multiclass RRmrropc, + RegisterClass RCo, ValueType Tyo, + RegisterClass RCi, ValueType Tyi> { + def rr : RR + { let cy = 1; let cz = 1; let hasSideEffects = 0; } +} + +multiclass RRmriopc, + RegisterClass RCo, ValueType Tyo, + RegisterClass RCi, ValueType Tyi, Operand immOp> { + // VE calculates (OpNode $sy, $sz), but llvm requires to have immediate + // in RHS, so we use following definition. + def ri : RR + { let cy = 0; let cz = 1; let hasSideEffects = 0; } +} + +multiclass RRmizopc, + RegisterClass RCo, ValueType Tyo, + RegisterClass RCi, ValueType Tyi, Operand immOp> { + def zi : RR + { let cy = 0; let cz = 0; let sz = 0; let hasSideEffects = 0; } +} + +multiclass RRNDmrmopc, + RegisterClass RCo, ValueType Tyo, + RegisterClass RCi, ValueType Tyi, Operand immOp2> { + def rm0 : RR { + let cy = 1; + let cz = 0; + let sz{6} = 1; + // (guess) tblgen conservatively assumes hasSideEffects when + // it fails to infer from a pattern. + let hasSideEffects = 0; + } +} + +// Used by add, mul, div, and similar commutative instructions +// The order of operands are "$sx, $sy, $sz" + +multiclass RRmopc, + RegisterClass RC, ValueType Ty, Operand immOp, Operand immOp2> : + RRmrr, + RRmri, + RRmiz, + RRNDmrm; + +// Branch multiclass +let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in +multiclass BCRm opc, + RegisterClass RC, ValueType Ty, Operand immOp, Operand immOp2> { + def rr : CF< + opc, (outs), + (ins CCOp:$cf, RC:$sy, RC:$sz, brtarget32:$imm32), + !strconcat(opcStr, " $sy, $sz, $imm32")> { + let cy = 1; + let cz = 1; + let hasSideEffects = 0; + } +} + + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +// LEA and LEASL instruction (load 32 bit imm to low or high part) +let cx = 0 in +defm LEA : RMm<"lea", 0x06, I64, i64, simm7Op64, simm32Op64>; +let cx = 1 in +defm LEASL : RMm<"lea.sl", 0x06, I64, i64, simm7Op64, simm32Op64>; + +// 5.3.2.2. Fixed-Point Arithmetic Operation Instructions + +// ADX instruction +let cx = 0 in +defm ADX : RRm<"adds.l", 0x59, I64, i64, simm7Op64, uimm6Op64>; + +// 5.3.2.3. Logical Arithmetic Operation Instructions + +let cx = 0 in { + defm AND : RRm<"and", 0x44, I64, i64, simm7Op64, uimm6Op64>; + defm OR : RRm<"or", 0x45, I64, i64, simm7Op64, uimm6Op64>; +} + +// Load and Store instructions +// As 1st step, only uses sz and imm32 to represent $addr +let mayLoad = 1, hasSideEffects = 0 in { +let cy = 0, sy = 0, cz = 1 in { +let cx = 0 in +def LDSri : RM< + 0x01, (outs I64:$sx), (ins MEMri:$addr), + "ld $sx, $addr">; +} +} + +let mayStore = 1, hasSideEffects = 0 in { +let cx = 0, cy = 0, sy = 0, cz = 1 in { +def STSri : RM< + 0x11, (outs), (ins MEMri:$addr, I64:$sx), + "st $sx, $addr">; +} +} + +// Return instruction is also a special case of jump. +let cx = 0, cx2 = 0, bpf = 0 /* NONE */, cf = 15 /* AT */, cy = 0, sy = 0, + cz = 1, sz = 0x10 /* SX10 */, imm32 = 0, Uses = [SX10], + isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, + isCodeGenOnly = 1, hasSideEffects = 0 in +def RET : CF< + 0x19, (outs), (ins), + "b.l (,%lr)", + [(retflag)]>; + +// Branch instruction +let cx = 0, cx2 = 0, bpf = 0 /* NONE */ in +defm BCRL : BCRm<"br${cf}.l", "br.l", 0x18, I64, i64, simm7Op64, uimm6Op64>; + +let cx = 0, cy = 0, cz = 1, hasSideEffects = 0 in { +let sy = 3 in +def SHMri : RM< + 0x31, (outs), (ins MEMASri:$addr, I64:$sx), + "shm.l $sx, $addr">; +} + +let cx = 0, sx = 0, cy = 0, sy = 0, cz = 0, sz = 0, hasSideEffects = 0 in +def MONC : RR< + 0x3F, (outs), (ins), + "monc">; + +//===----------------------------------------------------------------------===// +// Pseudo Instructions +//===----------------------------------------------------------------------===// + +let Defs = [SX11], Uses = [SX11], hasSideEffects = 0 in { +def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt, i64imm:$amt2), + "# ADJCALLSTACKDOWN $amt, $amt2", + [(callseq_start timm:$amt, timm:$amt2)]>; +def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), + "# ADJCALLSTACKUP $amt1", + [(callseq_end timm:$amt1, timm:$amt2)]>; +} + +let Defs = [SX8], Uses = [SX8, SX11], hasSideEffects = 0 in +def EXTEND_STACK : Pseudo<(outs), (ins), + "# EXTEND STACK", + []>; +let hasSideEffects = 0 in +def EXTEND_STACK_GUARD : Pseudo<(outs), (ins), + "# EXTEND STACK GUARD", + []>; diff --git a/llvm/lib/Target/VE/VEMCInstLower.cpp b/llvm/lib/Target/VE/VEMCInstLower.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEMCInstLower.cpp @@ -0,0 +1,70 @@ +//===-- VEMCInstLower.cpp - Convert VE MachineInstr to MCInst -------------===// +// +// 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 contains code to lower VE MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "VE.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/Mangler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" + +using namespace llvm; + +static MCOperand LowerSymbolOperand(const MachineInstr *MI, + const MachineOperand &MO, + const MCSymbol *Symbol, AsmPrinter &AP) { + + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, AP.OutContext); + return MCOperand::createExpr(MCSym); +} + +static MCOperand LowerOperand(const MachineInstr *MI, const MachineOperand &MO, + AsmPrinter &AP) { + switch (MO.getType()) { + default: + report_fatal_error("unsupported operand type"); + break; + + case MachineOperand::MO_Register: + if (MO.isImplicit()) + break; + return MCOperand::createReg(MO.getReg()); + + case MachineOperand::MO_Immediate: + return MCOperand::createImm(MO.getImm()); + + case MachineOperand::MO_MachineBasicBlock: + return LowerSymbolOperand(MI, MO, MO.getMBB()->getSymbol(), AP); + + case MachineOperand::MO_RegisterMask: + break; + } + return MCOperand(); +} + +void llvm::LowerVEMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, + AsmPrinter &AP) { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + MCOperand MCOp = LowerOperand(MI, MO, AP); + + if (MCOp.isValid()) + OutMI.addOperand(MCOp); + } +} diff --git a/llvm/lib/Target/VE/VERegisterInfo.h b/llvm/lib/Target/VE/VERegisterInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VERegisterInfo.h @@ -0,0 +1,56 @@ +//===-- VERegisterInfo.h - VE Register Information Impl ---------*- 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 contains the VE implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_VEREGISTERINFO_H +#define LLVM_LIB_TARGET_VE_VEREGISTERINFO_H + +#include "llvm/CodeGen/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "VEGenRegisterInfo.inc" + +namespace llvm { +struct VERegisterInfo : public VEGenRegisterInfo { +private: + // VLS register class's Pressure Set ID. + unsigned VLSPSetID; + +public: + VERegisterInfo(); + + /// Code Generation virtual methods... + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const override; + const uint32_t *getNoPreservedMask() const override; + + BitVector getReservedRegs(const MachineFunction &MF) const override; + bool isConstantPhysReg(unsigned PhysReg) const override; + + const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, + unsigned Kind) const override; + + void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, + unsigned FIOperandNum, + RegScavenger *RS = nullptr) const override; + + Register getFrameRegister(const MachineFunction &MF) const override; + + bool canRealignStack(const MachineFunction &MF) const override; + + unsigned getRegPressureSetLimit(const MachineFunction &MF, + unsigned Idx) const override; +}; + +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/VE/VERegisterInfo.cpp b/llvm/lib/Target/VE/VERegisterInfo.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VERegisterInfo.cpp @@ -0,0 +1,138 @@ +//===-- VERegisterInfo.cpp - VE Register Information ----------------------===// +// +// 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 contains the VE implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "VERegisterInfo.h" +#include "VE.h" +#include "VESubtarget.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +#define GET_REGINFO_TARGET_DESC +#include "VEGenRegisterInfo.inc" + +// VE uses %s10 == %lp to keep return address +VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {} + +const MCPhysReg * +VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + return CSR_SaveList; +} + +const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const { + return CSR_RegMask; +} + +const uint32_t *VERegisterInfo::getNoPreservedMask() const { + return CSR_NoRegs_RegMask; +} + +BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + Reserved.set(VE::SX8); // stack limit + Reserved.set(VE::SX9); // frame pointer + Reserved.set(VE::SX10); // link register (return address) + Reserved.set(VE::SX11); // stack pointer + + Reserved.set(VE::SX12); // outer register + Reserved.set(VE::SX13); // id register for dynamic linker + + Reserved.set(VE::SX14); // thread pointer + Reserved.set(VE::SX15); // global offset table register + Reserved.set(VE::SX16); // procedure linkage table register + Reserved.set(VE::SX17); // linkage-area register + + // sx18-sx33 are callee-saved registers + // sx34-sx63 are temporary registers + + return Reserved; +} + +bool VERegisterInfo::isConstantPhysReg(unsigned PhysReg) const { return false; } + +const TargetRegisterClass * +VERegisterInfo::getPointerRegClass(const MachineFunction &MF, + unsigned Kind) const { + return &VE::I64RegClass; +} + +static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II, + MachineInstr &MI, const DebugLoc &dl, + unsigned FIOperandNum, int Offset, unsigned FramePtr) { + // Replace frame index with a frame pointer reference directly. + // VE has 32 bit offset field, so no need to expand a target instruction. + // Directly encode it. + MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); +} + +void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { + assert(SPAdj == 0 && "Unexpected"); + + MachineInstr &MI = *II; + DebugLoc dl = MI.getDebugLoc(); + int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); + MachineFunction &MF = *MI.getParent()->getParent(); + const VEFrameLowering *TFI = getFrameLowering(MF); + + unsigned FrameReg; + int Offset; + Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg); + + Offset += MI.getOperand(FIOperandNum + 1).getImm(); + + replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg); +} + +unsigned VERegisterInfo::getRegPressureSetLimit(const MachineFunction &MF, + unsigned Idx) const { + return VEGenRegisterInfo::getRegPressureSetLimit(MF, Idx); +} + +Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const { + return VE::SX9; +} + +// VE has no architectural need for stack realignment support, +// except that LLVM unfortunately currently implements overaligned +// stack objects by depending upon stack realignment support. +// If that ever changes, this can probably be deleted. +bool VERegisterInfo::canRealignStack(const MachineFunction &MF) const { + if (!TargetRegisterInfo::canRealignStack(MF)) + return false; + + // VE always has a fixed frame pointer register, so don't need to + // worry about needing to reserve it. [even if we don't have a frame + // pointer for our frame, it still cannot be used for other things, + // or register window traps will be SADNESS.] + + // If there's a reserved call frame, we can use VE to access locals. + if (getFrameLowering(MF)->hasReservedCallFrame(MF)) + return true; + + // Otherwise, we'd need a base pointer, but those aren't implemented + // for VE at the moment. + + return false; +} diff --git a/llvm/lib/Target/VE/VERegisterInfo.td b/llvm/lib/Target/VE/VERegisterInfo.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VERegisterInfo.td @@ -0,0 +1,37 @@ +//===-- VERegisterInfo.td - VE Register defs ---------------*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the VE register file +//===----------------------------------------------------------------------===// + +class VEReg Enc, string n> : Register { + let HWEncoding{15-7} = 0; + let HWEncoding{6-0} = Enc; + let Namespace = "VE"; +} + +// Registers are identified with 7-bit ID numbers. +// R - 64-bit integer or floating-point registers +class R Enc, string n, list subregs = [], + list aliases = []>: VEReg { + let SubRegs = subregs; + let Aliases = aliases; +} + +// Generic integer registers - 64 bits wide +foreach I = 0-63 in + def SX#I : R, + DwarfRegNum<[I]>; + +// Register classes. +// +// The register order is defined in terms of the preferred +// allocation order. +def I64 : RegisterClass<"VE", [i64], 64, + (sequence "SX%u", 0, 63)>; diff --git a/llvm/lib/Target/VE/VESubtarget.h b/llvm/lib/Target/VE/VESubtarget.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VESubtarget.h @@ -0,0 +1,73 @@ +//===-- VESubtarget.h - Define Subtarget for the VE -------------*- 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 VE specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_VESUBTARGET_H +#define LLVM_LIB_TARGET_VE_VESUBTARGET_H + +#include "VEFrameLowering.h" +#include "VEISelLowering.h" +#include "VEInstrInfo.h" +#include "llvm/CodeGen/SelectionDAGTargetInfo.h" +#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DataLayout.h" +#include + +#define GET_SUBTARGETINFO_HEADER +#include "VEGenSubtargetInfo.inc" + +namespace llvm { +class StringRef; + +class VESubtarget : public VEGenSubtargetInfo { + Triple TargetTriple; + virtual void anchor(); + + VEInstrInfo InstrInfo; + VETargetLowering TLInfo; + SelectionDAGTargetInfo TSInfo; + VEFrameLowering FrameLowering; + +public: + VESubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, + const TargetMachine &TM); + + const VEInstrInfo *getInstrInfo() const override { return &InstrInfo; } + const TargetFrameLowering *getFrameLowering() const override { + return &FrameLowering; + } + const VERegisterInfo *getRegisterInfo() const override { + return &InstrInfo.getRegisterInfo(); + } + const VETargetLowering *getTargetLowering() const override { return &TLInfo; } + const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { + return &TSInfo; + } + + bool enableMachineScheduler() const override; + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + VESubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); + + /// Given a actual stack size as determined by FrameInfo, this function + /// returns adjusted framesize which includes space for register window + /// spills and arguments. + int getAdjustedFrameSize(int stackSize) const; + + bool isTargetLinux() const { return TargetTriple.isOSLinux(); } +}; + +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/VE/VESubtarget.cpp b/llvm/lib/Target/VE/VESubtarget.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VESubtarget.cpp @@ -0,0 +1,99 @@ +//===-- VESubtarget.cpp - VE Subtarget Information ------------------------===// +// +// 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 implements the VE specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#include "VESubtarget.h" +#include "VE.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "ve-subtarget" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "VEGenSubtargetInfo.inc" + +void VESubtarget::anchor() {} + +VESubtarget &VESubtarget::initializeSubtargetDependencies(StringRef CPU, + StringRef FS) { + // Determine default and user specified characteristics + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "ve"; + + // Parse features string. + ParseSubtargetFeatures(CPUName, FS); + + return *this; +} + +VESubtarget::VESubtarget(const Triple &TT, const std::string &CPU, + const std::string &FS, const TargetMachine &TM) + : VEGenSubtargetInfo(TT, CPU, FS), TargetTriple(TT), + InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), + FrameLowering(*this) {} + +int VESubtarget::getAdjustedFrameSize(int frameSize) const { + + // VE stack frame: + // + // +----------------------------------------+ + // | Locals and temporaries | + // +----------------------------------------+ + // | Parameter area for callee | + // 176(fp) | | + // +----------------------------------------+ + // | Register save area (RSA) for callee | + // | | + // 16(fp) | 20 * 8 bytes | + // +----------------------------------------+ + // 8(fp) | Return address | + // +----------------------------------------+ + // 0(fp) | Frame pointer of caller | + // --------+----------------------------------------+-------- + // | Locals and temporaries for callee | + // +----------------------------------------+ + // | Parameter area for callee of callee | + // +----------------------------------------+ + // 16(sp) | RSA for callee of callee | + // +----------------------------------------+ + // 8(sp) | Return address | + // +----------------------------------------+ + // 0(sp) | Frame pointer of callee | + // +----------------------------------------+ + + // RSA frame: + // +----------------------------------------------+ + // 168(fp) | %s33 | + // +----------------------------------------------+ + // | %s19...%s32 | + // +----------------------------------------------+ + // 48(fp) | %s18 | + // +----------------------------------------------+ + // 40(fp) | Linkage area register (%s17) | + // +----------------------------------------------+ + // 32(fp) | Procedure linkage table register (%plt=%s16) | + // +----------------------------------------------+ + // 24(fp) | Global offset table register (%got=%s15) | + // +----------------------------------------------+ + // 16(fp) | Thread pointer register (%tp=%s14) | + // +----------------------------------------------+ + + frameSize += 176; // for RSA, RA, and FP + frameSize = alignTo(frameSize, 16); // requires 16 bytes alignment + + return frameSize; +} + +bool VESubtarget::enableMachineScheduler() const { return true; } diff --git a/llvm/lib/Target/VE/VETargetMachine.h b/llvm/lib/Target/VE/VETargetMachine.h --- a/llvm/lib/Target/VE/VETargetMachine.h +++ b/llvm/lib/Target/VE/VETargetMachine.h @@ -13,17 +13,43 @@ #ifndef LLVM_LIB_TARGET_VE_VETARGETMACHINE_H #define LLVM_LIB_TARGET_VE_VETARGETMACHINE_H +#include "VEInstrInfo.h" +#include "VESubtarget.h" #include "llvm/Target/TargetMachine.h" namespace llvm { class VETargetMachine : public LLVMTargetMachine { + std::unique_ptr TLOF; + VESubtarget Subtarget; + // Hold Strings that can be free'd all together with VETargetMachine + // e.g.: "GCC_except_tableXX" string. + std::list StrList; + public: VETargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Optional RM, Optional CM, CodeGenOpt::Level OL, bool JIT); ~VETargetMachine() override; + + const VESubtarget *getSubtargetImpl() const { return &Subtarget; } + const VESubtarget *getSubtargetImpl(const Function &) const override { + return &Subtarget; + } + std::list *getStrList() const { + return const_cast *>(&StrList); + } + + // Pass Pipeline Configuration + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; + TargetLoweringObjectFile *getObjFileLowering() const override { + return TLOF.get(); + } + + bool isMachineVerifierClean() const override { return false; } + + TargetTransformInfo getTargetTransformInfo(const Function &F) override; }; } // namespace llvm diff --git a/llvm/lib/Target/VE/VETargetMachine.cpp b/llvm/lib/Target/VE/VETargetMachine.cpp --- a/llvm/lib/Target/VE/VETargetMachine.cpp +++ b/llvm/lib/Target/VE/VETargetMachine.cpp @@ -11,6 +11,11 @@ #include "VETargetMachine.h" #include "VE.h" +#include "VETargetTransformInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -47,16 +52,57 @@ return *RM; } +class VEELFTargetObjectFile : public TargetLoweringObjectFileELF { + void Initialize(MCContext &Ctx, const TargetMachine &TM) override { + TargetLoweringObjectFileELF::Initialize(Ctx, TM); + InitializeELF(TM.Options.UseInitArray); + } +}; + +static std::unique_ptr createTLOF() { + return std::make_unique(); +} + /// Create an Aurora VE architecture model -VETargetMachine::VETargetMachine( - const Target &T, const Triple &TT, StringRef CPU, StringRef FS, - const TargetOptions &Options, Optional RM, - Optional CM, CodeGenOpt::Level OL, bool JIT) - : LLVMTargetMachine( - T, computeDataLayout(TT), TT, CPU, FS, Options, - getEffectiveRelocModel(RM), - getEffectiveCodeModel(CM, CodeModel::Small), - OL) -{} +VETargetMachine::VETargetMachine(const Target &T, const Triple &TT, + StringRef CPU, StringRef FS, + const TargetOptions &Options, + Optional RM, + Optional CM, + CodeGenOpt::Level OL, bool JIT) + : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, + getEffectiveRelocModel(RM), + getEffectiveCodeModel(CM, CodeModel::Small), OL), + TLOF(createTLOF()), Subtarget(TT, CPU, FS, *this) { + initAsmInfo(); +} VETargetMachine::~VETargetMachine() {} + +TargetTransformInfo VETargetMachine::getTargetTransformInfo(const Function &F) { + return TargetTransformInfo(VETTIImpl(this, F)); +} + +namespace { +/// VE Code Generator Pass Configuration Options. +class VEPassConfig : public TargetPassConfig { +public: + VEPassConfig(VETargetMachine &TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + VETargetMachine &getVETargetMachine() const { + return getTM(); + } + + bool addInstSelector() override; +}; +} // namespace + +TargetPassConfig *VETargetMachine::createPassConfig(PassManagerBase &PM) { + return new VEPassConfig(*this, PM); +} + +bool VEPassConfig::addInstSelector() { + addPass(createVEISelDag(getVETargetMachine())); + return false; +} diff --git a/llvm/lib/Target/VE/VETargetTransformInfo.h b/llvm/lib/Target/VE/VETargetTransformInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VETargetTransformInfo.h @@ -0,0 +1,50 @@ +//===- VETargetTransformInfo.h - VE specific TTI ------*- 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// This file a TargetTransformInfo::Concept conforming object specific to the +/// VE target machine. It uses the target's detailed information to +/// provide more precise answers to certain TTI queries, while letting the +/// target independent and default TTI implementations handle the rest. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_VETARGETTRANSFORMINFO_H +#define LLVM_LIB_TARGET_VE_VETARGETTRANSFORMINFO_H + +#include "VE.h" +#include "VETargetMachine.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/CodeGen/BasicTTIImpl.h" + +namespace llvm { + +class VETTIImpl : public BasicTTIImplBase { + using BaseT = BasicTTIImplBase; + friend BaseT; + + const VESubtarget *ST; + const VETargetLowering *TLI; + + const VESubtarget *getST() const { return ST; } + const VETargetLowering *getTLI() const { return TLI; } + +public: + explicit VETTIImpl(const VETargetMachine *TM, const Function &F) + : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), + TLI(ST->getTargetLowering()) {} + + unsigned getNumberOfRegisters(unsigned ClassID) const { return 64; } + + unsigned getRegisterBitWidth(bool Vector) const { return 64; } + + unsigned getMinVectorRegisterBitWidth() const { return 64; } +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_VE_VETARGETTRANSFORMINFO_H diff --git a/llvm/test/CodeGen/VE/simple_prologue_epilogue.ll b/llvm/test/CodeGen/VE/simple_prologue_epilogue.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/VE/simple_prologue_epilogue.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s + +define void @func() { +; CHECK-LABEL: func: +; CHECK: # %bb.0: +; CHECK-NEXT: st %s9, (,%s11) +; CHECK-NEXT: st %s10, 8(,%s11) +; CHECK-NEXT: st %s15, 24(,%s11) +; CHECK-NEXT: st %s16, 32(,%s11) +; CHECK-NEXT: or %s9, 0, %s11 +; CHECK-NEXT: lea %s13, -176 +; CHECK-NEXT: and %s13, %s13, (32)0 +; CHECK-NEXT: lea.sl %s11, -1(%s11, %s13) +; CHECK-NEXT: brge.l %s11, %s8, .LBB0_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: ld %s61, 24(,%s14) +; CHECK-NEXT: or %s62, 0, %s0 +; CHECK-NEXT: lea %s63, 315 +; CHECK-NEXT: shm.l %s63, (%s61) +; CHECK-NEXT: shm.l %s8, 8(%s61) +; CHECK-NEXT: shm.l %s11, 16(%s61) +; CHECK-NEXT: monc +; CHECK-NEXT: or %s0, 0, %s62 +; CHECK-NEXT: .LBB0_2: +; CHECK-NEXT: or %s11, 0, %s9 +; CHECK-NEXT: ld %s16, 32(,%s11) +; CHECK-NEXT: ld %s15, 24(,%s11) +; CHECK-NEXT: ld %s10, 8(,%s11) +; CHECK-NEXT: ld %s9, (,%s11) +; CHECK-NEXT: b.l (,%lr) + ret void +}