aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target
diff options
context:
space:
mode:
authorJustin Holewinski <justin.holewinski@gmail.com>2011-06-16 17:50:00 +0000
committerJustin Holewinski <justin.holewinski@gmail.com>2011-06-16 17:50:00 +0000
commite0aef2de81c670f3e4229b979e81178860a458cb (patch)
treef6732316482108699b84e2a37da89367073a3d4f /lib/Target
parent1b91bcddd5a26c8bfad7cc1195aa092d42053c0e (diff)
downloadexternal_llvm-e0aef2de81c670f3e4229b979e81178860a458cb.zip
external_llvm-e0aef2de81c670f3e4229b979e81178860a458cb.tar.gz
external_llvm-e0aef2de81c670f3e4229b979e81178860a458cb.tar.bz2
PTX: Finish new calling convention implementation
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133172 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/PTX/CMakeLists.txt1
-rw-r--r--lib/Target/PTX/Makefile1
-rw-r--r--lib/Target/PTX/PTX.td6
-rw-r--r--lib/Target/PTX/PTXAsmPrinter.cpp118
-rw-r--r--lib/Target/PTX/PTXCallingConv.td36
-rw-r--r--lib/Target/PTX/PTXISelLowering.cpp171
-rw-r--r--lib/Target/PTX/PTXMFInfoExtract.cpp6
-rw-r--r--lib/Target/PTX/PTXMachineFunctionInfo.h17
8 files changed, 233 insertions, 123 deletions
diff --git a/lib/Target/PTX/CMakeLists.txt b/lib/Target/PTX/CMakeLists.txt
index 331266d..c4448d6 100644
--- a/lib/Target/PTX/CMakeLists.txt
+++ b/lib/Target/PTX/CMakeLists.txt
@@ -1,6 +1,7 @@
set(LLVM_TARGET_DEFINITIONS PTX.td)
tablegen(PTXGenAsmWriter.inc -gen-asm-writer)
+tablegen(PTXGenCallingConv.inc -gen-callingconv)
tablegen(PTXGenDAGISel.inc -gen-dag-isel)
tablegen(PTXGenInstrInfo.inc -gen-instr-desc)
tablegen(PTXGenInstrNames.inc -gen-instr-enums)
diff --git a/lib/Target/PTX/Makefile b/lib/Target/PTX/Makefile
index 2c40d69..844480f 100644
--- a/lib/Target/PTX/Makefile
+++ b/lib/Target/PTX/Makefile
@@ -13,6 +13,7 @@ TARGET = PTX
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = PTXGenAsmWriter.inc \
+ PTXGenCallingConv.inc \
PTXGenDAGISel.inc \
PTXGenInstrInfo.inc \
PTXGenInstrNames.inc \
diff --git a/lib/Target/PTX/PTX.td b/lib/Target/PTX/PTX.td
index 231866a..2c7bd3b 100644
--- a/lib/Target/PTX/PTX.td
+++ b/lib/Target/PTX/PTX.td
@@ -72,6 +72,12 @@ def : Proc<"generic", []>;
include "PTXRegisterInfo.td"
//===----------------------------------------------------------------------===//
+// Calling Conventions
+//===----------------------------------------------------------------------===//
+
+include "PTXCallingConv.td"
+
+//===----------------------------------------------------------------------===//
// Instruction Descriptions
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp
index cf8d461..1142144 100644
--- a/lib/Target/PTX/PTXAsmPrinter.cpp
+++ b/lib/Target/PTX/PTXAsmPrinter.cpp
@@ -80,11 +80,11 @@ static const char *getRegisterTypeName(unsigned RegNo) {
#define TEST_REGCLS(cls, clsstr) \
if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr;
TEST_REGCLS(RegPred, pred);
- TEST_REGCLS(RegI16, u16);
- TEST_REGCLS(RegI32, u32);
- TEST_REGCLS(RegI64, u64);
- TEST_REGCLS(RegF32, f32);
- TEST_REGCLS(RegF64, f64);
+ TEST_REGCLS(RegI16, b16);
+ TEST_REGCLS(RegI32, b32);
+ TEST_REGCLS(RegI64, b64);
+ TEST_REGCLS(RegF32, b32);
+ TEST_REGCLS(RegF64, b64);
#undef TEST_REGCLS
llvm_unreachable("Not in any register class!");
@@ -394,17 +394,23 @@ void PTXAsmPrinter::EmitFunctionDeclaration() {
const PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
const bool isKernel = MFI->isKernel();
- unsigned reg;
std::string decl = isKernel ? ".entry" : ".func";
- // Print return register
- reg = MFI->retReg();
- if (!isKernel && reg != PTX::NoRegister) {
- decl += " (.reg ."; // FIXME: could it return in .param space?
- decl += getRegisterTypeName(reg);
- decl += " ";
- decl += getRegisterName(reg);
+ if (!isKernel) {
+ decl += " (";
+
+ for (PTXMachineFunctionInfo::ret_iterator
+ i = MFI->retRegBegin(), e = MFI->retRegEnd(), b = i;
+ i != e; ++i) {
+ if (i != b) {
+ decl += ", ";
+ }
+ decl += ".reg .";
+ decl += getRegisterTypeName(*i);
+ decl += " ";
+ decl += getRegisterName(*i);
+ }
decl += ")";
}
@@ -412,40 +418,66 @@ void PTXAsmPrinter::EmitFunctionDeclaration() {
decl += " ";
decl += CurrentFnSym->getName().str();
- // Print parameter list
- if (!MFI->argRegEmpty()) {
- decl += " (";
+ decl += " (";
+
+ unsigned cnt = 0;
+
+ // Print parameters
+ for (PTXMachineFunctionInfo::reg_iterator
+ i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i;
+ i != e; ++i) {
+ if (i != b) {
+ decl += ", ";
+ }
if (isKernel) {
- unsigned cnt = 0;
- for(PTXMachineFunctionInfo::reg_iterator
- i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i;
- i != e; ++i) {
- reg = *i;
- assert(reg != PTX::NoRegister && "Not a valid register!");
- if (i != b)
- decl += ", ";
- decl += ".param .";
- decl += getRegisterTypeName(reg);
- decl += " ";
- decl += PARAM_PREFIX;
- decl += utostr(++cnt);
- }
+ decl += ".param .b";
+ decl += utostr(*i);
+ decl += " ";
+ decl += PARAM_PREFIX;
+ decl += utostr(++cnt);
} else {
- for (PTXMachineFunctionInfo::reg_iterator
- i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i;
- i != e; ++i) {
- reg = *i;
- assert(reg != PTX::NoRegister && "Not a valid register!");
- if (i != b)
- decl += ", ";
- decl += ".reg .";
- decl += getRegisterTypeName(reg);
- decl += " ";
- decl += getRegisterName(reg);
- }
+ decl += ".reg .";
+ decl += getRegisterTypeName(*i);
+ decl += " ";
+ decl += getRegisterName(*i);
}
- decl += ")";
}
+ decl += ")";
+
+ // // Print parameter list
+ // if (!MFI->argRegEmpty()) {
+ // decl += " (";
+ // if (isKernel) {
+ // unsigned cnt = 0;
+ // for(PTXMachineFunctionInfo::reg_iterator
+ // i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i;
+ // i != e; ++i) {
+ // reg = *i;
+ // assert(reg != PTX::NoRegister && "Not a valid register!");
+ // if (i != b)
+ // decl += ", ";
+ // decl += ".param .";
+ // decl += getRegisterTypeName(reg);
+ // decl += " ";
+ // decl += PARAM_PREFIX;
+ // decl += utostr(++cnt);
+ // }
+ // } else {
+ // for (PTXMachineFunctionInfo::reg_iterator
+ // i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i;
+ // i != e; ++i) {
+ // reg = *i;
+ // assert(reg != PTX::NoRegister && "Not a valid register!");
+ // if (i != b)
+ // decl += ", ";
+ // decl += ".reg .";
+ // decl += getRegisterTypeName(reg);
+ // decl += " ";
+ // decl += getRegisterName(reg);
+ // }
+ // }
+ // decl += ")";
+ // }
OutStreamer.EmitRawText(Twine(decl));
}
diff --git a/lib/Target/PTX/PTXCallingConv.td b/lib/Target/PTX/PTXCallingConv.td
new file mode 100644
index 0000000..4d7759b
--- /dev/null
+++ b/lib/Target/PTX/PTXCallingConv.td
@@ -0,0 +1,36 @@
+//===--- PTXCallingConv.td - Calling Conventions -----------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This describes the calling conventions for the PTX architecture.
+//
+//===----------------------------------------------------------------------===//
+
+// Currently, we reserve one register of each type for return values and let
+// the rest be used for parameters. This is a dirty hack, but I am not sure
+// how to tell LLVM that registers used for parameter passing cannot be used
+// for return values.
+
+// PTX Calling Conventions
+def CC_PTX : CallingConv<[
+ CCIfType<[i1], CCAssignToReg<[P1, P2, P3, P4, P5, P6, P7]>>,
+ CCIfType<[i16], CCAssignToReg<[RH1, RH2, RH3, RH4, RH5, RH6, RH7]>>,
+ CCIfType<[i32, f32], CCAssignToReg<[R1, R2, R3, R4, R5, R6, R7]>>,
+ CCIfType<[i64, f64], CCAssignToReg<[RD1, RD2, RD3, RD4, RD5, RD6, RD7]>>
+]>;
+
+//===----------------------------------------------------------------------===//
+// Return Value Calling Conventions
+//===----------------------------------------------------------------------===//
+
+def RetCC_PTX : CallingConv<[
+ CCIfType<[i1], CCAssignToReg<[P0]>>,
+ CCIfType<[i16], CCAssignToReg<[RH0]>>,
+ CCIfType<[i32, f32], CCAssignToReg<[R0]>>,
+ CCIfType<[i64, f64], CCAssignToReg<[RD0]>>
+]>;
diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp
index cacd5c8..c3cdaba 100644
--- a/lib/Target/PTX/PTXISelLowering.cpp
+++ b/lib/Target/PTX/PTXISelLowering.cpp
@@ -16,6 +16,7 @@
#include "PTXMachineFunctionInfo.h"
#include "PTXRegisterInfo.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
@@ -24,6 +25,16 @@
using namespace llvm;
+//===----------------------------------------------------------------------===//
+// Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+#include "PTXGenCallingConv.inc"
+
+//===----------------------------------------------------------------------===//
+// TargetLowering Implementation
+//===----------------------------------------------------------------------===//
+
PTXTargetLowering::PTXTargetLowering(TargetMachine &TM)
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
// Set up the register classes.
@@ -195,44 +206,72 @@ SDValue PTXTargetLowering::
break;
}
- // Make sure we don't add argument registers twice
- if (MFI->isDoneAddArg())
- llvm_unreachable("cannot add argument registers twice");
-
- // Reset argmap before allocation
- for (struct argmap_entry *i = argmap, *e = argmap + array_lengthof(argmap);
- i != e; ++ i)
- i->reset();
-
- for (int i = 0, e = Ins.size(); i != e; ++ i) {
- MVT::SimpleValueType VT = Ins[i].VT.SimpleTy;
+ if (MFI->isKernel()) {
+ // For kernel functions, we just need to emit the proper READ_PARAM ISDs
+ for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
- struct argmap_entry *entry = std::find(argmap,
- argmap + array_lengthof(argmap), VT);
- if (entry == argmap + array_lengthof(argmap))
- llvm_unreachable("Type of argument is not supported");
+ assert(Ins[i].VT != MVT::i1 && "Kernels cannot take pred operands");
- if (MFI->isKernel() && entry->RC == PTX::RegPredRegisterClass)
- llvm_unreachable("cannot pass preds to kernel");
+ SDValue ArgValue = DAG.getNode(PTXISD::READ_PARAM, dl, Ins[i].VT, Chain,
+ DAG.getTargetConstant(i, MVT::i32));
+ InVals.push_back(ArgValue);
- MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo();
-
- unsigned preg = *++(entry->loc); // allocate start from register 1
- unsigned vreg = RegInfo.createVirtualRegister(entry->RC);
- RegInfo.addLiveIn(preg, vreg);
-
- MFI->addArgReg(preg);
-
- SDValue inval;
- if (MFI->isKernel())
- inval = DAG.getNode(PTXISD::READ_PARAM, dl, VT, Chain,
- DAG.getTargetConstant(i, MVT::i32));
- else
- inval = DAG.getCopyFromReg(Chain, dl, vreg, VT);
- InVals.push_back(inval);
+ // Instead of storing a physical register in our argument list, we just
+ // store the total size of the parameter, in bits. The ASM printer
+ // knows how to process this.
+ MFI->addArgReg(Ins[i].VT.getStoreSizeInBits());
+ }
+ }
+ else {
+ // For device functions, we use the PTX calling convention to do register
+ // assignments then create CopyFromReg ISDs for the allocated registers
+
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), ArgLocs,
+ *DAG.getContext());
+
+ CCInfo.AnalyzeFormalArguments(Ins, CC_PTX);
+
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+
+ CCValAssign& VA = ArgLocs[i];
+ EVT RegVT = VA.getLocVT();
+ TargetRegisterClass* TRC = 0;
+
+ assert(VA.isRegLoc() && "CCValAssign must be RegLoc");
+
+ // Determine which register class we need
+ if (RegVT == MVT::i1) {
+ TRC = PTX::RegPredRegisterClass;
+ }
+ else if (RegVT == MVT::i16) {
+ TRC = PTX::RegI16RegisterClass;
+ }
+ else if (RegVT == MVT::i32) {
+ TRC = PTX::RegI32RegisterClass;
+ }
+ else if (RegVT == MVT::i64) {
+ TRC = PTX::RegI64RegisterClass;
+ }
+ else if (RegVT == MVT::f32) {
+ TRC = PTX::RegF32RegisterClass;
+ }
+ else if (RegVT == MVT::f64) {
+ TRC = PTX::RegF64RegisterClass;
+ }
+ else {
+ llvm_unreachable("Unknown parameter type");
+ }
+
+ unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC);
+ MF.getRegInfo().addLiveIn(VA.getLocReg(), Reg);
+
+ SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
+ InVals.push_back(ArgValue);
+
+ MFI->addArgReg(VA.getLocReg());
+ }
}
-
- MFI->doneAddArg();
return Chain;
}
@@ -254,51 +293,43 @@ SDValue PTXTargetLowering::
assert(Outs.size() == 0 && "Kernel must return void.");
return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain);
case CallingConv::PTX_Device:
- assert(Outs.size() <= 1 && "Can at most return one value.");
+ //assert(Outs.size() <= 1 && "Can at most return one value.");
break;
}
- // PTX_Device
-
- // return void
- if (Outs.size() == 0)
- return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain);
+ MachineFunction& MF = DAG.getMachineFunction();
+ PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
+ getTargetMachine(), RVLocs, *DAG.getContext());
SDValue Flag;
- unsigned reg;
- if (Outs[0].VT == MVT::i16) {
- reg = PTX::RH0;
- }
- else if (Outs[0].VT == MVT::i32) {
- reg = PTX::R0;
- }
- else if (Outs[0].VT == MVT::i64) {
- reg = PTX::RD0;
- }
- else if (Outs[0].VT == MVT::f32) {
- reg = PTX::R0;
- }
- else {
- assert(Outs[0].VT == MVT::f64 && "Can return only basic types");
- reg = PTX::RD0;
- }
+ CCInfo.AnalyzeReturn(Outs, RetCC_PTX);
- MachineFunction &MF = DAG.getMachineFunction();
- PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
- MFI->setRetReg(reg);
+ for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
+
+ CCValAssign& VA = RVLocs[i];
- // If this is the first return lowered for this function, add the regs to the
- // liveout set for the function
- if (DAG.getMachineFunction().getRegInfo().liveout_empty())
- DAG.getMachineFunction().getRegInfo().addLiveOut(reg);
+ assert(VA.isRegLoc() && "CCValAssign must be RegLoc");
- // Copy the result values into the output registers
- Chain = DAG.getCopyToReg(Chain, dl, reg, OutVals[0], Flag);
+ unsigned Reg = VA.getLocReg();
- // Guarantee that all emitted copies are stuck together,
- // avoiding something bad
- Flag = Chain.getValue(1);
+ DAG.getMachineFunction().getRegInfo().addLiveOut(Reg);
- return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag);
+ Chain = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i], Flag);
+
+ // Guarantee that all emitted copies are stuck together,
+ // avoiding something bad
+ Flag = Chain.getValue(1);
+
+ MFI->addRetReg(Reg);
+ }
+
+ if (Flag.getNode() == 0) {
+ return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain);
+ }
+ else {
+ return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag);
+ }
}
diff --git a/lib/Target/PTX/PTXMFInfoExtract.cpp b/lib/Target/PTX/PTXMFInfoExtract.cpp
index c5e1910..6fe9e6c 100644
--- a/lib/Target/PTX/PTXMFInfoExtract.cpp
+++ b/lib/Target/PTX/PTXMFInfoExtract.cpp
@@ -54,8 +54,6 @@ bool PTXMFInfoExtract::runOnMachineFunction(MachineFunction &MF) {
DEBUG(dbgs() << "******** PTX FUNCTION LOCAL VAR REG DEF ********\n");
- unsigned retreg = MFI->retReg();
-
DEBUG(dbgs()
<< "PTX::NoRegister == " << PTX::NoRegister << "\n"
<< "PTX::NUM_TARGET_REGS == " << PTX::NUM_TARGET_REGS << "\n");
@@ -68,15 +66,13 @@ bool PTXMFInfoExtract::runOnMachineFunction(MachineFunction &MF) {
// FIXME: This is a slow linear scanning
for (unsigned reg = PTX::NoRegister + 1; reg < PTX::NUM_TARGET_REGS; ++reg)
if (MRI.isPhysRegUsed(reg) &&
- reg != retreg &&
+ !MFI->isRetReg(reg) &&
(MFI->isKernel() || !MFI->isArgReg(reg)))
MFI->addLocalVarReg(reg);
// Notify MachineFunctionInfo that I've done adding local var reg
MFI->doneAddLocalVar();
- DEBUG(dbgs() << "Return Reg: " << retreg << "\n");
-
DEBUG(for (PTXMachineFunctionInfo::reg_iterator
i = MFI->argRegBegin(), e = MFI->argRegEnd();
i != e; ++i)
diff --git a/lib/Target/PTX/PTXMachineFunctionInfo.h b/lib/Target/PTX/PTXMachineFunctionInfo.h
index 81df1c2..1da4b5d 100644
--- a/lib/Target/PTX/PTXMachineFunctionInfo.h
+++ b/lib/Target/PTX/PTXMachineFunctionInfo.h
@@ -15,6 +15,7 @@
#define PTX_MACHINE_FUNCTION_INFO_H
#include "PTX.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/CodeGen/MachineFunction.h"
namespace llvm {
@@ -25,7 +26,7 @@ class PTXMachineFunctionInfo : public MachineFunctionInfo {
private:
bool is_kernel;
std::vector<unsigned> reg_arg, reg_local_var;
- unsigned reg_ret;
+ DenseSet<unsigned> reg_ret;
bool _isDoneAddArg;
public:
@@ -39,19 +40,18 @@ public:
void addArgReg(unsigned reg) { reg_arg.push_back(reg); }
void addLocalVarReg(unsigned reg) { reg_local_var.push_back(reg); }
- void setRetReg(unsigned reg) { reg_ret = reg; }
+ void addRetReg(unsigned reg) { reg_ret.insert(reg); }
void doneAddArg(void) {
_isDoneAddArg = true;
}
void doneAddLocalVar(void) {}
- bool isDoneAddArg(void) { return _isDoneAddArg; }
-
bool isKernel() const { return is_kernel; }
typedef std::vector<unsigned>::const_iterator reg_iterator;
typedef std::vector<unsigned>::const_reverse_iterator reg_reverse_iterator;
+ typedef DenseSet<unsigned>::const_iterator ret_iterator;
bool argRegEmpty() const { return reg_arg.empty(); }
int getNumArg() const { return reg_arg.size(); }
@@ -64,12 +64,19 @@ public:
reg_iterator localVarRegBegin() const { return reg_local_var.begin(); }
reg_iterator localVarRegEnd() const { return reg_local_var.end(); }
- unsigned retReg() const { return reg_ret; }
+ bool retRegEmpty() const { return reg_ret.empty(); }
+ int getNumRet() const { return reg_ret.size(); }
+ ret_iterator retRegBegin() const { return reg_ret.begin(); }
+ ret_iterator retRegEnd() const { return reg_ret.end(); }
bool isArgReg(unsigned reg) const {
return std::find(reg_arg.begin(), reg_arg.end(), reg) != reg_arg.end();
}
+ bool isRetReg(unsigned reg) const {
+ return std::find(reg_ret.begin(), reg_ret.end(), reg) != reg_ret.end();
+ }
+
bool isLocalVarReg(unsigned reg) const {
return std::find(reg_local_var.begin(), reg_local_var.end(), reg)
!= reg_local_var.end();