From 00b66647dccd07e33b476122bd74f946a56b6fea Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Sat, 27 Jan 2024 01:37:03 +0300 Subject: [PATCH] [Xtensa] Initial codegen support from IR. Initial codegen support for IR tests. Added basic implementation of the TargetFrameLowering, MCInstLower, AsmPrinter, RegisterInfo, InstructionInfo, TargetLowering, SelectionDAGISel. --- llvm/lib/Target/Xtensa/CMakeLists.txt | 9 +++ llvm/lib/Target/Xtensa/Xtensa.h | 28 +++++++ llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp | 70 ++++++++++++++++ llvm/lib/Target/Xtensa/XtensaAsmPrinter.h | 46 +++++++++++ .../lib/Target/Xtensa/XtensaFrameLowering.cpp | 39 +++++++++ llvm/lib/Target/Xtensa/XtensaFrameLowering.h | 32 ++++++++ llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp | 79 +++++++++++++++++++ llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 58 ++++++++++++++ llvm/lib/Target/Xtensa/XtensaISelLowering.h | 41 ++++++++++ llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp | 27 +++++++ llvm/lib/Target/Xtensa/XtensaInstrInfo.h | 45 +++++++++++ llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp | 69 ++++++++++++++++ llvm/lib/Target/Xtensa/XtensaRegisterInfo.h | 56 +++++++++++++ llvm/lib/Target/Xtensa/XtensaSubtarget.cpp | 44 +++++++++++ llvm/lib/Target/Xtensa/XtensaSubtarget.h | 72 +++++++++++++++++ .../lib/Target/Xtensa/XtensaTargetMachine.cpp | 41 +++++++++- llvm/lib/Target/Xtensa/XtensaTargetMachine.h | 7 ++ llvm/test/CodeGen/Xtensa/lit.local.cfg | 2 + llvm/test/CodeGen/Xtensa/simple.ll | 5 ++ 19 files changed, 769 insertions(+), 1 deletion(-) create mode 100644 llvm/lib/Target/Xtensa/Xtensa.h create mode 100644 llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp create mode 100644 llvm/lib/Target/Xtensa/XtensaAsmPrinter.h create mode 100644 llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp create mode 100644 llvm/lib/Target/Xtensa/XtensaFrameLowering.h create mode 100644 llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp create mode 100644 llvm/lib/Target/Xtensa/XtensaISelLowering.cpp create mode 100644 llvm/lib/Target/Xtensa/XtensaISelLowering.h create mode 100644 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp create mode 100644 llvm/lib/Target/Xtensa/XtensaInstrInfo.h create mode 100644 llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp create mode 100644 llvm/lib/Target/Xtensa/XtensaRegisterInfo.h create mode 100644 llvm/lib/Target/Xtensa/XtensaSubtarget.cpp create mode 100644 llvm/lib/Target/Xtensa/XtensaSubtarget.h create mode 100644 llvm/test/CodeGen/Xtensa/lit.local.cfg create mode 100644 llvm/test/CodeGen/Xtensa/simple.ll diff --git a/llvm/lib/Target/Xtensa/CMakeLists.txt b/llvm/lib/Target/Xtensa/CMakeLists.txt index 7192f7392072b..2064511e75b82 100644 --- a/llvm/lib/Target/Xtensa/CMakeLists.txt +++ b/llvm/lib/Target/Xtensa/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_TARGET_DEFINITIONS Xtensa.td) tablegen(LLVM XtensaGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM XtensaGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM XtensaGenDAGISel.inc -gen-dag-isel) tablegen(LLVM XtensaGenDisassemblerTables.inc -gen-disassembler) tablegen(LLVM XtensaGenInstrInfo.inc -gen-instr-info) tablegen(LLVM XtensaGenMCCodeEmitter.inc -gen-emitter) @@ -13,6 +14,13 @@ tablegen(LLVM XtensaGenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(XtensaCommonTableGen) add_llvm_target(XtensaCodeGen + XtensaAsmPrinter.cpp + XtensaFrameLowering.cpp + XtensaInstrInfo.cpp + XtensaISelDAGToDAG.cpp + XtensaISelLowering.cpp + XtensaRegisterInfo.cpp + XtensaSubtarget.cpp XtensaTargetMachine.cpp LINK_COMPONENTS @@ -20,6 +28,7 @@ add_llvm_target(XtensaCodeGen CodeGen Core MC + SelectionDAG Support Target XtensaDesc diff --git a/llvm/lib/Target/Xtensa/Xtensa.h b/llvm/lib/Target/Xtensa/Xtensa.h new file mode 100644 index 0000000000000..da44e30f367fa --- /dev/null +++ b/llvm/lib/Target/Xtensa/Xtensa.h @@ -0,0 +1,28 @@ +//===- Xtensa.h - Top-level interface for Xtensa representation -*- 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 entry points for global functions defined in +// the LLVM Xtensa back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_XTENSA_XTENSA_H +#define LLVM_LIB_TARGET_XTENSA_XTENSA_H + +#include "MCTargetDesc/XtensaMCTargetDesc.h" +#include "llvm/PassRegistry.h" +#include "llvm/Support/CodeGen.h" + +namespace llvm { +class XtensaTargetMachine; +class FunctionPass; + +FunctionPass *createXtensaISelDag(XtensaTargetMachine &TM, + CodeGenOptLevel OptLevel); +} // namespace llvm +#endif // LLVM_LIB_TARGET_XTENSA_XTENSA_H diff --git a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp new file mode 100644 index 0000000000000..87dbf2eb5166c --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp @@ -0,0 +1,70 @@ +//===- XtensaAsmPrinter.cpp Xtensa LLVM Assembly Printer ------------------===// +// +// 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 Xtensa assembly language. +// +//===----------------------------------------------------------------------===// + +#include "XtensaAsmPrinter.h" +#include "TargetInfo/XtensaTargetInfo.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/TargetRegistry.h" + +using namespace llvm; + +void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) { + MCInst LoweredMI; + lowerToMCInst(MI, LoweredMI); + EmitToStreamer(*OutStreamer, LoweredMI); +} + +MCOperand XtensaAsmPrinter::lowerOperand(const MachineOperand &MO, + unsigned Offset) const { + MachineOperand::MachineOperandType MOTy = MO.getType(); + + switch (MOTy) { + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) + break; + return MCOperand::createReg(MO.getReg()); + case MachineOperand::MO_Immediate: + return MCOperand::createImm(MO.getImm() + Offset); + case MachineOperand::MO_RegisterMask: + break; + default: + report_fatal_error("unknown operand type"); + } + + return MCOperand(); +} + +void XtensaAsmPrinter::lowerToMCInst(const MachineInstr *MI, + MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + MCOperand MCOp = lowerOperand(MO); + + if (MCOp.isValid()) + OutMI.addOperand(MCOp); + } +} + +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() { + RegisterAsmPrinter A(getTheXtensaTarget()); +} diff --git a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.h b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.h new file mode 100644 index 0000000000000..dec2a1ee4954f --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.h @@ -0,0 +1,46 @@ +//===- XtensaAsmPrinter.h - Xtensa LLVM Assembly Printer --------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Xtensa Assembly printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAASMPRINTER_H +#define LLVM_LIB_TARGET_XTENSA_XTENSAASMPRINTER_H + +#include "XtensaTargetMachine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { +class MCStreamer; +class MachineBasicBlock; +class MachineInstr; +class Module; +class raw_ostream; + +class LLVM_LIBRARY_VISIBILITY XtensaAsmPrinter : public AsmPrinter { + const MCSubtargetInfo *STI; + +public: + explicit XtensaAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {} + + StringRef getPassName() const override { return "Xtensa Assembly Printer"; } + void emitInstruction(const MachineInstr *MI) override; + + // Lower MachineInstr MI to MCInst OutMI. + void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) const; + + // Return an MCOperand for MO. Return an empty operand if MO is implicit. + MCOperand lowerOperand(const MachineOperand &MO, unsigned Offset = 0) const; +}; +} // end namespace llvm + +#endif /* LLVM_LIB_TARGET_XTENSA_XTENSAASMPRINTER_H */ diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp new file mode 100644 index 0000000000000..2092a2d947f86 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp @@ -0,0 +1,39 @@ +//===- XtensaFrameLowering.cpp - Xtensa 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 Xtensa implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "XtensaFrameLowering.h" +#include "XtensaInstrInfo.h" +#include "XtensaSubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/IR/Function.h" + +using namespace llvm; + +XtensaFrameLowering::XtensaFrameLowering() + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0, + Align(4)) {} + +bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + return MF.getTarget().Options.DisableFramePointerElim(MF) || + MFI.hasVarSizedObjects(); +} + +void XtensaFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const {} + +void XtensaFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const {} diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h new file mode 100644 index 0000000000000..19e52310a99d9 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h @@ -0,0 +1,32 @@ +//===- XtensaFrameLowering.h - Define frame lowering for Xtensa --*- 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_XTENSA_XTENSAFRAMELOWERING_H +#define LLVM_LIB_TARGET_XTENSA_XTENSAFRAMELOWERING_H + +#include "llvm/CodeGen/TargetFrameLowering.h" + +namespace llvm { +class XtensaTargetMachine; +class XtensaSubtarget; + +class XtensaFrameLowering : public TargetFrameLowering { +public: + XtensaFrameLowering(); + + bool hasFP(const MachineFunction &MF) const override; + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &, MachineBasicBlock &) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; +}; + +} // namespace llvm + +#endif /* LLVM_LIB_TARGET_XTENSA_XTENSAFRAMELOWERING_H */ diff --git a/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp b/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp new file mode 100644 index 0000000000000..3007372754522 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp @@ -0,0 +1,79 @@ +//===- XtensaISelDAGToDAG.cpp - A dag to dag inst selector for Xtensa -----===// +// +// 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 Xtensa target. +// +//===----------------------------------------------------------------------===// + +#include "Xtensa.h" +#include "XtensaTargetMachine.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "xtensa-isel" + +namespace { + +class XtensaDAGToDAGISel : public SelectionDAGISel { +public: + static char ID; + + XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel) + : SelectionDAGISel(ID, TM, OptLevel) {} + + StringRef getPassName() const override { + return "Xtensa DAG->DAG Pattern Instruction Selection"; + } + + void Select(SDNode *Node) override; + + bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset, + int Scale) { + report_fatal_error("MemReg address is not implemented yet"); + } + + bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) { + return selectMemRegAddr(Addr, Base, Offset, 1); + } + + bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) { + return selectMemRegAddr(Addr, Base, Offset, 2); + } + + bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) { + return selectMemRegAddr(Addr, Base, Offset, 4); + } + +// Include the pieces autogenerated from the target description. +#include "XtensaGenDAGISel.inc" +}; // namespace +} // end anonymous namespace + +char XtensaDAGToDAGISel::ID = 0; + +FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM, + CodeGenOptLevel OptLevel) { + return new XtensaDAGToDAGISel(TM, OptLevel); +} + +void XtensaDAGToDAGISel::Select(SDNode *Node) { + SDLoc DL(Node); + + // If we have a custom node, we already have selected! + if (Node->isMachineOpcode()) { + Node->setNodeId(-1); + return; + } + + SelectCode(Node); +} diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp new file mode 100644 index 0000000000000..276fab838d17c --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -0,0 +1,58 @@ +//===- XtensaISelLowering.cpp - Xtensa 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 defines the interfaces that Xtensa uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "XtensaISelLowering.h" +#include "XtensaSubtarget.h" +#include "XtensaTargetMachine.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "xtensa-lower" + +XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM, + const XtensaSubtarget &STI) + : TargetLowering(TM), Subtarget(STI) { + // Set up the register classes. + addRegisterClass(MVT::i32, &Xtensa::ARRegClass); + + // Set up special registers. + setStackPointerRegisterToSaveRestore(Xtensa::SP); + + setSchedulingPreference(Sched::RegPressure); + + setMinFunctionAlignment(Align(4)); + + // Compute derived properties from the register classes + computeRegisterProperties(STI.getRegisterInfo()); +} + +SDValue XtensaTargetLowering::LowerOperation(SDValue Op, + SelectionDAG &DAG) const { + switch (Op.getOpcode()) { + default: + report_fatal_error("Unexpected node to lower"); + } +} + +const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const { + return nullptr; +} diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h new file mode 100644 index 0000000000000..8b03712efc9bb --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h @@ -0,0 +1,41 @@ +//===- XtensaISelLowering.h - Xtensa 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 Xtensa uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAISELLOWERING_H +#define LLVM_LIB_TARGET_XTENSA_XTENSAISELLOWERING_H + +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/TargetLowering.h" + +namespace llvm { +class XtensaSubtarget; + +class XtensaTargetLowering : public TargetLowering { +public: + explicit XtensaTargetLowering(const TargetMachine &TM, + const XtensaSubtarget &STI); + + const char *getTargetNodeName(unsigned Opcode) const override; + + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; + + const XtensaSubtarget &getSubtarget() const { return Subtarget; } + +private: + const XtensaSubtarget &Subtarget; +}; + +} // end namespace llvm + +#endif /* LLVM_LIB_TARGET_XTENSA_XTENSAISELLOWERING_H */ diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp new file mode 100644 index 0000000000000..41b794d64fdb1 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp @@ -0,0 +1,27 @@ +//===- XtensaInstrInfo.cpp - Xtensa Instruction Information ---------------===// +// +// The LLVM Compiler Infrastructure +// +// 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 Xtensa implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "XtensaInstrInfo.h" +#include "XtensaTargetMachine.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +#define GET_INSTRINFO_CTOR_DTOR +#include "XtensaGenInstrInfo.inc" + +using namespace llvm; + +XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI) + : XtensaGenInstrInfo(), RI(STI), STI(STI) {} diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h new file mode 100644 index 0000000000000..8c73c9bd79408 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h @@ -0,0 +1,45 @@ +//===-- XtensaInstrInfo.h - Xtensa Instruction Information ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// 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 Xtensa implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAINSTRINFO_H +#define LLVM_LIB_TARGET_XTENSA_XTENSAINSTRINFO_H + +#include "Xtensa.h" +#include "XtensaRegisterInfo.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" + +#define GET_INSTRINFO_HEADER + +#include "XtensaGenInstrInfo.inc" + +namespace llvm { + +class XtensaTargetMachine; +class XtensaSubtarget; +class XtensaInstrInfo : public XtensaGenInstrInfo { + const XtensaRegisterInfo RI; + const XtensaSubtarget &STI; + +public: + XtensaInstrInfo(const XtensaSubtarget &STI); + + // Return the XtensaRegisterInfo, which this class owns. + const XtensaRegisterInfo &getRegisterInfo() const { return RI; } + + const XtensaSubtarget &getSubtarget() const { return STI; } +}; +} // end namespace llvm + +#endif /* LLVM_LIB_TARGET_XTENSA_XTENSAINSTRINFO_H */ diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp new file mode 100644 index 0000000000000..f749cc51f96a0 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp @@ -0,0 +1,69 @@ +//===- XtensaRegisterInfo.cpp - Xtensa 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 Xtensa implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "XtensaRegisterInfo.h" +#include "XtensaInstrInfo.h" +#include "XtensaSubtarget.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "xtensa-reg-info" + +#define GET_REGINFO_TARGET_DESC +#include "XtensaGenRegisterInfo.inc" + +using namespace llvm; + +XtensaRegisterInfo::XtensaRegisterInfo(const XtensaSubtarget &STI) + : XtensaGenRegisterInfo(Xtensa::A0), Subtarget(STI) {} + +const uint16_t * +XtensaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + // Calling convention is not implemented yet + return nullptr; +} + +const uint32_t * +XtensaRegisterInfo::getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const { + // Calling convention is not implemented yet + return nullptr; +} + +BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + + Reserved.set(Xtensa::A0); + if (TFI->hasFP(MF)) { + // Reserve frame pointer. + Reserved.set(getFrameRegister(MF)); + } + + // Reserve stack pointer. + Reserved.set(Xtensa::SP); + return Reserved; +} + +bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { + report_fatal_error("Eliminate frame index not supported yet"); +} + +Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + return TFI->hasFP(MF) ? Xtensa::A15 : Xtensa::SP; +} diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h new file mode 100644 index 0000000000000..a4eda87f4c8b7 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h @@ -0,0 +1,56 @@ +//===-- XtensaRegisterInfo.h - Xtensa 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 Xtensa implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAREGISTERINFO_H +#define LLVM_LIB_TARGET_XTENSA_XTENSAREGISTERINFO_H + +#include "Xtensa.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "XtensaGenRegisterInfo.inc" + +namespace llvm { +class TargetRegisterClass; +class XtensaInstrInfo; +class XtensaSubtarget; + +struct XtensaRegisterInfo : public XtensaGenRegisterInfo { +public: + const XtensaSubtarget &Subtarget; + + XtensaRegisterInfo(const XtensaSubtarget &STI); + + bool requiresRegisterScavenging(const MachineFunction &MF) const override { + return true; + } + + bool requiresFrameIndexScavenging(const MachineFunction &MF) const override { + return true; + } + + const uint16_t * + getCalleeSavedRegs(const MachineFunction *MF = 0) const override; + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const override; + BitVector getReservedRegs(const MachineFunction &MF) const override; + + bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, + unsigned FIOperandNum, + RegScavenger *RS = nullptr) const override; + + Register getFrameRegister(const MachineFunction &MF) const override; +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_XTENSA_REGISTERINFO_H diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.cpp b/llvm/lib/Target/Xtensa/XtensaSubtarget.cpp new file mode 100644 index 0000000000000..10ab92d2a2d38 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.cpp @@ -0,0 +1,44 @@ +//===- XtensaSubtarget.cpp - Xtensa 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 Xtensa specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#include "XtensaSubtarget.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "xtensa-subtarget" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "XtensaGenSubtargetInfo.inc" + +using namespace llvm; + +XtensaSubtarget & +XtensaSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) { + StringRef CPUName = CPU; + if (CPUName.empty()) { + // set default cpu name + CPUName = "generic"; + } + + HasDensity = false; + + // Parse features string. + ParseSubtargetFeatures(CPUName, CPUName, FS); + return *this; +} + +XtensaSubtarget::XtensaSubtarget(const Triple &TT, StringRef CPU, StringRef FS, + const TargetMachine &TM) + : XtensaGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), TargetTriple(TT), + InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), + TSInfo(), FrameLowering() {} diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h new file mode 100644 index 0000000000000..948dcbc5278ea --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h @@ -0,0 +1,72 @@ +//===-- XtensaSubtarget.h - Define Subtarget for the Xtensa ----*- 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 Xtensa specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_XTENSA_XTENSASUBTARGET_H +#define LLVM_LIB_TARGET_XTENSA_XTENSASUBTARGET_H + +#include "XtensaFrameLowering.h" +#include "XtensaISelLowering.h" +#include "XtensaInstrInfo.h" +#include "XtensaRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGTargetInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/Target/TargetMachine.h" + +#define GET_SUBTARGETINFO_HEADER +#include "XtensaGenSubtargetInfo.inc" + +namespace llvm { +class StringRef; + +class XtensaSubtarget : public XtensaGenSubtargetInfo { +private: + const Triple &TargetTriple; + XtensaInstrInfo InstrInfo; + XtensaTargetLowering TLInfo; + SelectionDAGTargetInfo TSInfo; + XtensaFrameLowering FrameLowering; + + // Enabled Xtensa Density extension + bool HasDensity; + + XtensaSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); + +public: + XtensaSubtarget(const Triple &TT, StringRef CPU, StringRef FS, + const TargetMachine &TM); + + const Triple &getTargetTriple() const { return TargetTriple; } + + const TargetFrameLowering *getFrameLowering() const override { + return &FrameLowering; + } + const XtensaInstrInfo *getInstrInfo() const override { return &InstrInfo; } + const XtensaRegisterInfo *getRegisterInfo() const override { + return &InstrInfo.getRegisterInfo(); + } + + const XtensaTargetLowering *getTargetLowering() const override { + return &TLInfo; + } + const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { + return &TSInfo; + } + + bool hasDensity() const { return HasDensity; } + + // Automatically generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); +}; +} // end namespace llvm + +#endif /* LLVM_LIB_TARGET_XTENSA_XTENSASUBTARGET_H */ diff --git a/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp b/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp index c891ecd9c0c3f..49c7faf84df1d 100644 --- a/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp +++ b/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp @@ -64,6 +64,45 @@ XtensaTargetMachine::XtensaTargetMachine(const Target &T, const Triple &TT, CodeGenOptLevel OL, bool JIT) : XtensaTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {} +const XtensaSubtarget * +XtensaTargetMachine::getSubtargetImpl(const Function &F) const { + Attribute CPUAttr = F.getFnAttribute("target-cpu"); + Attribute FSAttr = F.getFnAttribute("target-features"); + + auto CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; + auto FS = FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; + + auto &I = SubtargetMap[CPU + FS]; + if (!I) { + // This needs to be done before we create a new subtarget since any + // creation will depend on the TM and the code generation flags on the + // function that reside in TargetOptions. + resetTargetOptions(F); + I = std::make_unique(TargetTriple, CPU, FS, *this); + } + return I.get(); +} + +namespace { +/// Xtensa Code Generator Pass Configuration Options. +class XtensaPassConfig : public TargetPassConfig { +public: + XtensaPassConfig(XtensaTargetMachine &TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + XtensaTargetMachine &getXtensaTargetMachine() const { + return getTM(); + } + + bool addInstSelector() override; +}; +} // end anonymous namespace + +bool XtensaPassConfig::addInstSelector() { + addPass(createXtensaISelDag(getXtensaTargetMachine(), getOptLevel())); + return false; +} + TargetPassConfig *XtensaTargetMachine::createPassConfig(PassManagerBase &PM) { - return new TargetPassConfig(*this, PM); + return new XtensaPassConfig(*this, PM); } diff --git a/llvm/lib/Target/Xtensa/XtensaTargetMachine.h b/llvm/lib/Target/Xtensa/XtensaTargetMachine.h index dd76f45b3bb71..f371f22ed3d0e 100644 --- a/llvm/lib/Target/Xtensa/XtensaTargetMachine.h +++ b/llvm/lib/Target/Xtensa/XtensaTargetMachine.h @@ -15,6 +15,7 @@ #ifndef LLVM_LIB_TARGET_XTENSA_XTENSATARGETMACHINE_H #define LLVM_LIB_TARGET_XTENSA_XTENSATARGETMACHINE_H +#include "XtensaSubtarget.h" #include "llvm/Target/TargetMachine.h" #include @@ -36,10 +37,16 @@ class XtensaTargetMachine : public LLVMTargetMachine { std::optional CM, CodeGenOptLevel OL, bool JIT); + const XtensaSubtarget *getSubtargetImpl(const Function &F) const override; + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; + TargetLoweringObjectFile *getObjFileLowering() const override { return TLOF.get(); } + +protected: + mutable StringMap> SubtargetMap; }; } // end namespace llvm diff --git a/llvm/test/CodeGen/Xtensa/lit.local.cfg b/llvm/test/CodeGen/Xtensa/lit.local.cfg new file mode 100644 index 0000000000000..e81bfa773f36a --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/lit.local.cfg @@ -0,0 +1,2 @@ +if not "Xtensa" in config.root.targets: + config.unsupported = True diff --git a/llvm/test/CodeGen/Xtensa/simple.ll b/llvm/test/CodeGen/Xtensa/simple.ll new file mode 100644 index 0000000000000..a2c55aa513835 --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/simple.ll @@ -0,0 +1,5 @@ +; RUN: llc -mtriple=xtensa -filetype=asm %s -o - | FileCheck %s +; RUN: llc -mtriple=xtensa -filetype=obj %s -o - | llvm-objdump --arch=xtensa -d - | FileCheck %s --check-prefix=DUMP + +; CHECK: .text +; DUMP: file format elf32-xtensa