and so it begins...

PHASE 1: write instruction selector
PHASE 2: ???
PHASE 3: profit!


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@20652 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duraid Madina 2005-03-17 18:17:03 +00:00
parent 7805fa4acc
commit 9b9d45f60e
17 changed files with 3756 additions and 0 deletions

50
lib/Target/IA64/IA64.h Normal file
View File

@ -0,0 +1,50 @@
//===-- IA64.h - Top-level interface for IA64 representation ------*- C++ -*-===//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and 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 IA64
// target library, as used by the LLVM JIT.
//
//===----------------------------------------------------------------------===//
#ifndef TARGET_IA64_H
#define TARGET_IA64_H
#include <iosfwd>
namespace llvm {
class TargetMachine;
class FunctionPass;
class IntrinsicLowering;
/// createIA64PatternInstructionSelector - This pass converts an LLVM function
/// into a machine code representation in a more aggressive way.
///
FunctionPass *createIA64PatternInstructionSelector(TargetMachine &TM);
/// createIA64CodePrinterPass - Returns a pass that prints the IA64
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *createIA64CodePrinterPass(std::ostream &o,TargetMachine &tm);
} // End llvm namespace
// Defines symbolic names for IA64 registers. This defines a mapping from
// register name to register number.
//
#include "IA64GenRegisterNames.inc"
// Defines symbolic names for the IA64 instructions.
//
#include "IA64GenInstrNames.inc"
#endif

93
lib/Target/IA64/IA64.td Normal file
View File

@ -0,0 +1,93 @@
//===-- IA64.td - Target definition file for Intel IA64 -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a target description file for the Intel IA64 architecture,
// also known variously as ia64, IA-64, IPF, "the Itanium architecture" etc.
//
//===----------------------------------------------------------------------===//
// Get the target-independent interfaces which we are implementing...
//
include "../Target.td"
//===----------------------------------------------------------------------===//
// Register File Description
//===----------------------------------------------------------------------===//
include "IA64RegisterInfo.td"
//===----------------------------------------------------------------------===//
// Instruction Descriptions
//===----------------------------------------------------------------------===//
include "IA64InstrInfo.td"
def IA64InstrInfo : InstrInfo {
let PHIInst = PHI;
}
def IA64 : Target {
// The following registers are always saved across calls:
let CalleeSavedRegisters =
//'preserved' GRs:
[r4, r5, r6, r7,
//'special' GRs:
r1, // global data pointer (GP)
r12, // memory stack pointer (SP)
// **** r13 (thread pointer) we do not touch, ever. it's not here. ****//
//r15, // our frame pointer (FP)
//'stacked' GRs the RSE takes care of, we don't worry about
/* We don't want PEI::calculateCallerSavedRegisters to worry about them,
since the RSE takes care of them (and we determinethe appropriate
'alloc' instructions and save/restore ar.pfs ourselves, in instruction
selection)
**************************************************************************
* r32, r33, r34, r35,
* r36, r37, r38, r39, r40, r41, r42, r43, r44, r45, r46, r47,
* r48, r49, r50, r51, r52, r53, r54, r55, r56, r57, r58, r59,
* r60, r61, r62, r63, r64, r65, r66, r67, r68, r69, r70, r71,
* r72, r73, r74, r75, r76, r77, r78, r79, r80, r81, r82, r83,
* r84, r85, r86, r87, r88, r89, r90, r91, r92, r93, r94, r95,
* r96, r97, r98, r99, r100, r101, r102, r103, r104, r105, r106, r107,
* r108, r109, r110, r111, r112, r113, r114, r115, r116, r117, r118, r119,
* r120, r121, r122, r123, r124, r125, r126, r127,
**************************************************************************
*/
//'preserved' FP regs:
F2,F3,F4,F5,
F16,F17,F18,F19,F20,F21,F22,F23,
F24,F25,F26,F27,F28,F29,F30,F31,
//'preserved' predicate regs:
p1, p2, p3, p4, p5,
p16, p17, p18, p19, p20, p21, p22, p23,
p24, p25, p26, p27, p28, p29, p30, p31,
p32, p33, p34, p35, p36, p37, p38, p39,
p40, p41, p42, p43, p44, p45, p46, p47,
p48, p49, p50, p51, p52, p53, p54, p55,
p56, p57, p58, p59, p60, p61, p62, p63];
// We don't go anywhere near the LP32 variant of IA64 as
// sometimes seen in (for example) HP-UX
let PointerType = i64;
// Our instruction set
let InstructionSet = IA64InstrInfo;
}

View File

@ -0,0 +1,399 @@
//===-- IA64AsmPrinter.cpp - Print out IA64 LLVM as assembly --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and 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 assembly accepted by the GNU binutils 'gas'
// assembler. The Intel 'ias' and HP-UX 'as' assemblers *may* choke on this
// output, but if so that's a bug I'd like to hear about: please file a bug
// report in bugzilla. FYI, the excellent 'ias' assembler is bundled with
// the Intel C/C++ compiler for Itanium Linux.
//
//===----------------------------------------------------------------------===//
#include "IA64.h"
#include "IA64TargetMachine.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
namespace {
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
struct IA64SharedAsmPrinter : public AsmPrinter {
std::set<std::string> ExternalFunctionNames;
IA64SharedAsmPrinter(std::ostream &O, TargetMachine &TM)
: AsmPrinter(O, TM) { }
void printConstantPool(MachineConstantPool *MCP);
bool doFinalization(Module &M);
};
}
static bool isScale(const MachineOperand &MO) {
return MO.isImmediate() &&
(MO.getImmedValue() == 1 || MO.getImmedValue() == 2 ||
MO.getImmedValue() == 4 || MO.getImmedValue() == 8);
}
static bool isMem(const MachineInstr *MI, unsigned Op) {
if (MI->getOperand(Op).isFrameIndex()) return true;
if (MI->getOperand(Op).isConstantPoolIndex()) return true;
return Op+4 <= MI->getNumOperands() &&
MI->getOperand(Op ).isRegister() && isScale(MI->getOperand(Op+1)) &&
MI->getOperand(Op+2).isRegister() && (MI->getOperand(Op+3).isImmediate() ||
MI->getOperand(Op+3).isGlobalAddress());
}
// SwitchSection - Switch to the specified section of the executable if we are
// not already in it!
//
static void SwitchSection(std::ostream &OS, std::string &CurSection,
const char *NewSection) {
if (CurSection != NewSection) {
CurSection = NewSection;
if (!CurSection.empty())
OS << "\t" << NewSection << "\n";
}
}
/// printConstantPool - Print to the current output stream assembly
/// representations of the constants in the constant pool MCP. This is
/// used to print out constants which have been "spilled to memory" by
/// the code generator.
///
void IA64SharedAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
const std::vector<Constant*> &CP = MCP->getConstants();
const TargetData &TD = TM.getTargetData();
if (CP.empty()) return;
O << "\n\t.section .data\n"; // would be nice to have this rodata? hmmm
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType()));
O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString
<< *CP[i] << "\n";
emitGlobalConstant(CP[i]);
}
}
bool IA64SharedAsmPrinter::doFinalization(Module &M) {
const TargetData &TD = TM.getTargetData();
std::string CurSection;
// Print out module-level global variables here.
for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
if (I->hasInitializer()) { // External global require no code
O << "\n\n";
std::string name = Mang->getValueName(I);
Constant *C = I->getInitializer();
unsigned Size = TD.getTypeSize(C->getType());
unsigned Align = TD.getTypeAlignmentShift(C->getType());
if (C->isNullValue() &&
(I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
I->hasWeakLinkage() /* FIXME: Verify correct */)) {
SwitchSection(O, CurSection, ".data");
if (I->hasInternalLinkage())
O << "\t.local " << name << "\n";
O << "\t.common " << name << "," << TD.getTypeSize(C->getType())
<< "," << (1 << Align);
O << "\t\t// ";
WriteAsOperand(O, I, true, true, &M);
O << "\n";
} else {
switch (I->getLinkage()) {
case GlobalValue::LinkOnceLinkage:
case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
// Nonnull linkonce -> weak
O << "\t.weak " << name << "\n";
SwitchSection(O, CurSection, "");
O << "\t.section\t.llvm.linkonce.d." << name
<< ", \"aw\", \"progbits\"\n";
break;
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
O << "\t.global " << name << "\n";
// FALL THROUGH
case GlobalValue::InternalLinkage:
if (C->isNullValue())
SwitchSection(O, CurSection, ".data"); // FIXME: this was
// '.bss', but in ia64-land .bss means "nobits" (i.e. uninitialized)
// hmm.
else
SwitchSection(O, CurSection, ".data");
break;
case GlobalValue::GhostLinkage:
std::cerr << "GhostLinkage cannot appear in IA64AsmPrinter!\n";
abort();
}
emitAlignment(Align);
O << "\t.type " << name << ",@object\n";
O << "\t.size " << name << "," << Size << "\n";
O << name << ":\t\t\t\t// ";
WriteAsOperand(O, I, true, true, &M);
O << " = ";
WriteAsOperand(O, C, false, false, &M);
O << "\n";
emitGlobalConstant(C);
}
}
// we print out ".global X \n .type X, @function" for each external function
O << "\n\n// br.call targets referenced (and not defined) above: \n";
for (std::set<std::string>::iterator i = ExternalFunctionNames.begin(),
e = ExternalFunctionNames.end(); i!=e; ++i) {
O << "\t.global " << *i << "\n\t.type " << *i << ", @function\n";
}
O << "\n\n";
AsmPrinter::doFinalization(M);
return false; // success
}
namespace {
struct IA64AsmPrinter : public IA64SharedAsmPrinter {
IA64AsmPrinter(std::ostream &O, TargetMachine &TM)
: IA64SharedAsmPrinter(O, TM) {
CommentString = "//";
Data8bitsDirective = "\tdata1\t";
Data16bitsDirective = "\tdata2\t";
Data32bitsDirective = "\tdata4\t";
Data64bitsDirective = "\tdata8\t";
ZeroDirective = "\t.skip\t";
AsciiDirective = "\tstring\t";
}
virtual const char *getPassName() const {
return "IA64 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
/// returns false.
bool printInstruction(const MachineInstr *MI);
// This method is used by the tablegen'erated instruction printer.
void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
const MachineOperand &MO = MI->getOperand(OpNo);
if (MO.getType() == MachineOperand::MO_MachineRegister) {
assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physref??");
//XXX Bug Workaround: See note in Printer::doInitialization about %.
O << TM.getRegisterInfo()->get(MO.getReg()).Name;
} else {
printOp(MO);
}
}
void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
O << (short)MI->getOperand(OpNo).getImmedValue();
}
void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
O << (unsigned short)MI->getOperand(OpNo).getImmedValue();
}
void printS21ImmOperand(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
O << (int)MI->getOperand(OpNo).getImmedValue(); // FIXME (21, not 32!)
}
void printS32ImmOperand(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
O << (int)MI->getOperand(OpNo).getImmedValue();
}
void printU32ImmOperand(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
O << (unsigned int)MI->getOperand(OpNo).getImmedValue();
}
void printU64ImmOperand(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
O << (uint64_t)MI->getOperand(OpNo).getImmedValue();
}
void printCallOperand(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
printOp(MI->getOperand(OpNo), true); // this is a br.call instruction
}
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO, bool isBRCALLinsn= false);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
};
} // end of anonymous namespace
// Include the auto-generated portion of the assembly writer.
#include "IA64GenAsmWriter.inc"
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool IA64AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
setupMachineFunction(MF);
O << "\n\n";
// Print out constants referenced by the function
printConstantPool(MF.getConstantPool());
// Print out labels for the function.
O << "\n\t.section .text, \"ax\", \"progbits\"\n";
// ^^ means "Allocated instruXions in mem, initialized"
emitAlignment(4);
O << "\t.global\t" << CurrentFnName << "\n";
O << "\t.type\t" << CurrentFnName << ", @function\n";
O << CurrentFnName << ":\n";
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block if there are any predecessors.
if (I->pred_begin() != I->pred_end())
O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t"
<< CommentString << " " << I->getBasicBlock()->getName() << "\n";
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
O << "\t";
printMachineInstruction(II);
}
}
// We didn't modify anything.
return false;
}
void IA64AsmPrinter::printOp(const MachineOperand &MO,
bool isBRCALLinsn /* = false */) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
switch (MO.getType()) {
case MachineOperand::MO_VirtualRegister:
if (Value *V = MO.getVRegValueOrNull()) {
O << "<" << V->getName() << ">";
return;
}
// FALLTHROUGH
case MachineOperand::MO_MachineRegister:
case MachineOperand::MO_CCRegister: {
O << RI.get(MO.getReg()).Name;
return;
}
case MachineOperand::MO_SignExtendedImmed:
case MachineOperand::MO_UnextendedImmed:
O << /*(unsigned int)*/MO.getImmedValue();
return;
case MachineOperand::MO_MachineBasicBlock: {
MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
<< "_" << MBBOp->getNumber () << "\t// "
<< MBBOp->getBasicBlock ()->getName ();
return;
}
case MachineOperand::MO_PCRelativeDisp:
std::cerr << "Shouldn't use addPCDisp() when building IA64 MachineInstrs";
abort ();
return;
case MachineOperand::MO_ConstantPoolIndex: {
O << "@gprel(.CPI" << CurrentFnName << "_"
<< MO.getConstantPoolIndex() << ")";
return;
}
case MachineOperand::MO_GlobalAddress: {
// functions need @ltoff(@fptr(fn_name)) form
GlobalValue *GV = MO.getGlobal();
Function *F = dyn_cast<Function>(GV);
bool Needfptr=false; // if we're computing an address @ltoff(X), do
// we need to decorate it so it becomes
// @ltoff(@fptr(X)) ?
if(F && !isBRCALLinsn && F->isExternal())
Needfptr=true;
// if this is the target of a call instruction, we should define
// the function somewhere (GNU gas has no problem without this, but
// Intel ias rightly complains of an 'undefined symbol')
if(F && isBRCALLinsn && F->isExternal())
ExternalFunctionNames.insert(Mang->getValueName(MO.getGlobal()));
if (!isBRCALLinsn)
O << "@ltoff(";
if (Needfptr)
O << "@fptr(";
O << Mang->getValueName(MO.getGlobal());
if (Needfptr)
O << ")"; // close fptr(
if (!isBRCALLinsn)
O << ")"; // close ltoff(
int Offset = MO.getOffset();
if (Offset > 0)
O << " + " << Offset;
else if (Offset < 0)
O << " - " << -Offset;
return;
}
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
return;
default:
O << "<AsmPrinter: unknown operand type: " << MO.getType() << " >"; return;
}
}
/// printMachineInstruction -- Print out a single IA64 LLVM instruction
/// MI to the current output stream.
///
void IA64AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
// Call the autogenerated instruction printer routines.
printInstruction(MI);
}
bool IA64AsmPrinter::doInitialization(Module &M) {
AsmPrinter::doInitialization(M);
O << "\t.psr lsb\n" // should be "msb" on HP-UX, for starters
<< "\t.radix C\n"
<< "\t.psr abi64\n"; // we only support 64 bits for now
return false;
}
/// createIA64CodePrinterPass - Returns a pass that prints the IA64
/// assembly code for a MachineFunction to the given output stream, using
/// the given target machine description.
///
FunctionPass *llvm::createIA64CodePrinterPass(std::ostream &o,TargetMachine &tm){
return new IA64AsmPrinter(o, tm);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
//===-- IA64PCInstrBuilder.h - Aids for building IA64 insts -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file exposes functions that may be used with BuildMI from the
// MachineInstrBuilder.h file to simplify generating frame and constant pool
// references.
//
//===----------------------------------------------------------------------===//
#ifndef IA64_INSTRBUILDER_H
#define IA64_INSTRBUILDER_H
#include "llvm/CodeGen/MachineInstrBuilder.h"
namespace llvm {
/// addFrameReference - This function is used to add a reference to the base of
/// an abstract object on the stack frame of the current function. This
/// reference has base register as the FrameIndex offset until it is resolved.
/// This allows a constant offset to be specified as well...
///
inline const MachineInstrBuilder&
addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0,
bool mem = true) {
if (mem)
return MIB.addSImm(Offset).addFrameIndex(FI);
else
return MIB.addFrameIndex(FI).addSImm(Offset);
}
/// addConstantPoolReference - This function is used to add a reference to the
/// base of a constant value spilled to the per-function constant pool. The
/// reference has base register ConstantPoolIndex offset which is retained until
/// either machine code emission or assembly output. This allows an optional
/// offset to be added as well.
///
inline const MachineInstrBuilder&
addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI,
int Offset = 0) {
return MIB.addSImm(Offset).addConstantPoolIndex(CPI);
}
} // End llvm namespace
#endif

View File

@ -0,0 +1,67 @@
//===- IA64InstrFormats.td - IA64 Instruction Formats --*- tablegen -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// - Warning: the stuff in here isn't really being used, so is mostly
// junk. It'll get fixed as the JIT gets built.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Instruction format superclass
//===----------------------------------------------------------------------===//
class InstIA64<bits<4> op, dag OL, string asmstr> : Instruction {
// IA64 instruction baseline
field bits<41> Inst;
let Namespace = "IA64";
let OperandList = OL;
let AsmString = asmstr;
let Inst{40-37} = op;
}
//"Each Itanium instruction is categorized into one of six types."
//We should have:
// A, I, M, F, B, L+X
class AForm<bits<4> opcode, bits<6> qpReg, dag OL, string asmstr> :
InstIA64<opcode, OL, asmstr> {
let Inst{5-0} = qpReg;
}
let isBranch = 1, isTerminator = 1 in
class BForm<bits<4> opcode, bits<6> x6, bits<3> btype, dag OL, string asmstr> :
InstIA64<opcode, OL, asmstr> {
let Inst{32-27} = x6;
let Inst{8-6} = btype;
}
class MForm<bits<4> opcode, bits<6> x6, dag OL, string asmstr> :
InstIA64<opcode, OL, asmstr> {
bits<7> Ra;
bits<7> Rb;
bits<16> disp;
let Inst{35-30} = x6;
// let Inst{20-16} = Rb;
let Inst{15-0} = disp;
}
class RawForm<bits<4> opcode, bits<26> rest, dag OL, string asmstr> :
InstIA64<opcode, OL, asmstr> {
let Inst{25-0} = rest;
}
// Pseudo instructions.
class PseudoInstIA64<dag OL, string nm> : InstIA64<0, OL, nm> {
}

View File

@ -0,0 +1,47 @@
//===- IA64InstrInfo.cpp - IA64 Instruction Information -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the IA64 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#include "IA64InstrInfo.h"
#include "IA64.h"
#include "IA64InstrBuilder.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "IA64GenInstrInfo.inc"
using namespace llvm;
IA64InstrInfo::IA64InstrInfo()
: TargetInstrInfo(IA64Insts, sizeof(IA64Insts)/sizeof(IA64Insts[0])) {
}
bool IA64InstrInfo::isMoveInstr(const MachineInstr& MI,
unsigned& sourceReg,
unsigned& destReg) const {
MachineOpCode oc = MI.getOpcode();
if (oc == IA64::MOV || oc == IA64::FMOV) {
assert(MI.getNumOperands() == 2 &&
/* MI.getOperand(0).isRegister() &&
MI.getOperand(1).isRegister() && */
"invalid register-register move instruction");
if( MI.getOperand(0).isRegister() &&
MI.getOperand(1).isRegister() ) {
// if both operands of the MOV/FMOV are registers, then
// yes, this is a move instruction
sourceReg = MI.getOperand(1).getReg();
destReg = MI.getOperand(0).getReg();
return true;
}
}
return false; // we don't consider e.g. %regN = MOV <FrameIndex #x> a
// move instruction
}

View File

@ -0,0 +1,50 @@
//===- IA64InstrInfo.h - IA64 Instruction Information ----------*- C++ -*- ===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the IA64 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef IA64INSTRUCTIONINFO_H
#define IA64INSTRUCTIONINFO_H
#include "llvm/Target/TargetInstrInfo.h"
#include "IA64RegisterInfo.h"
namespace llvm {
/// IA64II - This namespace holds all of the target specific flags that
/// instruction info tracks.
/// FIXME: now gone!
class IA64InstrInfo : public TargetInstrInfo {
const IA64RegisterInfo RI;
public:
IA64InstrInfo();
/// 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).
///
virtual const MRegisterInfo &getRegisterInfo() const { return RI; }
//
// Return true if the instruction is a register to register move and
// leave the source and dest operands in the passed parameters.
//
virtual bool isMoveInstr(const MachineInstr& MI,
unsigned& sourceReg,
unsigned& destReg) const;
};
} // End llvm namespace
#endif

View File

@ -0,0 +1,319 @@
//===- IA64InstrInfo.td - Describe the IA64 Instruction Set -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the IA64 instruction set, defining the instructions, and
// properties of the instructions which are needed for code generation, machine
// code emission, and analysis.
//
//===----------------------------------------------------------------------===//
include "IA64InstrFormats.td"
def u6imm : Operand<i8>;
def s16imm : Operand<i16>;
def s21imm : Operand<i32> {
let PrintMethod = "printS21ImmOperand";
}
def u32imm : Operand<i32> {
let PrintMethod = "printU32ImmOperand";
}
def s32imm : Operand<i32> {
let PrintMethod = "printS32ImmOperand";
}
def u64imm : Operand<i64> {
let PrintMethod = "printU64ImmOperand";
}
// the asmprinter needs to know about calls
let PrintMethod = "printCallOperand" in
def calltarget : Operand<i64>;
def PHI : PseudoInstIA64<(ops), "PHI">;
def IDEF : PseudoInstIA64<(ops), "// IDEF">;
def WTF : PseudoInstIA64<(ops), "que??">;
def ADJUSTCALLSTACKUP : PseudoInstIA64<(ops), "// ADJUSTCALLSTACKUP">;
def ADJUSTCALLSTACKDOWN : PseudoInstIA64<(ops), "// ADJUSTCALLSTACKDOWN">;
def PSEUDO_ALLOC : PseudoInstIA64<(ops), "// PSEUDO_ALLOC">;
def ALLOC : AForm<0x03, 0x0b,
(ops GR:$dst, i8imm:$inputs, i8imm:$locals, i8imm:$outputs, i8imm:$rotating),
"alloc $dst = ar.pfs,$inputs,$locals,$outputs,$rotating;;">;
def MOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "mov $dst = $src;;">;
def PMOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src, PR:$qp),
"($qp) mov $dst = $src;;">;
def SPILL_ALL_PREDICATES_TO_GR : AForm<0x03, 0x0b, (ops GR:$dst),
"mov $dst = pr;;">;
def FILL_ALL_PREDICATES_FROM_GR : AForm<0x03, 0x0b, (ops GR:$src),
"mov pr = $src;;">;
let isTwoAddress = 1 in {
def CMOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src2, GR:$src, PR:$qp),
"($qp) mov $dst = $src;;">;
}
let isTwoAddress = 1 in {
def TCMPNE : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4),
"cmp.ne $dst, p0 = $src3, $src4;;">;
def TPCMPEQOR : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.eq.or $dst, p0 = $src3, $src4;;">;
def TPCMPNE : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.ne $dst, p0 = $src3, $src4;;">;
def TPCMPEQ : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.eq $dst, p0 = $src3, $src4;;">;
}
def MOVI32 : AForm<0x03, 0x0b, (ops GR:$dst, u32imm:$imm),
"mov $dst = $imm;;">;
def MOVLI32 : AForm<0x03, 0x0b, (ops GR:$dst, u32imm:$imm),
"movl $dst = $imm;;">;
def MOVLSI32 : AForm<0x03, 0x0b, (ops GR:$dst, s32imm:$imm),
"movl $dst = $imm;;">;
def MOVLI64 : AForm<0x03, 0x0b, (ops GR:$dst, u64imm:$imm),
"movl $dst = $imm;;">;
def AND : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"and $dst = $src1, $src2;;">;
def OR : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"or $dst = $src1, $src2;;">;
def XOR : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"xor $dst = $src1, $src2;;">;
def SHL : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"shl $dst = $src1, $src2;;">;
def SHLI : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s21imm:$imm),
"shl $dst = $src1, $imm;;">; // FIXME: 6 immediate bits, not 21
def SHRU : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"shr.u $dst = $src1, $src2;;">;
def SHRS : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"shr $dst = $src1, $src2;;">;
def DEPZ : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm1, u6imm:$imm2), "dep.z $dst = $src1, $imm1, $imm2;;">;
def SXT1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt1 $dst = $src;;">;
def ZXT1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt1 $dst = $src;;">;
def SXT2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt2 $dst = $src;;">;
def ZXT2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt2 $dst = $src;;">;
def SXT4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt4 $dst = $src;;">;
def ZXT4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt4 $dst = $src;;">;
// the following are all a bit unfortunate: we throw away the complement
// of the compare!
def CMPEQ : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.eq $dst, p0 = $src1, $src2;;">;
def CMPGT : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.gt $dst, p0 = $src1, $src2;;">;
def CMPGE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.ge $dst, p0 = $src1, $src2;;">;
def CMPLT : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.lt $dst, p0 = $src1, $src2;;">;
def CMPLE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.le $dst, p0 = $src1, $src2;;">;
def CMPNE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.ne $dst, p0 = $src1, $src2;;">;
def CMPLTU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.ltu $dst, p0 = $src1, $src2;;">;
def CMPGTU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.gtu $dst, p0 = $src1, $src2;;">;
def CMPLEU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.leu $dst, p0 = $src1, $src2;;">;
def CMPGEU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.geu $dst, p0 = $src1, $src2;;">;
// and we do the whole thing again for FP compares!
def FCMPEQ : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.eq $dst, p0 = $src1, $src2;;">;
def FCMPGT : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.gt $dst, p0 = $src1, $src2;;">;
def FCMPGE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.ge $dst, p0 = $src1, $src2;;">;
def FCMPLT : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.lt $dst, p0 = $src1, $src2;;">;
def FCMPLE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.le $dst, p0 = $src1, $src2;;">;
def FCMPNE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.neq $dst, p0 = $src1, $src2;;">;
def FCMPLTU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.ltu $dst, p0 = $src1, $src2;;">;
def FCMPGTU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.gtu $dst, p0 = $src1, $src2;;">;
def FCMPLEU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.leu $dst, p0 = $src1, $src2;;">;
def FCMPGEU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.geu $dst, p0 = $src1, $src2;;">;
def PCMPEQOR : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.eq.or $dst, p0 = $src1, $src2;;">;
def PCMPEQUNC : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.eq.unc $dst, p0 = $src1, $src2;;">;
def PCMPNE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.ne $dst, p0 = $src1, $src2;;">;
// two destinations!
def BCMPEQ : AForm<0x03, 0x0b, (ops PR:$dst1, PR:$dst2, GR:$src1, GR:$src2),
"cmp.eq $dst1, dst2 = $src1, $src2;;">;
def ADD : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"add $dst = $src1, $src2;;">;
def ADDIMM22 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s21imm:$imm),
"add $dst = $imm, $src1;;">;
def CADDIMM22 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s21imm:$imm, PR:$qp),
"($qp) add $dst = $imm, $src1;;">;
let isTwoAddress = 1 in {
def TPCADDIMM22 : AForm<0x03, 0x0b,
(ops GR:$dst, GR:$src1, s21imm:$imm, PR:$qp),
"($qp) add $dst = $imm, $dst;;">;
def TPCMPIMM8NE : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src1, s21imm:$imm, GR:$src2, PR:$qp),
"($qp) cmp.ne $dst , p0 = $imm, $src2;;">;
}
def SUB : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"sub $dst = $src1, $src2;;">;
def ST1 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
"st1 [$dstPtr] = $value;;">;
def ST2 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
"st2 [$dstPtr] = $value;;">;
def ST4 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
"st4 [$dstPtr] = $value;;">;
def ST8 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
"st8 [$dstPtr] = $value;;">;
def LD1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
"ld1 $dst = [$srcPtr];;">;
def LD2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
"ld2 $dst = [$srcPtr];;">;
def LD4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
"ld4 $dst = [$srcPtr];;">;
def LD8 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
"ld8 $dst = [$srcPtr];;">;
// some FP stuff:
def FADD : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"fadd $dst = $src1, $src2;;">;
def FADDS: AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"fadd.s $dst = $src1, $src2;;">;
def FSUB : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"fsub $dst = $src1, $src2;;">;
def FMPY : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"fmpy $dst = $src1, $src2;;">;
def FMOV : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"mov $dst = $src;;">; // XXX: there _is_ no fmov
def FMA : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"fma $dst = $src1, $src2, $src3;;">;
def FNMA : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"fnma $dst = $src1, $src2, $src3;;">;
def CFMAS1 : AForm<0x03, 0x0b,
(ops FP:$dst, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fma.s1 $dst = $src1, $src2, $src3;;">;
def CFNMAS1 : AForm<0x03, 0x0b,
(ops FP:$dst, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fnma.s1 $dst = $src1, $src2, $src3;;">;
// FIXME: we 'explode' FRCPA (which should write two registers) into two
// operations that write one each. this is a waste, and is also destroying
// f127. not cool.
def FRCPAS1FLOAT : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"frcpa.s1 $dst , p0 = $src1, $src2;;">;
// XXX: this _will_ break things: (f127)
def FRCPAS1PREDICATE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"frcpa.s1 f127 , $dst = $src1, $src2;; // XXX FIXME!!!!">;
def XMAL : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"xma.l $dst = $src1, $src2, $src3;;">;
def FCVTXF : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.xf $dst = $src;;">;
def FCVTXUF : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.xuf $dst = $src;;">;
def FCVTXUFS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.xuf.s1 $dst = $src;;">;
def FCVTFX : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fx $dst = $src;;">;
def FCVTFXU : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fxu $dst = $src;;">;
def FCVTFXTRUNC : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fx.trunc $dst = $src;;">;
def FCVTFXUTRUNC : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fxu.trunc $dst = $src;;">;
def FCVTFXTRUNCS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fx.trunc.s1 $dst = $src;;">;
def FCVTFXUTRUNCS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fxu.trunc.s1 $dst = $src;;">;
def FNORMD : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fnorm.d $dst = $src;;">;
def GETFD : AForm<0x03, 0x0b, (ops GR:$dst, FP:$src),
"getf.d $dst = $src;;">;
def SETFD : AForm<0x03, 0x0b, (ops FP:$dst, GR:$src),
"setf.d $dst = $src;;">;
def GETFSIG : AForm<0x03, 0x0b, (ops GR:$dst, FP:$src),
"getf.sig $dst = $src;;">;
def SETFSIG : AForm<0x03, 0x0b, (ops FP:$dst, GR:$src),
"setf.sig $dst = $src;;">;
def LDF4 : AForm<0x03, 0x0b, (ops FP:$dst, GR:$srcPtr),
"ldfs $dst = [$srcPtr];;">;
def LDF8 : AForm<0x03, 0x0b, (ops FP:$dst, GR:$srcPtr),
"ldfd $dst = [$srcPtr];;">;
def STF4 : AForm<0x03, 0x0b, (ops GR:$dstPtr, FP:$value),
"stfs [$dstPtr] = $value;;">;
def STF8 : AForm<0x03, 0x0b, (ops GR:$dstPtr, FP:$value),
"stfd [$dstPtr] = $value;;">;
let isTerminator = 1, isBranch = 1 in {
def BRLCOND_NOTCALL : RawForm<0x03, 0xb0, (ops PR:$qp, i64imm:$dst),
"($qp) brl.cond.sptk $dst;;">;
def BRCOND_NOTCALL : RawForm<0x03, 0xb0, (ops PR:$qp, GR:$dst),
"($qp) br.cond.sptk $dst;;">;
}
let isCall = 1, isTerminator = 1, isBranch = 1,
// all calls clobber non-callee-saved registers, and for now, they are these:
Defs = [r2,r3,r8,r9,r10,r11,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,
r25,r26,r27,r28,r29,r30,r31,
p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,
F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,
F32,F33,F34,F35,F36,F37,F38,F39,F40,F41,F42,F43,F44,F45,F46,F47,F48,F49,
F50,F51,F52,F53,F54,F55,F56,
F57,F58,F59,F60,F61,F62,F63,F64,F65,F66,F67,F68,F69,F70,F71,F72,F73,F74,
F75,F76,F77,F78,F79,F80,F81,
F82,F83,F84,F85,F86,F87,F88,F89,F90,F91,F92,F93,F94,F95,F96,F97,F98,F99,
F100,F101,F102,F103,F104,F105,
F106,F107,F108,F109,F110,F111,F112,F113,F114,F115,F116,F117,F118,F119,
F120,F121,F122,F123,F124,F125,F126,F127,
out0,out1,out2,out3,out4,out5,out6,out7] in {
def BRCALL : RawForm<0x03, 0xb0, (ops calltarget:$dst),
"br.call.sptk rp = $dst;;">; // FIXME: teach llvm about branch regs?
def BRLCOND_CALL : RawForm<0x03, 0xb0, (ops PR:$qp, i64imm:$dst),
"($qp) brl.cond.call.sptk $dst;;">;
def BRCOND_CALL : RawForm<0x03, 0xb0, (ops PR:$qp, GR:$dst),
"($qp) br.cond.call.sptk $dst;;">;
}
let isTerminator = 1, isReturn = 1 in
def RET : RawForm<0x03, 0xb0, (ops), "br.ret.sptk.many rp;;">; // return

View File

@ -0,0 +1,34 @@
//===-- IA64MachineFunctionInfo.h - IA64-specific information ---*- C++ -*-===//
//===-- for MachineFunction ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
//===----------------------------------------------------------------------===//
//
// This file declares IA64-specific per-machine-function information.
//
//===----------------------------------------------------------------------===//
#ifndef IA64MACHINEFUNCTIONINFO_H
#define IA64MACHINEFUNCTIONINFO_H
#include "llvm/CodeGen/MachineFunction.h"
//#include "IA64JITInfo.h"
namespace llvm {
class IA64FunctionInfo : public MachineFunctionInfo {
public:
unsigned outRegsUsed; // how many 'out' registers are used
// by this machinefunction? (used to compute the appropriate
// entry in the 'alloc' instruction at the top of the
// machinefunction)
IA64FunctionInfo(MachineFunction& MF) { outRegsUsed=0; };
};
} // End llvm namespace
#endif

View File

@ -0,0 +1,362 @@
//===- IA64RegisterInfo.cpp - IA64 Register Information ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the IA64 implementation of the MRegisterInfo class. This
// file is responsible for the frame pointer elimination optimization on IA64.
//
//===----------------------------------------------------------------------===//
#include "IA64.h"
#include "IA64RegisterInfo.h"
#include "IA64InstrBuilder.h"
#include "IA64MachineFunctionInfo.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/STLExtras.h"
#include <iostream>
using namespace llvm;
namespace {
}
IA64RegisterInfo::IA64RegisterInfo()
: IA64GenRegisterInfo(IA64::ADJUSTCALLSTACKDOWN, IA64::ADJUSTCALLSTACKUP) {}
static const TargetRegisterClass *getClass(unsigned SrcReg) {
if (IA64::FPRegisterClass->contains(SrcReg))
return IA64::FPRegisterClass;
if (IA64::PRRegisterClass->contains(SrcReg))
return IA64::PRRegisterClass;
assert(IA64::GRRegisterClass->contains(SrcReg) &&
"PROBLEM: Reg is not FP, predicate or GR!");
return IA64::GRRegisterClass;
}
void IA64RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned SrcReg, int FrameIdx) const {
if (getClass(SrcReg) == IA64::FPRegisterClass) {
BuildMI(MBB, MI, IA64::STF8, 2).addFrameIndex(FrameIdx).addReg(SrcReg);
}
else if (getClass(SrcReg) == IA64::GRRegisterClass) {
BuildMI(MBB, MI, IA64::ST8, 2).addFrameIndex(FrameIdx).addReg(SrcReg);
}
else if (getClass(SrcReg) == IA64::PRRegisterClass) {
/* we use IA64::r2 as a temporary register for doing this hackery. */
// first we load 0:
BuildMI(MBB, MI, IA64::MOV, 1, IA64::r2).addReg(IA64::r0);
// then conditionally add 1:
BuildMI(MBB, MI, IA64::CADDIMM22, 3, IA64::r2).addReg(IA64::r2)
.addImm(1).addReg(SrcReg);
// and then store it to the stack
BuildMI(MBB, MI, IA64::ST8, 2).addFrameIndex(FrameIdx).addReg(IA64::r2);
} else assert(0 &&
"sorry, I don't know how to store this sort of reg in the stack\n");
}
void IA64RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, int FrameIdx)const{
if (getClass(DestReg) == IA64::FPRegisterClass) {
BuildMI(MBB, MI, IA64::LDF8, 1, DestReg).addFrameIndex(FrameIdx);
} else if (getClass(DestReg) == IA64::GRRegisterClass) {
BuildMI(MBB, MI, IA64::LD8, 1, DestReg).addFrameIndex(FrameIdx);
} else if (getClass(DestReg) == IA64::PRRegisterClass) {
// first we load a byte from the stack into r2, our 'predicate hackery'
// scratch reg
BuildMI(MBB, MI, IA64::LD8, 1, IA64::r2).addFrameIndex(FrameIdx);
// then we compare it to zero. If it _is_ zero, compare-not-equal to
// r0 gives us 0, which is what we want, so that's nice.
BuildMI(MBB, MI, IA64::CMPNE, 2, DestReg).addReg(IA64::r2).addReg(IA64::r0);
} else assert(0 &&
"sorry, I don't know how to load this sort of reg from the stack\n");
}
void IA64RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *RC) const {
if(RC == IA64::PRRegisterClass ) // if a bool, we use pseudocode
// (SrcReg) DestReg = cmp.eq.unc(r0, r0)
BuildMI(MBB, MI, IA64::PCMPEQUNC, 1, DestReg).addReg(IA64::r0).addReg(IA64::r0).addReg(SrcReg);
else // otherwise, MOV works (for both gen. regs and FP regs)
BuildMI(MBB, MI, IA64::MOV, 1, DestReg).addReg(SrcReg);
}
//===----------------------------------------------------------------------===//
// Stack Frame Processing methods
//===----------------------------------------------------------------------===//
// 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.
//
static bool hasFP(MachineFunction &MF) {
return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects();
}
void IA64RegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
if (hasFP(MF)) {
// If we have a frame pointer, turn the adjcallstackup instruction into a
// 'sub SP, <amt>' and the adjcallstackdown instruction into 'add SP,
// <amt>'
MachineInstr *Old = I;
unsigned Amount = Old->getOperand(0).getImmedValue();
if (Amount != 0) {
// We need to keep the stack aligned properly. To do this, we round the
// amount of space needed for the outgoing arguments up to the next
// alignment boundary.
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
Amount = (Amount+Align-1)/Align*Align;
MachineInstr *New;
if (Old->getOpcode() == IA64::ADJUSTCALLSTACKDOWN) {
New=BuildMI(IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12)
.addImm(-Amount);
} else {
assert(Old->getOpcode() == IA64::ADJUSTCALLSTACKUP);
New=BuildMI(IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12)
.addImm(Amount);
}
// Replace the pseudo instruction with a new instruction...
MBB.insert(I, New);
}
}
MBB.erase(I);
}
void IA64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
unsigned i = 0;
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
MachineFunction &MF = *MBB.getParent();
bool FP = hasFP(MF);
while (!MI.getOperand(i).isFrameIndex()) {
++i;
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
}
int FrameIndex = MI.getOperand(i).getFrameIndex();
// choose a base register: ( hasFP? framepointer : stack pointer )
unsigned BaseRegister = FP ? IA64::r15 : IA64::r12;
// Add the base register
MI.SetMachineOperandReg(i, BaseRegister);
// Now add the frame object offset to the offset from r1.
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
// If we're not using a Frame Pointer that has been set to the value of the
// SP before having the stack size subtracted from it, then add the stack size
// to Offset to get the correct offset.
Offset += MF.getFrameInfo()->getStackSize();
// XXX: we use 'r22' as another hack+slash temporary register here :(
if ( Offset <= 8191 && Offset >= -8192) { // smallish offset
//fix up the old:
MI.SetMachineOperandReg(i, IA64::r22);
//insert the new
MachineInstr* nMI=BuildMI(IA64::ADDIMM22, 2, IA64::r22)
.addReg(BaseRegister).addSImm(Offset);
MBB.insert(II, nMI);
} else { // it's big
//fix up the old:
MI.SetMachineOperandReg(i, IA64::r22);
MachineInstr* nMI;
nMI=BuildMI(IA64::MOVLSI32, 1, IA64::r22).addSImm(Offset);
MBB.insert(II, nMI);
nMI=BuildMI(IA64::ADD, 2, IA64::r22).addReg(BaseRegister)
.addReg(IA64::r22);
MBB.insert(II, nMI);
}
}
void IA64RegisterInfo::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo *MFI = MF.getFrameInfo();
MachineInstr *MI;
bool FP = hasFP(MF);
// first, we handle the 'alloc' instruction, that should be right up the
// top of any function
static const unsigned RegsInOrder[96] = { // there are 96 GPRs the
// RSE worries about
IA64::r32, IA64::r33, IA64::r34, IA64::r35,
IA64::r36, IA64::r37, IA64::r38, IA64::r39, IA64::r40, IA64::r41,
IA64::r42, IA64::r43, IA64::r44, IA64::r45, IA64::r46, IA64::r47,
IA64::r48, IA64::r49, IA64::r50, IA64::r51, IA64::r52, IA64::r53,
IA64::r54, IA64::r55, IA64::r56, IA64::r57, IA64::r58, IA64::r59,
IA64::r60, IA64::r61, IA64::r62, IA64::r63, IA64::r64, IA64::r65,
IA64::r66, IA64::r67, IA64::r68, IA64::r69, IA64::r70, IA64::r71,
IA64::r72, IA64::r73, IA64::r74, IA64::r75, IA64::r76, IA64::r77,
IA64::r78, IA64::r79, IA64::r80, IA64::r81, IA64::r82, IA64::r83,
IA64::r84, IA64::r85, IA64::r86, IA64::r87, IA64::r88, IA64::r89,
IA64::r90, IA64::r91, IA64::r92, IA64::r93, IA64::r94, IA64::r95,
IA64::r96, IA64::r97, IA64::r98, IA64::r99, IA64::r100, IA64::r101,
IA64::r102, IA64::r103, IA64::r104, IA64::r105, IA64::r106, IA64::r107,
IA64::r108, IA64::r109, IA64::r110, IA64::r111, IA64::r112, IA64::r113,
IA64::r114, IA64::r115, IA64::r116, IA64::r117, IA64::r118, IA64::r119,
IA64::r120, IA64::r121, IA64::r122, IA64::r123, IA64::r124, IA64::r125,
IA64::r126, IA64::r127 };
unsigned numStackedGPRsUsed=0;
for(int i=0; i<96; i++) {
if(MF.isPhysRegUsed(RegsInOrder[i]))
numStackedGPRsUsed=i+1; // (i+1 and not ++ - consider fn(fp, fp, int)
}
unsigned numOutRegsUsed=MF.getInfo<IA64FunctionInfo>()->outRegsUsed;
// XXX FIXME : this code should be a bit more reliable (in case there _isn't_ a pseudo_alloc in the MBB)
unsigned dstRegOfPseudoAlloc;
for(MBBI = MBB.begin(); /*MBBI->getOpcode() != IA64::PSEUDO_ALLOC*/; ++MBBI) {
assert(MBBI != MBB.end());
if(MBBI->getOpcode() == IA64::PSEUDO_ALLOC) {
dstRegOfPseudoAlloc=MBBI->getOperand(0).getReg();
break;
}
}
MI=BuildMI(IA64::ALLOC,5).addReg(dstRegOfPseudoAlloc).addImm(0).\
addImm(numStackedGPRsUsed).addImm(numOutRegsUsed).addImm(0);
MBB.insert(MBBI, MI);
// Get the number of bytes to allocate from the FrameInfo
unsigned NumBytes = MFI->getStackSize();
if (MFI->hasCalls() && !FP) {
// We reserve argument space for call sites in the function immediately on
// entry to the current function. This eliminates the need for add/sub
// brackets around call sites.
NumBytes += MFI->getMaxCallFrameSize();
}
if(FP)
NumBytes += 8; // reserve space for the old FP
// Do we need to allocate space on the stack?
if (NumBytes == 0)
return;
// Add 16 bytes at the bottom of the stack (scratch area)
// and round the size to a multiple of the alignment.
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
unsigned Size = 16 + (FP ? 8 : 0);
NumBytes = (NumBytes+Size+Align-1)/Align*Align;
// Update frame info to pretend that this is part of the stack...
MFI->setStackSize(NumBytes);
// adjust stack pointer: r12 -= numbytes
if (NumBytes <= 8191) {
MI=BuildMI(IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12).addImm(-NumBytes);
MBB.insert(MBBI, MI);
} else { // we use r22 as a scratch register here
MI=BuildMI(IA64::MOVLSI32, 1, IA64::r22).addSImm(-NumBytes);
// FIXME: MOVLSI32 expects a _u_32imm
MBB.insert(MBBI, MI); // first load the decrement into r22
MI=BuildMI(IA64::ADD, 2, IA64::r12).addReg(IA64::r12).addReg(IA64::r22);
MBB.insert(MBBI, MI); // then add (subtract) it to r12 (stack ptr)
}
// now if we need to, save the old FP and set the new
if (FP) {
MI = BuildMI(IA64::ST8, 2).addReg(IA64::r12).addReg(IA64::r15);
MBB.insert(MBBI, MI);
// this must be the last instr in the prolog ? (XXX: why??)
MI = BuildMI(IA64::MOV, 1, IA64::r15).addReg(IA64::r12);
MBB.insert(MBBI, MI);
}
}
void IA64RegisterInfo::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
MachineBasicBlock::iterator MBBI = prior(MBB.end());
MachineInstr *MI;
assert(MBBI->getOpcode() == IA64::RET &&
"Can only insert epilog into returning blocks");
bool FP = hasFP(MF);
// Get the number of bytes allocated from the FrameInfo...
unsigned NumBytes = MFI->getStackSize();
//now if we need to, restore the old FP
if (FP)
{
//copy the FP into the SP (discards allocas)
MI=BuildMI(IA64::MOV, 1, IA64::r12).addReg(IA64::r15);
MBB.insert(MBBI, MI);
//restore the FP
MI=BuildMI(IA64::LD8, 1, IA64::r15).addReg(IA64::r15);
MBB.insert(MBBI, MI);
}
if (NumBytes != 0)
{
if (NumBytes <= 8191) {
MI=BuildMI(IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12).addImm(NumBytes);
MBB.insert(MBBI, MI);
} else {
MI=BuildMI(IA64::MOVLI32, 1, IA64::r22).addImm(NumBytes);
MBB.insert(MBBI, MI);
MI=BuildMI(IA64::ADD, 2, IA64::r12).addReg(IA64::r12).addReg(IA64::r22);
MBB.insert(MBBI, MI);
}
}
}
#include "IA64GenRegisterInfo.inc"
const TargetRegisterClass*
IA64RegisterInfo::getRegClassForType(const Type* Ty) const {
switch (Ty->getTypeID()) {
default: assert(0 && "Invalid type to getClass!");
case Type::LongTyID:
case Type::ULongTyID:
case Type::BoolTyID:
case Type::SByteTyID:
case Type::UByteTyID:
case Type::ShortTyID:
case Type::UShortTyID:
case Type::IntTyID:
case Type::UIntTyID:
case Type::PointerTyID: return &GRInstance;
case Type::FloatTyID:
case Type::DoubleTyID: return &FPInstance;
}
}

View File

@ -0,0 +1,55 @@
//===- IA64RegisterInfo.h - IA64 Register Information Impl ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the IA64 implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef IA64REGISTERINFO_H
#define IA64REGISTERINFO_H
#include "llvm/Target/MRegisterInfo.h"
#include "IA64GenRegisterInfo.h.inc"
namespace llvm { class llvm::Type; }
namespace llvm {
struct IA64RegisterInfo : public IA64GenRegisterInfo {
IA64RegisterInfo();
const TargetRegisterClass* getRegClassForType(const Type* Ty) const;
/// Code Generation virtual methods...
void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned SrcReg, int FrameIndex) const;
void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, int FrameIndex) const;
void copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *RC) const;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const;
void eliminateFrameIndex(MachineBasicBlock::iterator MI) const;
void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
};
} // End llvm namespace
#endif

View File

@ -0,0 +1,291 @@
//===- IA64RegisterInfo.td - Describe the IA64 Register File ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the IA64 register file, defining the registers
// themselves, aliases between the registers, and the register classes built
// out of the registers.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Register definitions...
//
class IA64Register<string n> : Register<n> {
let Namespace = "IA64";
}
// GR - One of 128 32-bit general registers
class GR<bits<7> num, string n> : IA64Register<n> {
field bits<7> Num = num;
}
// FP - One of 128 82-bit floating-point registers
class FP<bits<7> num, string n> : IA64Register<n> {
field bits<7> Num = num;
}
// PR - One of 64 1-bit predicate registers
class PR<bits<6> num, string n> : IA64Register<n> {
field bits<6> Num = num;
}
/* general registers */
def r0 : GR< 0, "r0">; def r1 : GR< 1, "r1">;
def r2 : GR< 2, "r2">; def r3 : GR< 3, "r3">;
def r4 : GR< 4, "r4">; def r5 : GR< 5, "r5">;
def r6 : GR< 6, "r6">; def r7 : GR< 7, "r7">;
def r8 : GR< 8, "r8">; def r9 : GR< 9, "r9">;
def r10 : GR< 10, "r10">; def r11 : GR< 11, "r11">;
def r12 : GR< 12, "r12">; def r13 : GR< 13, "r13">;
def r14 : GR< 14, "r14">; def r15 : GR< 15, "r15">;
def r16 : GR< 16, "r16">; def r17 : GR< 17, "r17">;
def r18 : GR< 18, "r18">; def r19 : GR< 19, "r19">;
def r20 : GR< 20, "r20">; def r21 : GR< 21, "r21">;
def r22 : GR< 22, "r22">; def r23 : GR< 23, "r23">;
def r24 : GR< 24, "r24">; def r25 : GR< 25, "r25">;
def r26 : GR< 26, "r26">; def r27 : GR< 27, "r27">;
def r28 : GR< 28, "r28">; def r29 : GR< 29, "r29">;
def r30 : GR< 30, "r30">; def r31 : GR< 31, "r31">;
def r32 : GR< 32, "r32">; def r33 : GR< 33, "r33">;
def r34 : GR< 34, "r34">; def r35 : GR< 35, "r35">;
def r36 : GR< 36, "r36">; def r37 : GR< 37, "r37">;
def r38 : GR< 38, "r38">; def r39 : GR< 39, "r39">;
def r40 : GR< 40, "r40">; def r41 : GR< 41, "r41">;
def r42 : GR< 42, "r42">; def r43 : GR< 43, "r43">;
def r44 : GR< 44, "r44">; def r45 : GR< 45, "r45">;
def r46 : GR< 46, "r46">; def r47 : GR< 47, "r47">;
def r48 : GR< 48, "r48">; def r49 : GR< 49, "r49">;
def r50 : GR< 50, "r50">; def r51 : GR< 51, "r51">;
def r52 : GR< 52, "r52">; def r53 : GR< 53, "r53">;
def r54 : GR< 54, "r54">; def r55 : GR< 55, "r55">;
def r56 : GR< 56, "r56">; def r57 : GR< 57, "r57">;
def r58 : GR< 58, "r58">; def r59 : GR< 59, "r59">;
def r60 : GR< 60, "r60">; def r61 : GR< 61, "r61">;
def r62 : GR< 62, "r62">; def r63 : GR< 63, "r63">;
def r64 : GR< 64, "r64">; def r65 : GR< 65, "r65">;
def r66 : GR< 66, "r66">; def r67 : GR< 67, "r67">;
def r68 : GR< 68, "r68">; def r69 : GR< 69, "r69">;
def r70 : GR< 70, "r70">; def r71 : GR< 71, "r71">;
def r72 : GR< 72, "r72">; def r73 : GR< 73, "r73">;
def r74 : GR< 74, "r74">; def r75 : GR< 75, "r75">;
def r76 : GR< 76, "r76">; def r77 : GR< 77, "r77">;
def r78 : GR< 78, "r78">; def r79 : GR< 79, "r79">;
def r80 : GR< 80, "r80">; def r81 : GR< 81, "r81">;
def r82 : GR< 82, "r82">; def r83 : GR< 83, "r83">;
def r84 : GR< 84, "r84">; def r85 : GR< 85, "r85">;
def r86 : GR< 86, "r86">; def r87 : GR< 87, "r87">;
def r88 : GR< 88, "r88">; def r89 : GR< 89, "r89">;
def r90 : GR< 90, "r90">; def r91 : GR< 91, "r91">;
def r92 : GR< 92, "r92">; def r93 : GR< 93, "r93">;
def r94 : GR< 94, "r94">; def r95 : GR< 95, "r95">;
def r96 : GR< 96, "r96">; def r97 : GR< 97, "r97">;
def r98 : GR< 98, "r98">; def r99 : GR< 99, "r99">;
def r100 : GR< 100, "r100">; def r101 : GR< 101, "r101">;
def r102 : GR< 102, "r102">; def r103 : GR< 103, "r103">;
def r104 : GR< 104, "r104">; def r105 : GR< 105, "r105">;
def r106 : GR< 106, "r106">; def r107 : GR< 107, "r107">;
def r108 : GR< 108, "r108">; def r109 : GR< 109, "r109">;
def r110 : GR< 110, "r110">; def r111 : GR< 111, "r111">;
def r112 : GR< 112, "r112">; def r113 : GR< 113, "r113">;
def r114 : GR< 114, "r114">; def r115 : GR< 115, "r115">;
def r116 : GR< 116, "r116">; def r117 : GR< 117, "r117">;
def r118 : GR< 118, "r118">; def r119 : GR< 119, "r119">;
def r120 : GR< 120, "r120">; def r121 : GR< 121, "r121">;
def r122 : GR< 122, "r122">; def r123 : GR< 123, "r123">;
def r124 : GR< 124, "r124">; def r125 : GR< 125, "r125">;
def r126 : GR< 126, "r126">; def r127 : GR< 127, "r127">;
/* floating-point registers */
def F0 : FP< 0, "f0">; def F1 : FP< 1, "f1">;
def F2 : FP< 2, "f2">; def F3 : FP< 3, "f3">;
def F4 : FP< 4, "f4">; def F5 : FP< 5, "f5">;
def F6 : FP< 6, "f6">; def F7 : FP< 7, "f7">;
def F8 : FP< 8, "f8">; def F9 : FP< 9, "f9">;
def F10 : FP< 10, "f10">; def F11 : FP< 11, "f11">;
def F12 : FP< 12, "f12">; def F13 : FP< 13, "f13">;
def F14 : FP< 14, "f14">; def F15 : FP< 15, "f15">;
def F16 : FP< 16, "f16">; def F17 : FP< 17, "f17">;
def F18 : FP< 18, "f18">; def F19 : FP< 19, "f19">;
def F20 : FP< 20, "f20">; def F21 : FP< 21, "f21">;
def F22 : FP< 22, "f22">; def F23 : FP< 23, "f23">;
def F24 : FP< 24, "f24">; def F25 : FP< 25, "f25">;
def F26 : FP< 26, "f26">; def F27 : FP< 27, "f27">;
def F28 : FP< 28, "f28">; def F29 : FP< 29, "f29">;
def F30 : FP< 30, "f30">; def F31 : FP< 31, "f31">;
def F32 : FP< 32, "f32">; def F33 : FP< 33, "f33">;
def F34 : FP< 34, "f34">; def F35 : FP< 35, "f35">;
def F36 : FP< 36, "f36">; def F37 : FP< 37, "f37">;
def F38 : FP< 38, "f38">; def F39 : FP< 39, "f39">;
def F40 : FP< 40, "f40">; def F41 : FP< 41, "f41">;
def F42 : FP< 42, "f42">; def F43 : FP< 43, "f43">;
def F44 : FP< 44, "f44">; def F45 : FP< 45, "f45">;
def F46 : FP< 46, "f46">; def F47 : FP< 47, "f47">;
def F48 : FP< 48, "f48">; def F49 : FP< 49, "f49">;
def F50 : FP< 50, "f50">; def F51 : FP< 51, "f51">;
def F52 : FP< 52, "f52">; def F53 : FP< 53, "f53">;
def F54 : FP< 54, "f54">; def F55 : FP< 55, "f55">;
def F56 : FP< 56, "f56">; def F57 : FP< 57, "f57">;
def F58 : FP< 58, "f58">; def F59 : FP< 59, "f59">;
def F60 : FP< 60, "f60">; def F61 : FP< 61, "f61">;
def F62 : FP< 62, "f62">; def F63 : FP< 63, "f63">;
def F64 : FP< 64, "f64">; def F65 : FP< 65, "f65">;
def F66 : FP< 66, "f66">; def F67 : FP< 67, "f67">;
def F68 : FP< 68, "f68">; def F69 : FP< 69, "f69">;
def F70 : FP< 70, "f70">; def F71 : FP< 71, "f71">;
def F72 : FP< 72, "f72">; def F73 : FP< 73, "f73">;
def F74 : FP< 74, "f74">; def F75 : FP< 75, "f75">;
def F76 : FP< 76, "f76">; def F77 : FP< 77, "f77">;
def F78 : FP< 78, "f78">; def F79 : FP< 79, "f79">;
def F80 : FP< 80, "f80">; def F81 : FP< 81, "f81">;
def F82 : FP< 82, "f82">; def F83 : FP< 83, "f83">;
def F84 : FP< 84, "f84">; def F85 : FP< 85, "f85">;
def F86 : FP< 86, "f86">; def F87 : FP< 87, "f87">;
def F88 : FP< 88, "f88">; def F89 : FP< 89, "f89">;
def F90 : FP< 90, "f90">; def F91 : FP< 91, "f91">;
def F92 : FP< 92, "f92">; def F93 : FP< 93, "f93">;
def F94 : FP< 94, "f94">; def F95 : FP< 95, "f95">;
def F96 : FP< 96, "f96">; def F97 : FP< 97, "f97">;
def F98 : FP< 98, "f98">; def F99 : FP< 99, "f99">;
def F100 : FP< 100, "f100">; def F101 : FP< 101, "f101">;
def F102 : FP< 102, "f102">; def F103 : FP< 103, "f103">;
def F104 : FP< 104, "f104">; def F105 : FP< 105, "f105">;
def F106 : FP< 106, "f106">; def F107 : FP< 107, "f107">;
def F108 : FP< 108, "f108">; def F109 : FP< 109, "f109">;
def F110 : FP< 110, "f110">; def F111 : FP< 111, "f111">;
def F112 : FP< 112, "f112">; def F113 : FP< 113, "f113">;
def F114 : FP< 114, "f114">; def F115 : FP< 115, "f115">;
def F116 : FP< 116, "f116">; def F117 : FP< 117, "f117">;
def F118 : FP< 118, "f118">; def F119 : FP< 119, "f119">;
def F120 : FP< 120, "f120">; def F121 : FP< 121, "f121">;
def F122 : FP< 122, "f122">; def F123 : FP< 123, "f123">;
def F124 : FP< 124, "f124">; def F125 : FP< 125, "f125">;
def F126 : FP< 126, "f126">; def F127 : FP< 127, "f127">;
/* predicate registers */
def p0 : PR< 0, "p0">; def p1 : PR< 1, "p1">;
def p2 : PR< 2, "p2">; def p3 : PR< 3, "p3">;
def p4 : PR< 4, "p4">; def p5 : PR< 5, "p5">;
def p6 : PR< 6, "p6">; def p7 : PR< 7, "p7">;
def p8 : PR< 8, "p8">; def p9 : PR< 9, "p9">;
def p10 : PR< 10, "p10">; def p11 : PR< 11, "p11">;
def p12 : PR< 12, "p12">; def p13 : PR< 13, "p13">;
def p14 : PR< 14, "p14">; def p15 : PR< 15, "p15">;
def p16 : PR< 16, "p16">; def p17 : PR< 17, "p17">;
def p18 : PR< 18, "p18">; def p19 : PR< 19, "p19">;
def p20 : PR< 20, "p20">; def p21 : PR< 21, "p21">;
def p22 : PR< 22, "p22">; def p23 : PR< 23, "p23">;
def p24 : PR< 24, "p24">; def p25 : PR< 25, "p25">;
def p26 : PR< 26, "p26">; def p27 : PR< 27, "p27">;
def p28 : PR< 28, "p28">; def p29 : PR< 29, "p29">;
def p30 : PR< 30, "p30">; def p31 : PR< 31, "p31">;
def p32 : PR< 32, "p32">; def p33 : PR< 33, "p33">;
def p34 : PR< 34, "p34">; def p35 : PR< 35, "p35">;
def p36 : PR< 36, "p36">; def p37 : PR< 37, "p37">;
def p38 : PR< 38, "p38">; def p39 : PR< 39, "p39">;
def p40 : PR< 40, "p40">; def p41 : PR< 41, "p41">;
def p42 : PR< 42, "p42">; def p43 : PR< 43, "p43">;
def p44 : PR< 44, "p44">; def p45 : PR< 45, "p45">;
def p46 : PR< 46, "p46">; def p47 : PR< 47, "p47">;
def p48 : PR< 48, "p48">; def p49 : PR< 49, "p49">;
def p50 : PR< 50, "p50">; def p51 : PR< 51, "p51">;
def p52 : PR< 52, "p52">; def p53 : PR< 53, "p53">;
def p54 : PR< 54, "p54">; def p55 : PR< 55, "p55">;
def p56 : PR< 56, "p56">; def p57 : PR< 57, "p57">;
def p58 : PR< 58, "p58">; def p59 : PR< 59, "p59">;
def p60 : PR< 60, "p60">; def p61 : PR< 61, "p61">;
def p62 : PR< 62, "p62">; def p63 : PR< 63, "p63">;
// XXX : this is temporary, we'll eventually have the output registers
// in the general purpose register class too?
def out0 : GR<0, "out0">; def out1 : GR<1, "out1">;
def out2 : GR<2, "out2">; def out3 : GR<3, "out3">;
def out4 : GR<4, "out4">; def out5 : GR<5, "out5">;
def out6 : GR<6, "out6">; def out7 : GR<7, "out7">;
// application (special) registers:
// " previous function state" application register
def AR_PFS : GR<0, "ar.pfs">;
// "return pointer" (this is really branch register b0)
def rp : GR<0, "rp">;
// branch reg 6
def B6 : GR<0, "b6">;
//===----------------------------------------------------------------------===//
// Register Class Definitions... now that we have all of the pieces, define the
// top-level register classes. The order specified in the register list is
// implicitly defined to be the register allocation order.
//
// these are the scratch (+stacked) general registers
// ZERO (r0), GP (r1), SP (r12), ThreadP (r13) are not here...
// FIXME/XXX we also reserve a frame pointer (r15)
// FIXME/XXX we also reserve r2 for spilling/filling predicates
// in IA64RegisterInfo.cpp
// FIXME/XXX we also reserve r22 for calculating addresses
// in IA64RegisterInfo.cpp
def GR : RegisterClass<i64, 64,
[/*r2,*/ r3,
r8, r9, r10, r11, r14, /*r15, */
r16, r17, r18, r19, r20, r21, /*r22,*/ r23,
r24, r25, r26, r27, r28, r29, r30, r31,
r32, r33, r34, r35, r36, r37, r38, r39,
r40, r41, r42, r43, r44, r45, r46, r47,
r48, r49, r50, r51, r52, r53, r54, r55,
r56, r57, r58, r59, r60, r61, r62, r63,
r64, r65, r66, r67, r68, r69, r70, r71,
r72, r73, r74, r75, r76, r77, r78, r79,
r80, r81, r82, r83, r84, r85, r86, r87,
r88, r89, r90, r91, r92, r93, r94, r95,
r96, r97, r98, r99, r100, r101, r102, r103,
r104, r105, r106, r107, r108, r109, r110, r111,
r112, r113, r114, r115, r116, r117, r118, r119,
r120, r121, r122, r123, r124, r125, r126, r127]>;
// these are the scratch (+stacked) FP registers
// ZERO (F0) and ONE (F1) are not here
def FP : RegisterClass<f64, 64,
[F6, F7,
F8, F9, F10, F11, F12, F13, F14, F15,
F32, F33, F34, F35, F36, F37, F38, F39,
F40, F41, F42, F43, F44, F45, F46, F47,
F48, F49, F50, F51, F52, F53, F54, F55,
F56, F57, F58, F59, F60, F61, F62, F63,
F64, F65, F66, F67, F68, F69, F70, F71,
F72, F73, F74, F75, F76, F77, F78, F79,
F80, F81, F82, F83, F84, F85, F86, F87,
F88, F89, F90, F91, F92, F93, F94, F95,
F96, F97, F98, F99, F100, F101, F102, F103,
F104, F105, F106, F107, F108, F109, F110, F111,
F112, F113, F114, F115, F116, F117, F118, F119,
F120, F121, F122, F123, F124, F125, F126, F127]>;
// these are the predicate registers, p0 (1/TRUE) is not here
def PR : RegisterClass<i1, 64,
// for now, let's be wimps and only have the scratch predicate regs
[p6, p7, p8, p9, p10, p11, p12, p13, p14, p15]> {
let Size = 64;
}
/*
[p1, p2, p3, p4, p5, p6, p7,
p8, p9, p10, p11, p12, p13, p14, p15,
p16, p17, p18, p19, p20, p21, p22, p23,
p24, p25, p26, p27, p28, p29, p30, p31,
p32, p33, p34, p35, p36, p37, p38, p39,
p40, p41, p42, p43, p44, p45, p46, p47,
p48, p49, p50, p51, p52, p53, p54, p55,
p56, p57, p58, p59, p60, p61, p62, p63]>;
*/

View File

@ -0,0 +1,134 @@
//===-- IA64TargetMachine.cpp - Define TargetMachine for IA64 -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the IA64 specific subclass of TargetMachine.
//
//===----------------------------------------------------------------------===//
#include "IA64TargetMachine.h"
#include "IA64.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
/// IA64TargetMachineModule - Note that this is used on hosts that cannot link
/// in a library unless there are references into the library. In particular,
/// it seems that it is not possible to get things to work on Win32 without
/// this. Though it is unused, do not remove it.
extern "C" int IA64TargetMachineModule;
int IA64TargetMachineModule = 0;
namespace {
cl::opt<bool> DisableOutput("disable-ia64-llc-output", cl::Hidden,
cl::desc("Disable the IA64 asm printer, for use "
"when profiling the code generator."));
// Register the target.
RegisterTarget<IA64TargetMachine> X("ia64", " IA-64 (Itanium)");
}
unsigned IA64TargetMachine::compileTimeMatchQuality() {
#if defined(__ia64__) || defined(__IA64__)
return 50;
#else
return 0;
#endif
}
unsigned IA64TargetMachine::getModuleMatchQuality(const Module &M) {
// we match [iI][aA]*64
bool seenIA64=false;
std::string TT = M.getTargetTriple();
if (TT.size() >= 4) {
if( (TT[0]=='i' || TT[0]=='I') &&
(TT[1]=='a' || TT[1]=='A') ) {
for(unsigned int i=2; i<(TT.size()-1); i++)
if(TT[i]=='6' && TT[i+1]=='4')
seenIA64=true;
}
if(seenIA64)
return 50; // strong match
}
return compileTimeMatchQuality()/2;
}
/// IA64TargetMachine ctor - Create an LP64 architecture model
///
IA64TargetMachine::IA64TargetMachine(const Module &M, IntrinsicLowering *IL)
: TargetMachine("IA64", IL, true),
FrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0) { // FIXME? check this stuff
}
// addPassesToEmitAssembly - We currently use all of the same passes as the JIT
// does to emit statically compiled machine code.
bool IA64TargetMachine::addPassesToEmitAssembly(PassManager &PM,
std::ostream &Out) {
// FIXME: Implement efficient support for garbage collection intrinsics.
PM.add(createLowerGCPass());
// FIXME: Implement the invoke/unwind instructions!
PM.add(createLowerInvokePass());
// FIXME: Implement the switch instruction in the instruction selector!
PM.add(createLowerSwitchPass());
// Make sure that no unreachable blocks are instruction selected.
PM.add(createUnreachableBlockEliminationPass());
PM.add(createIA64PatternInstructionSelector(*this));
/* XXX not yet. ;)
// Run optional SSA-based machine code optimizations next...
if (!NoSSAPeephole)
PM.add(createIA64SSAPeepholeOptimizerPass());
*/
// Print the instruction selected machine code...
if (PrintMachineCode)
PM.add(createMachineFunctionPrinterPass(&std::cerr));
// Perform register allocation to convert to a concrete IA64 representation
PM.add(createRegisterAllocator());
if (PrintMachineCode)
PM.add(createMachineFunctionPrinterPass(&std::cerr));
if (PrintMachineCode)
PM.add(createMachineFunctionPrinterPass(&std::cerr));
// Insert prolog/epilog code. Eliminate abstract frame index references...
PM.add(createPrologEpilogCodeInserter());
/* XXX no, not just yet */
// PM.add(createIA64PeepholeOptimizerPass());
if (PrintMachineCode) // Print the register-allocated code
PM.add(createIA64CodePrinterPass(std::cerr, *this));
if (!DisableOutput)
PM.add(createIA64CodePrinterPass(Out, *this));
// Delete machine code for this function
PM.add(createMachineCodeDeleter());
return false; // success!
}

View File

@ -0,0 +1,48 @@
//===-- IA64TargetMachine.h - Define TargetMachine for IA64 ---*- C++ -*---===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the IA64 specific subclass of TargetMachine.
//
//===----------------------------------------------------------------------===//
#ifndef IA64TARGETMACHINE_H
#define IA64TARGETMACHINE_H
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/PassManager.h"
#include "IA64InstrInfo.h"
namespace llvm {
class IntrinsicLowering;
class IA64TargetMachine : public TargetMachine {
IA64InstrInfo InstrInfo;
TargetFrameInfo FrameInfo;
//IA64JITInfo JITInfo;
public:
IA64TargetMachine(const Module &M, IntrinsicLowering *IL);
virtual const IA64InstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
virtual const MRegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
}
virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
static unsigned getModuleMatchQuality(const Module &M);
static unsigned compileTimeMatchQuality(void);
};
} // End llvm namespace
#endif

17
lib/Target/IA64/Makefile Normal file
View File

@ -0,0 +1,17 @@
##===- lib/Target/IA64/Makefile -----------------------------*- Makefile -*-===##
# The LLVM Compiler Infrastructure
#
# This file was developed by Duraid Madina and is distributed under the
# University of Illinois Open Source License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../..
LIBRARYNAME = LLVMIA64
TARGET = IA64
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = IA64GenRegisterInfo.h.inc IA64GenRegisterNames.inc \
IA64GenRegisterInfo.inc IA64GenInstrNames.inc \
IA64GenInstrInfo.inc IA64GenAsmWriter.inc
include $(LEVEL)/Makefile.common

98
lib/Target/IA64/README Normal file
View File

@ -0,0 +1,98 @@
*** README for the LLVM IA64 Backend "Version 0.01" - March 18, 2004
*** Quote for this version:
"Kaori and Hitomi are naughty!!"
Congratulations, you have found:
****************************************************************
* @@@ @@@ @@@ @@@ @@@@@@@@@@ *
* @@@ @@@ @@@ @@@ @@@@@@@@@@@ *
* @@! @@! @@! @@@ @@! @@! @@! *
* !@! !@! !@! @!@ !@! !@! !@! *
* @!! @!! @!@ !@! @!! !!@ @!@ *
* !!! !!! !@! !!! !@! ! !@! *
* !!: !!: :!: !!: !!: !!: *
* :!: :!: ::!!:! :!: :!: *
* :: :::: :: :::: :::: ::: :: *
* : :: : : : :: : : : : : *
* *
* *
* @@@@@@ @@@ @@@ @@@ @@@@@@ @@@@@@ @@@ *
* @@@@@@@@ @@@@ @@@ @@@ @@@@@@@@ @@@@@@@ @@@@ *
* @@! @@@ @@!@!@@@ @@! @@! @@@ !@@ @@!@! *
* !@! @!@ !@!!@!@! !@! !@! @!@ !@! !@!!@! *
* @!@ !@! @!@ !!@! !!@ @!@!@!@! !!@@!@! @!! @!! *
* !@! !!! !@! !!! !!! !!!@!!!! @!!@!!!! !!! !@! *
* !!: !!! !!: !!! !!: !!: !!! !:! !:! :!!:!:!!: *
* :!: !:! :!: !:! :!: :!: !:! :!: !:! !:::!!::: *
* ::::: :: :: :: :: :: ::: :::: ::: ::: *
* : : : :: : : : : : :: : : ::: *
* *
****************************************************************
* Bow down, bow down, before the power of IA64! Or be crushed, *
* be crushed, by its jolly registers of doom!! *
****************************************************************
DEVELOPMENT PLAN:
_ you are 2005 maybe 2005 2006 2006 and
/ here | | | beyond
v v v v |
v
CLEAN UP ADD INSTRUCTION ADD PLAY WITH
INSTRUCTION --> SCHEDULING AND --> JIT --> DYNAMIC --> FUTURE WORK
SELECTION BUNDLING SUPPORT REOPTIMIZATION
DISCLAIMER AND PROMISE:
As of the time of this release, you are probably better off using Intel C/C++
or GCC. The performance of the code emitted right now is, in a word,
terrible. Check back in a few months - the story will be different then,
I guarantee it.
TODO:
- clean up and thoroughly test the isel patterns.
- fix up floating point
(nb http://gcc.gnu.org/wiki?pagename=ia64%20floating%20point )
- bundling!
(we will avoid the mess that is:
http://gcc.gnu.org/ml/gcc/2003-12/msg00832.html )
- instruction scheduling (yep)
- write truly inspirational documentation
- if-conversion (predicate database/knowledge? etc etc)
- counted loop support
- make integer + FP mul/div more clever (we have fixed pseudocode atm)
- track and use comparison complements
INFO:
- we are strictly LP64 here, no support for ILP32 on HP-UX. Linux users
don't need to worry about this.
- i have instruction scheduling/bundling pseudocode, that really works
(has been tested, albeit at the perl-script level).
so, before you go write your own, send me an email!
KNOWN DEFECTS AT THE CURRENT TIME:
- no varargs
- alloca doesn't work (indeed, stack frame layout is bogus)
- no support for big-endian environments
- (not really the backend, but...) the CFE has some issues on IA64.
these will probably be fixed soon.
ACKNOWLEDGEMENTS:
- Chris Lattner (x100)
- Other LLVM developers ("hey, that looks familiar")
CONTACT:
- You can email me at duraid@octopus.com.au. If you find a small bug,
just email me. If you find a big bug, please file a bug report
in bugzilla! http://llvm.cs.uiuc.edu is your one stop shop for all
things LLVM.