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
This commit is contained in:
Che-Liang Chiou 2010-11-30 07:34:44 +00:00
parent cf82dc376a
commit 3f8e617891
3 changed files with 118 additions and 9 deletions

View File

@ -49,6 +49,8 @@ public:
virtual void EmitInstruction(const MachineInstr *MI); virtual void EmitInstruction(const MachineInstr *MI);
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); 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. // autogen'd.
void printInstruction(const MachineInstr *MI, raw_ostream &OS); void printInstruction(const MachineInstr *MI, raw_ostream &OS);
@ -61,7 +63,7 @@ private:
static const char PARAM_PREFIX[] = "__param_"; static const char PARAM_PREFIX[] = "__param_";
static const char *getRegisterTypeName(unsigned RegNo){ static const char *getRegisterTypeName(unsigned RegNo) {
#define TEST_REGCLS(cls, clsstr) \ #define TEST_REGCLS(cls, clsstr) \
if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr; if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr;
TEST_REGCLS(RRegs32, s32); TEST_REGCLS(RRegs32, s32);
@ -72,8 +74,7 @@ static const char *getRegisterTypeName(unsigned RegNo){
return NULL; 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) { for (int i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i); const MachineOperand &MO = MI->getOperand(i);
if (MO.getType() == MachineOperand::MO_Register) if (MO.getType() == MachineOperand::MO_Register)
@ -119,13 +120,13 @@ void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
// Replace "%type" if found // Replace "%type" if found
StringRef strref = OS.str(); StringRef strref = OS.str();
size_t pos; size_t pos;
if ((pos = strref.find("%type")) == StringRef::npos) { if ((pos = strref.find("%type")) != StringRef::npos) {
OutStreamer.EmitRawText(strref);
return;
}
std::string str = strref; std::string str = strref;
str.replace(pos, /*strlen("%type")==*/5, getInstructionTypeName(MI)); str.replace(pos, /*strlen("%type")==*/5, getInstructionTypeName(MI));
OutStreamer.EmitRawText(StringRef(str)); strref = StringRef(str);
}
OutStreamer.EmitRawText(strref);
} }
void PTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 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() { void PTXAsmPrinter::EmitFunctionDeclaration() {
// The function label could have already been emitted if two symbols end up // The function label could have already been emitted if two symbols end up
// conflicting due to asm renaming. Detect this and emit an error. // conflicting due to asm renaming. Detect this and emit an error.

View File

@ -14,6 +14,7 @@
#include "PTX.h" #include "PTX.h"
#include "PTXTargetMachine.h" #include "PTXTargetMachine.h"
#include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/DerivedTypes.h"
using namespace llvm; using namespace llvm;
@ -30,9 +31,16 @@ class PTXDAGToDAGISel : public SelectionDAGISel {
SDNode *Select(SDNode *Node); 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 the pieces auto'gened from the target description
#include "PTXGenDAGISel.inc" #include "PTXGenDAGISel.inc"
private:
bool isImm (const SDValue &operand);
bool SelectImm (const SDValue &operand, SDValue &imm);
}; // class PTXDAGToDAGISel }; // class PTXDAGToDAGISel
} // namespace } // namespace
@ -51,3 +59,54 @@ SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
// SelectCode() is auto'gened // SelectCode() is auto'gened
return SelectCode(Node); 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<ConstantSDNode>(node);
imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(), MVT::i32);
return true;
}

View File

@ -17,6 +17,31 @@
include "PTXInstrFormats.td" include "PTXInstrFormats.td"
//===----------------------------------------------------------------------===//
// Instruction Pattern Stuff
//===----------------------------------------------------------------------===//
def load_global : PatFrag<(ops node:$ptr), (load node:$ptr), [{
if (const Value *Src = cast<LoadSDNode>(N)->getSrcValue())
if (const PointerType *PT = dyn_cast<PointerType>(Src->getType()))
return PT->getAddressSpace() <= 255;
return false;
}]>;
// Addressing modes.
def ADDRri : ComplexPattern<i32, 2, "SelectADDRri", [], []>;
def ADDRii : ComplexPattern<i32, 2, "SelectADDRii", [], []>;
// Address operands
def MEMri : Operand<i32> {
let PrintMethod = "printMemOperand";
let MIOperandInfo = (ops RRegs32, i32imm);
}
def MEMii : Operand<i32> {
let PrintMethod = "printMemOperand";
let MIOperandInfo = (ops i32imm, i32imm);
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// PTX Specific Node Definitions // PTX Specific Node Definitions
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -41,6 +66,17 @@ multiclass INT3<string opcstr, SDNode opnode> {
[(set RRegs32:$d, (opnode RRegs32:$a, imm:$b))]>; [(set RRegs32:$d, (opnode RRegs32:$a, imm:$b))]>;
} }
multiclass PTX_LD<string opstr, RegisterClass RC, PatFrag pat_load> {
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 // Instructions
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -69,6 +105,8 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
[(set RRegs32:$d, imm:$a)]>; [(set RRegs32:$d, imm:$a)]>;
} }
defm LDg : PTX_LD<"ld.global", RRegs32, load_global>;
///===- Control Flow Instructions -----------------------------------------===// ///===- Control Flow Instructions -----------------------------------------===//
let isReturn = 1, isTerminator = 1, isBarrier = 1 in { let isReturn = 1, isTerminator = 1, isBarrier = 1 in {