From 3f8e61789100ee411d0bfe00fb90df60eaed65f5 Mon Sep 17 00:00:00 2001 From: Che-Liang Chiou Date: Tue, 30 Nov 2010 07:34:44 +0000 Subject: [PATCH] ptx: add ld instruction support register and register-immediate addressing mode todo: immediate and register-register addressing mode git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120407 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PTX/PTXAsmPrinter.cpp | 30 ++++++++++----- lib/Target/PTX/PTXISelDAGToDAG.cpp | 59 ++++++++++++++++++++++++++++++ lib/Target/PTX/PTXInstrInfo.td | 38 +++++++++++++++++++ 3 files changed, 118 insertions(+), 9 deletions(-) diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index 175b3c47505..03f177b2fa8 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -49,6 +49,8 @@ public: virtual void EmitInstruction(const MachineInstr *MI); void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, + const char *Modifier = 0); // autogen'd. void printInstruction(const MachineInstr *MI, raw_ostream &OS); @@ -61,7 +63,7 @@ private: static const char PARAM_PREFIX[] = "__param_"; -static const char *getRegisterTypeName(unsigned RegNo){ +static const char *getRegisterTypeName(unsigned RegNo) { #define TEST_REGCLS(cls, clsstr) \ if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr; TEST_REGCLS(RRegs32, s32); @@ -72,8 +74,7 @@ static const char *getRegisterTypeName(unsigned RegNo){ return NULL; } -static const char *getInstructionTypeName(const MachineInstr *MI) -{ +static const char *getInstructionTypeName(const MachineInstr *MI) { for (int i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); if (MO.getType() == MachineOperand::MO_Register) @@ -119,13 +120,13 @@ void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) { // Replace "%type" if found StringRef strref = OS.str(); size_t pos; - if ((pos = strref.find("%type")) == StringRef::npos) { - OutStreamer.EmitRawText(strref); - return; + if ((pos = strref.find("%type")) != StringRef::npos) { + std::string str = strref; + str.replace(pos, /*strlen("%type")==*/5, getInstructionTypeName(MI)); + strref = StringRef(str); } - std::string str = strref; - str.replace(pos, /*strlen("%type")==*/5, getInstructionTypeName(MI)); - OutStreamer.EmitRawText(StringRef(str)); + + OutStreamer.EmitRawText(strref); } void PTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum, @@ -145,6 +146,17 @@ void PTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum, } } +void PTXAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, + raw_ostream &OS, const char *Modifier) { + printOperand(MI, opNum, OS); + + if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) + return; // don't print "+0" + + OS << "+"; + printOperand(MI, opNum+1, OS); +} + void PTXAsmPrinter::EmitFunctionDeclaration() { // The function label could have already been emitted if two symbols end up // conflicting due to asm renaming. Detect this and emit an error. diff --git a/lib/Target/PTX/PTXISelDAGToDAG.cpp b/lib/Target/PTX/PTXISelDAGToDAG.cpp index da9136511db..1107236332d 100644 --- a/lib/Target/PTX/PTXISelDAGToDAG.cpp +++ b/lib/Target/PTX/PTXISelDAGToDAG.cpp @@ -14,6 +14,7 @@ #include "PTX.h" #include "PTXTargetMachine.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/DerivedTypes.h" using namespace llvm; @@ -30,9 +31,16 @@ class PTXDAGToDAGISel : public SelectionDAGISel { SDNode *Select(SDNode *Node); + // Complex Pattern Selectors. + bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset); + bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset); + // Include the pieces auto'gened from the target description #include "PTXGenDAGISel.inc" + private: + bool isImm (const SDValue &operand); + bool SelectImm (const SDValue &operand, SDValue &imm); }; // class PTXDAGToDAGISel } // namespace @@ -51,3 +59,54 @@ SDNode *PTXDAGToDAGISel::Select(SDNode *Node) { // SelectCode() is auto'gened return SelectCode(Node); } + +// Match memory operand of the form [reg+reg] and [reg+imm] +bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getNumOperands() >= 2 && + isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1))) + return false; // let SelectADDRii handle the [imm+imm] case + + // try [reg+imm] and [imm+reg] + if (Addr.getOpcode() == ISD::ADD) + for (int i = 0; i < 2; i ++) + if (SelectImm(Addr.getOperand(1-i), Offset)) { + Base = Addr.getOperand(i); + return true; + } + + // okay, it's [reg+reg] + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + +// Match memory operand of the form [imm+imm] and [imm] +bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::ADD) { + return SelectImm(Addr.getOperand(0), Base) && + SelectImm(Addr.getOperand(1), Offset); + } + + if (SelectImm(Addr, Base)) { + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + return false; +} + +bool PTXDAGToDAGISel::isImm(const SDValue &operand) { + return ConstantSDNode::classof(operand.getNode()); +} + +bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) { + SDNode *node = operand.getNode(); + if (!ConstantSDNode::classof(node)) + return false; + + ConstantSDNode *CN = cast(node); + imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(), MVT::i32); + return true; +} diff --git a/lib/Target/PTX/PTXInstrInfo.td b/lib/Target/PTX/PTXInstrInfo.td index 71d9016cd76..01e0f2a2b41 100644 --- a/lib/Target/PTX/PTXInstrInfo.td +++ b/lib/Target/PTX/PTXInstrInfo.td @@ -17,6 +17,31 @@ include "PTXInstrFormats.td" +//===----------------------------------------------------------------------===// +// Instruction Pattern Stuff +//===----------------------------------------------------------------------===// + +def load_global : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + return PT->getAddressSpace() <= 255; + return false; +}]>; + +// Addressing modes. +def ADDRri : ComplexPattern; +def ADDRii : ComplexPattern; + +// Address operands +def MEMri : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops RRegs32, i32imm); +} +def MEMii : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops i32imm, i32imm); +} + //===----------------------------------------------------------------------===// // PTX Specific Node Definitions //===----------------------------------------------------------------------===// @@ -41,6 +66,17 @@ multiclass INT3 { [(set RRegs32:$d, (opnode RRegs32:$a, imm:$b))]>; } +multiclass PTX_LD { + def ri : InstPTX<(outs RC:$d), + (ins MEMri:$a), + !strconcat(opstr, ".%type\t$d, [$a]"), + [(set RC:$d, (pat_load ADDRri:$a))]>; + def ii : InstPTX<(outs RC:$d), + (ins MEMii:$a), + !strconcat(opstr, ".%type\t$d, [$a]"), + [(set RC:$d, (pat_load ADDRii:$a))]>; +} + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -69,6 +105,8 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1 in { [(set RRegs32:$d, imm:$a)]>; } +defm LDg : PTX_LD<"ld.global", RRegs32, load_global>; + ///===- Control Flow Instructions -----------------------------------------===// let isReturn = 1, isTerminator = 1, isBarrier = 1 in {