diff options
author | Tony Linthicum <tlinth@codeaurora.org> | 2011-12-12 21:14:40 +0000 |
---|---|---|
committer | Tony Linthicum <tlinth@codeaurora.org> | 2011-12-12 21:14:40 +0000 |
commit | b4b54153ad760c69a00a08531abef4ed434a5092 (patch) | |
tree | 5c767f5ad7f35af4cb8dc0228769e16d62c993e7 /lib | |
parent | 127a669d09e21ddcd525f493c19dc399093bef35 (diff) |
Hexagon backend support
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146412 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
55 files changed, 20771 insertions, 0 deletions
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index ac4f005ab1..8f58e7029a 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -20,6 +20,7 @@ const char *Triple::getArchTypeName(ArchType Kind) { case arm: return "arm"; case cellspu: return "cellspu"; + case hexagon: return "hexagon"; case mips: return "mips"; case mipsel: return "mipsel"; case mips64: return "mips64"; @@ -59,6 +60,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case mblaze: return "mblaze"; + case hexagon: return "hexagon"; + case sparcv9: case sparc: return "sparc"; @@ -150,6 +153,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { return ppc; if (Name == "mblaze") return mblaze; + if (Name == "hexagon") + return hexagon; if (Name == "sparc") return sparc; if (Name == "sparcv9") @@ -295,6 +300,8 @@ Triple::ArchType Triple::ParseArch(StringRef ArchName) { return mips64; else if (ArchName == "mips64el") return mips64el; + else if (ArchName == "hexagon") + return hexagon; else if (ArchName == "sparc") return sparc; else if (ArchName == "sparcv9") diff --git a/lib/Target/Hexagon/CMakeLists.txt b/lib/Target/Hexagon/CMakeLists.txt new file mode 100644 index 0000000000..898590aec0 --- /dev/null +++ b/lib/Target/Hexagon/CMakeLists.txt @@ -0,0 +1,43 @@ +set(LLVM_TARGET_DEFINITIONS Hexagon.td) + +tablegen(LLVM HexagonGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM HexagonGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM HexagonGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM HexagonGenDAGISel.inc -gen-dag-isel) +tablegen(LLVM HexagonGenCallingConv.inc -gen-callingconv) +tablegen(LLVM HexagonGenSubtargetInfo.inc -gen-subtarget) +tablegen(LLVM HexagonGenIntrinsics.inc -gen-tgt-intrinsic) +add_public_tablegen_target(HexagonCommonTableGen) + +add_llvm_target(HexagonCodeGen + HexagonAsmPrinter.cpp + HexagonCallingConvLower.cpp + HexagonCFGOptimizer.cpp + HexagonExpandPredSpillCode.cpp + HexagonFrameLowering.cpp + HexagonHardwareLoops.cpp + HexagonInstrInfo.cpp + HexagonISelDAGToDAG.cpp + HexagonISelLowering.cpp + HexagonMCAsmInfo.cpp + HexagonOptimizeSZExtends.cpp + HexagonRegisterInfo.cpp + HexagonRemoveSZExtArgs.cpp + HexagonSelectionDAGInfo.cpp + HexagonSplitTFRCondSets.cpp + HexagonSubtarget.cpp + HexagonTargetMachine.cpp + HexagonTargetObjectFile.cpp + ) + +add_llvm_library_dependencies(LLVMHexagonCodeGen + LLVMAsmPrinter + LLVMCodeGen + LLVMCore + LLVMHexagonInfo + LLVMSelectionDAG + LLVMSupport + LLVMTarget + ) + +add_subdirectory(TargetInfo) diff --git a/lib/Target/Hexagon/Hexagon.h b/lib/Target/Hexagon/Hexagon.h new file mode 100644 index 0000000000..ced3e9f846 --- /dev/null +++ b/lib/Target/Hexagon/Hexagon.h @@ -0,0 +1,68 @@ +//=-- Hexagon.h - Top-level interface for Hexagon representation --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the LLVM +// Hexagon back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_Hexagon_H +#define TARGET_Hexagon_H + +#include <cassert> +#include "llvm/Target/TargetLowering.h" + +namespace llvm { + class FunctionPass; + class TargetMachine; + class HexagonTargetMachine; + class raw_ostream; + + FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM); + FunctionPass *createHexagonDelaySlotFillerPass(TargetMachine &TM); + FunctionPass *createHexagonFPMoverPass(TargetMachine &TM); + FunctionPass *createHexagonRemoveExtendOps(HexagonTargetMachine &TM); + FunctionPass *createHexagonCFGOptimizer(HexagonTargetMachine &TM); + + FunctionPass* createHexagonSplitTFRCondSets(HexagonTargetMachine &TM); + FunctionPass* createHexagonExpandPredSpillCode(HexagonTargetMachine &TM); + + FunctionPass *createHexagonHardwareLoops(); + FunctionPass *createHexagonOptimizeSZExtends(); + FunctionPass *createHexagonFixupHwLoops(); + + extern Target TheHexagonTarget; + +} // end namespace llvm; + +// Defines symbolic names for Hexagon instructions and registers. +// This defines a mapping from register name to register number. +// + +#define GET_REGINFO_ENUM +#include "HexagonGenRegisterInfo.inc" + +#define GET_INSTRINFO_ENUM +#include "HexagonGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "HexagonGenSubtargetInfo.inc" + +#define Hexagon_POINTER_SIZE 4 + +#define Hexagon_PointerSize (Hexagon_POINTER_SIZE) +#define Hexagon_PointerSize_Bits (Hexagon_POINTER_SIZE * 8) +#define Hexagon_WordSize Hexagon_PointerSize +#define Hexagon_WordSize_Bits Hexagon_PointerSize_Bits + +// allocframe saves LR and FP on stack before allocating +// a new stack frame. This takes 8 bytes. +#define HEXAGON_LRFP_SIZE 8 + +#endif diff --git a/lib/Target/Hexagon/Hexagon.td b/lib/Target/Hexagon/Hexagon.td new file mode 100644 index 0000000000..72939e6f1f --- /dev/null +++ b/lib/Target/Hexagon/Hexagon.td @@ -0,0 +1,66 @@ +//===- Hexagon.td - Describe the Hexagon Target Machine ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// Hexagon Subtarget features. +// + + +// Hexagon Archtectures +def ArchV2 : SubtargetFeature<"v2", "HexagonArchVersion", "V2", + "Hexagon v2">; +def ArchV3 : SubtargetFeature<"v3", "HexagonArchVersion", "V3", + "Hexagon v3">; +def ArchV4 : SubtargetFeature<"v4", "HexagonArchVersion", "V4", + "Hexagon v4">; + +//===----------------------------------------------------------------------===// +// Register File, Calling Conv, Instruction Descriptions +//===----------------------------------------------------------------------===// +include "HexagonSchedule.td" +include "HexagonRegisterInfo.td" +include "HexagonCallingConv.td" +include "HexagonInstrInfo.td" +include "HexagonIntrinsics.td" +include "HexagonIntrinsicsDerived.td" + + +def HexagonInstrInfo : InstrInfo { + // Define how we want to layout our target-specific information field. +} + +//===----------------------------------------------------------------------===// +// Hexagon processors supported. +//===----------------------------------------------------------------------===// + +class Proc<string Name, ProcessorItineraries Itin, + list<SubtargetFeature> Features> + : Processor<Name, Itin, Features>; + +def : Proc<"hexagonv2", HexagonItineraries, [ArchV2]>; +def : Proc<"hexagonv3", HexagonItineraries, [ArchV2, ArchV3]>; +def : Proc<"hexagonv4", HexagonItinerariesV4, [ArchV2, ArchV3, ArchV4]>; + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def Hexagon : Target { + // Pull in Instruction Info: + let InstructionSet = HexagonInstrInfo; +} diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/lib/Target/Hexagon/HexagonAsmPrinter.cpp new file mode 100644 index 0000000000..8f8e804024 --- /dev/null +++ b/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -0,0 +1,555 @@ +//===-- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly ----=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to Hexagon assembly language. This printer is +// the output mechanism used by `llc'. +// +// Documentation at http://developer.apple.com/documentation/DeveloperTools/ +// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html +// +//===----------------------------------------------------------------------===// + + +#define DEBUG_TYPE "asm-printer" +#include "Hexagon.h" +#include "HexagonTargetMachine.h" +#include "HexagonSubtarget.h" +#include "HexagonMachineFunctionInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static cl::opt<bool> AlignCalls( + "hexagon-align-calls", cl::Hidden, cl::init(true), + cl::desc("Insert falign after call instruction for Hexagon target")); + + +namespace { + class HexagonAsmPrinter : public AsmPrinter { + const HexagonSubtarget *Subtarget; + + public: + explicit HexagonAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) { + Subtarget = &TM.getSubtarget<HexagonSubtarget>(); + } + + virtual const char *getPassName() const { + return "Hexagon Assembly Printer"; + } + + /// printInstruction - This method is automatically generated by tablegen + /// from the instruction set description. This method returns true if the + /// machine instruction was sufficiently described to print it, otherwise it + void printInstruction(const MachineInstr *MI, raw_ostream &O); + virtual void EmitInstruction(const MachineInstr *MI); + + void printOp(const MachineOperand &MO, raw_ostream &O); + + /// printRegister - Print register according to target requirements. + /// + void printRegister(const MachineOperand &MO, bool R0AsZero, + raw_ostream &O) { + unsigned RegNo = MO.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); + O << getRegisterName(RegNo); + } + + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (MO.isReg()) { + printRegister(MO, false, OS); + } else if (MO.isImm()) { + OS << MO.getImm(); + } else { + printOp(MO, OS); + } + } + + + bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); + + + void printHexagonImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + int value = MI->getOperand(OpNo).getImm(); + O << value; + } + + + void printHexagonNegImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + int value = MI->getOperand(OpNo).getImm(); + O << -value; + } + + void printHexagonMEMriOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + const MachineOperand &MO1 = MI->getOperand(OpNo); + const MachineOperand &MO2 = MI->getOperand(OpNo+1); + + O << getRegisterName(MO1.getReg()) + << " + #" + << (int) MO2.getImm(); + } + + + void printHexagonFrameIndexOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + const MachineOperand &MO1 = MI->getOperand(OpNo); + const MachineOperand &MO2 = MI->getOperand(OpNo+1); + + O << getRegisterName(MO1.getReg()) + << ", #" + << MO2.getImm(); + } + + void printBranchOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + // Branches can take an immediate operand. This is used by the branch + // selection pass to print $+8, an eight byte displacement from the PC. + if (MI->getOperand(OpNo).isImm()) { + O << "$+" << MI->getOperand(OpNo).getImm()*4; + } else { + printOp(MI->getOperand(OpNo), O); + } + } + + void printCallOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + } + + void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + } + + + void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + O << "#HI("; + if (MI->getOperand(OpNo).isImm()) { + printHexagonImmOperand(MI, OpNo, O); + } else { + printOp(MI->getOperand(OpNo), O); + } + O << ")"; + } + + void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + O << "#HI("; + if (MI->getOperand(OpNo).isImm()) { + printHexagonImmOperand(MI, OpNo, O); + } else { + printOp(MI->getOperand(OpNo), O); + } + O << ")"; + } + + void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O); + + void printAddrModeBasePlusOffset(const MachineInstr *MI, int OpNo, + raw_ostream &O); + + void printGlobalOperand(const MachineInstr *MI, int OpNo, raw_ostream &O); + void printJumpTable(const MachineInstr *MI, int OpNo, raw_ostream &O); + + void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const; + + static const char *getRegisterName(unsigned RegNo); + }; + +} // end of anonymous namespace + +// Include the auto-generated portion of the assembly writer. +#include "HexagonGenAsmWriter.inc" + + +void HexagonAsmPrinter::EmitAlignment(unsigned NumBits, + const GlobalValue *GV) const { + + // For basic block level alignment, use falign. + if (!GV) { + OutStreamer.EmitRawText(StringRef("\t.falign")); + return; + } + + AsmPrinter::EmitAlignment(NumBits, GV); +} + +void HexagonAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { + switch (MO.getType()) { + case MachineOperand::MO_Immediate: + dbgs() << "printOp() does not handle immediate values\n"; + abort(); + return; + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_JumpTableIndex: + O << *GetJTISymbol(MO.getIndex()); + // FIXME: PIC relocation model. + return; + case MachineOperand::MO_ConstantPoolIndex: + O << *GetCPISymbol(MO.getIndex()); + return; + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + return; + case MachineOperand::MO_GlobalAddress: { + // Computing the address of a global symbol, not calling it. + O << *Mang->getSymbol(MO.getGlobal()); + printOffset(MO.getOffset(), O); + return; + } + + default: + O << "<unknown operand type: " << MO.getType() << ">"; + return; + } +} + + +// +// isBlockOnlyReachableByFallthrough - We need to override this since the +// default AsmPrinter does not print labels for any basic block that +// is only reachable by a fall through. That works for all cases except +// for the case in which the basic block is reachable by a fall through but +// through an indirect from a jump table. In this case, the jump table +// will contain a label not defined by AsmPrinter. +// +bool HexagonAsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + if (MBB->hasAddressTaken()) { + return false; + } + return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); +} + + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &OS) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'c': // Don't print "$" before a global var name or constant. + // Hexagon never has a prefix. + printOperand(MI, OpNo, OS); + return false; + case 'L': // Write second word of DImode reference. + // Verify that this operand has two consecutive registers. + if (!MI->getOperand(OpNo).isReg() || + OpNo+1 == MI->getNumOperands() || + !MI->getOperand(OpNo+1).isReg()) + return true; + ++OpNo; // Return the high-part. + break; + case 'I': + // Write 'i' if an integer constant, otherwise nothing. Used to print + // addi vs add, etc. + if (MI->getOperand(OpNo).isImm()) + OS << "i"; + return false; + } + } + + printOperand(MI, OpNo, OS); + return false; +} + +bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + + const MachineOperand &Base = MI->getOperand(OpNo); + const MachineOperand &Offset = MI->getOperand(OpNo+1); + + if (Base.isReg()) + printOperand(MI, OpNo, O); + else + assert(0 && "Unimplemented"); + + if (Offset.isImm()) { + if (Offset.getImm()) + O << " + #" << Offset.getImm(); + } + else + assert(0 && "Unimplemented"); + + return false; +} + +void HexagonAsmPrinter::printPredicateOperand(const MachineInstr *MI, + unsigned OpNo, + raw_ostream &O) { + assert(0 && "Unimplemented"); +} + + +/// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to +/// the current output stream. +/// +void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream O(Str); + + const Machi |