[NVPTX] Start conversion to MC infrastructure

This change converts the NVPTX target to use the MC infrastructure
instead of directly emitting MachineInstr instances. This brings
the target more up-to-date with LLVM TOT, and should fix PR15175
and PR15958 (libNVPTXInstPrinter is empty) as a side-effect.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187798 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Justin Holewinski 2013-08-06 14:13:27 +00:00
parent 8775a51d94
commit 82767327c5
11 changed files with 611 additions and 317 deletions

View File

@ -25,6 +25,7 @@ set(NVPTXCodeGen_sources
NVVMReflect.cpp
NVPTXGenericToNVVM.cpp
NVPTXPrologEpilogPass.cpp
NVPTXMCExpr.cpp
)
add_llvm_target(NVPTXCodeGen ${NVPTXCodeGen_sources})

View File

@ -1 +1,274 @@
// Placeholder
//===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Print MCInst instructions to .ptx format.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "InstPrinter/NVPTXInstPrinter.h"
#include "NVPTX.h"
#include "MCTargetDesc/NVPTXBaseInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include <cctype>
using namespace llvm;
#include "NVPTXGenAsmWriter.inc"
NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI,
const MCSubtargetInfo &STI)
: MCInstPrinter(MAI, MII, MRI) {
setAvailableFeatures(STI.getFeatureBits());
}
void NVPTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
// Decode the virtual register
// Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
unsigned RCId = (RegNo >> 28);
switch (RCId) {
default: report_fatal_error("Bad virtual register encoding");
case 0:
OS << "%p";
break;
case 1:
OS << "%rs";
break;
case 2:
OS << "%r";
break;
case 3:
OS << "%rl";
break;
case 4:
OS << "%f";
break;
case 5:
OS << "%fl";
break;
}
unsigned VReg = RegNo & 0x0FFFFFFF;
OS << VReg;
}
void NVPTXInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
StringRef Annot) {
printInstruction(MI, OS);
// Next always print the annotation.
printAnnotation(OS, Annot);
}
void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
unsigned Reg = Op.getReg();
printRegName(O, Reg);
} else if (Op.isImm()) {
O << markup("<imm:") << formatImm(Op.getImm()) << markup(">");
} else {
assert(Op.isExpr() && "Unknown operand kind in printOperand");
O << *Op.getExpr();
}
}
void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O,
const char *Modifier) {
const MCOperand &MO = MI->getOperand(OpNum);
int64_t Imm = MO.getImm();
if (strcmp(Modifier, "ftz") == 0) {
// FTZ flag
if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG)
O << ".ftz";
} else if (strcmp(Modifier, "sat") == 0) {
// SAT flag
if (Imm & NVPTX::PTXCvtMode::SAT_FLAG)
O << ".sat";
} else if (strcmp(Modifier, "base") == 0) {
// Default operand
switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
default:
return;
case NVPTX::PTXCvtMode::NONE:
break;
case NVPTX::PTXCvtMode::RNI:
O << ".rni";
break;
case NVPTX::PTXCvtMode::RZI:
O << ".rzi";
break;
case NVPTX::PTXCvtMode::RMI:
O << ".rmi";
break;
case NVPTX::PTXCvtMode::RPI:
O << ".rpi";
break;
case NVPTX::PTXCvtMode::RN:
O << ".rn";
break;
case NVPTX::PTXCvtMode::RZ:
O << ".rz";
break;
case NVPTX::PTXCvtMode::RM:
O << ".rm";
break;
case NVPTX::PTXCvtMode::RP:
O << ".rp";
break;
}
} else {
llvm_unreachable("Invalid conversion modifier");
}
}
void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O,
const char *Modifier) {
const MCOperand &MO = MI->getOperand(OpNum);
int64_t Imm = MO.getImm();
if (strcmp(Modifier, "ftz") == 0) {
// FTZ flag
if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG)
O << ".ftz";
} else if (strcmp(Modifier, "base") == 0) {
switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
default:
return;
case NVPTX::PTXCmpMode::EQ:
O << ".eq";
break;
case NVPTX::PTXCmpMode::NE:
O << ".ne";
break;
case NVPTX::PTXCmpMode::LT:
O << ".lt";
break;
case NVPTX::PTXCmpMode::LE:
O << ".le";
break;
case NVPTX::PTXCmpMode::GT:
O << ".gt";
break;
case NVPTX::PTXCmpMode::GE:
O << ".ge";
break;
case NVPTX::PTXCmpMode::LO:
O << ".lo";
break;
case NVPTX::PTXCmpMode::LS:
O << ".ls";
break;
case NVPTX::PTXCmpMode::HI:
O << ".hi";
break;
case NVPTX::PTXCmpMode::HS:
O << ".hs";
break;
case NVPTX::PTXCmpMode::EQU:
O << ".equ";
break;
case NVPTX::PTXCmpMode::NEU:
O << ".neu";
break;
case NVPTX::PTXCmpMode::LTU:
O << ".ltu";
break;
case NVPTX::PTXCmpMode::LEU:
O << ".leu";
break;
case NVPTX::PTXCmpMode::GTU:
O << ".gtu";
break;
case NVPTX::PTXCmpMode::GEU:
O << ".geu";
break;
case NVPTX::PTXCmpMode::NUM:
O << ".num";
break;
case NVPTX::PTXCmpMode::NotANumber:
O << ".nan";
break;
}
} else {
llvm_unreachable("Empty Modifier");
}
}
void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum,
raw_ostream &O, const char *Modifier) {
if (Modifier) {
const MCOperand &MO = MI->getOperand(OpNum);
int Imm = (int) MO.getImm();
if (!strcmp(Modifier, "volatile")) {
if (Imm)
O << ".volatile";
} else if (!strcmp(Modifier, "addsp")) {
switch (Imm) {
case NVPTX::PTXLdStInstCode::GLOBAL:
O << ".global";
break;
case NVPTX::PTXLdStInstCode::SHARED:
O << ".shared";
break;
case NVPTX::PTXLdStInstCode::LOCAL:
O << ".local";
break;
case NVPTX::PTXLdStInstCode::PARAM:
O << ".param";
break;
case NVPTX::PTXLdStInstCode::CONSTANT:
O << ".const";
break;
case NVPTX::PTXLdStInstCode::GENERIC:
break;
default:
llvm_unreachable("Wrong Address Space");
}
} else if (!strcmp(Modifier, "sign")) {
if (Imm == NVPTX::PTXLdStInstCode::Signed)
O << "s";
else if (Imm == NVPTX::PTXLdStInstCode::Unsigned)
O << "u";
else
O << "f";
} else if (!strcmp(Modifier, "vec")) {
if (Imm == NVPTX::PTXLdStInstCode::V2)
O << ".v2";
else if (Imm == NVPTX::PTXLdStInstCode::V4)
O << ".v4";
} else
llvm_unreachable("Unknown Modifier");
} else
llvm_unreachable("Empty Modifier");
}
void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
raw_ostream &O, const char *Modifier) {
printOperand(MI, OpNum, O);
if (Modifier && !strcmp(Modifier, "add")) {
O << ", ";
printOperand(MI, OpNum + 1, O);
} else {
if (MI->getOperand(OpNum + 1).isImm() &&
MI->getOperand(OpNum + 1).getImm() == 0)
return; // don't print ',0' or '+0'
O << "+";
printOperand(MI, OpNum + 1, O);
}
}

View File

@ -0,0 +1,52 @@
//= NVPTXInstPrinter.h - Convert NVPTX MCInst to assembly syntax --*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints an NVPTX MCInst to .ptx file syntax.
//
//===----------------------------------------------------------------------===//
#ifndef NVPTX_INST_PRINTER_H
#define NVPTX_INST_PRINTER_H
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
class MCOperand;
class MCSubtargetInfo;
class NVPTXInstPrinter : public MCInstPrinter {
public:
NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI, const MCSubtargetInfo &STI);
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);
// End
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O,
const char *Modifier = 0);
void printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O,
const char *Modifier = 0);
void printLdStCode(const MCInst *MI, int OpNum,
raw_ostream &O, const char *Modifier = 0);
void printMemOperand(const MCInst *MI, int OpNum,
raw_ostream &O, const char *Modifier = 0);
};
}
#endif

View File

@ -13,6 +13,7 @@
#include "NVPTXMCTargetDesc.h"
#include "NVPTXMCAsmInfo.h"
#include "InstPrinter/NVPTXInstPrinter.h"
#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
@ -57,6 +58,17 @@ static MCCodeGenInfo *createNVPTXMCCodeGenInfo(
return X;
}
static MCInstPrinter *createNVPTXMCInstPrinter(const Target &T,
unsigned SyntaxVariant,
const MCAsmInfo &MAI,
const MCInstrInfo &MII,
const MCRegisterInfo &MRI,
const MCSubtargetInfo &STI) {
if (SyntaxVariant == 0)
return new NVPTXInstPrinter(MAI, MII, MRI, STI);
return 0;
}
// Force static initialization.
extern "C" void LLVMInitializeNVPTXTargetMC() {
// Register the MC asm info.
@ -85,4 +97,9 @@ extern "C" void LLVMInitializeNVPTXTargetMC() {
TargetRegistry::RegisterMCSubtargetInfo(TheNVPTXTarget64,
createNVPTXMCSubtargetInfo);
// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(TheNVPTXTarget32,
createNVPTXMCInstPrinter);
TargetRegistry::RegisterMCInstPrinter(TheNVPTXTarget64,
createNVPTXMCInstPrinter);
}

View File

@ -57,6 +57,12 @@ def : Proc<"sm_35", [SM35]>;
def NVPTXInstrInfo : InstrInfo {
}
def NVPTXAsmWriter : AsmWriter {
bit isMCAsmWriter = 1;
string AsmWriterClassName = "InstPrinter";
}
def NVPTX : Target {
let InstructionSet = NVPTXInstrInfo;
let AssemblyWriters = [NVPTXAsmWriter];
}

View File

@ -16,6 +16,7 @@
#include "MCTargetDesc/NVPTXMCAsmInfo.h"
#include "NVPTX.h"
#include "NVPTXInstrInfo.h"
#include "NVPTXMCExpr.h"
#include "NVPTXRegisterInfo.h"
#include "NVPTXTargetMachine.h"
#include "NVPTXUtilities.h"
@ -46,8 +47,6 @@
#include <sstream>
using namespace llvm;
#include "NVPTXGenAsmWriter.inc"
bool RegAllocNilUsed = true;
#define DEPOTNAME "__local_depot"
@ -309,8 +308,106 @@ void NVPTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
raw_svector_ostream OS(Str);
if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA)
emitLineNumberAsDotLoc(*MI);
printInstruction(MI, OS);
OutStreamer.EmitRawText(OS.str());
MCInst Inst;
lowerToMCInst(MI, Inst);
OutStreamer.EmitInstruction(Inst);
}
void NVPTXAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
OutMI.setOpcode(MI->getOpcode());
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
MCOperand MCOp;
if (lowerOperand(MO, MCOp))
OutMI.addOperand(MCOp);
}
}
bool NVPTXAsmPrinter::lowerOperand(const MachineOperand &MO,
MCOperand &MCOp) {
switch (MO.getType()) {
default: llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register:
MCOp = MCOperand::CreateReg(encodeVirtualRegister(MO.getReg()));
break;
case MachineOperand::MO_Immediate:
MCOp = MCOperand::CreateImm(MO.getImm());
break;
case MachineOperand::MO_MachineBasicBlock:
MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
MO.getMBB()->getSymbol(), OutContext));
break;
case MachineOperand::MO_ExternalSymbol:
MCOp = GetSymbolRef(MO, GetExternalSymbolSymbol(MO.getSymbolName()));
break;
case MachineOperand::MO_GlobalAddress:
MCOp = GetSymbolRef(MO, Mang->getSymbol(MO.getGlobal()));
break;
case MachineOperand::MO_FPImmediate: {
const ConstantFP *Cnt = MO.getFPImm();
APFloat Val = Cnt->getValueAPF();
switch (Cnt->getType()->getTypeID()) {
default: report_fatal_error("Unsupported FP type"); break;
case Type::FloatTyID:
MCOp = MCOperand::CreateExpr(
NVPTXFloatMCExpr::CreateConstantFPSingle(Val, OutContext));
break;
case Type::DoubleTyID:
MCOp = MCOperand::CreateExpr(
NVPTXFloatMCExpr::CreateConstantFPDouble(Val, OutContext));
break;
}
break;
}
}
return true;
}
unsigned NVPTXAsmPrinter::encodeVirtualRegister(unsigned Reg) {
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
DenseMap<unsigned, unsigned> &RegMap = VRegMapping[RC];
unsigned RegNum = RegMap[Reg];
// Encode the register class in the upper 4 bits
// Must be kept in sync with NVPTXInstPrinter::printRegName
unsigned Ret = 0;
if (RC == &NVPTX::Int1RegsRegClass) {
Ret = 0;
} else if (RC == &NVPTX::Int16RegsRegClass) {
Ret = (1 << 28);
} else if (RC == &NVPTX::Int32RegsRegClass) {
Ret = (2 << 28);
} else if (RC == &NVPTX::Int64RegsRegClass) {
Ret = (3 << 28);
} else if (RC == &NVPTX::Float32RegsRegClass) {
Ret = (4 << 28);
} else if (RC == &NVPTX::Float64RegsRegClass) {
Ret = (5 << 28);
} else {
report_fatal_error("Bad register class");
}
// Insert the vreg number
Ret |= (RegNum & 0x0FFFFFFF);
return Ret;
}
MCOperand NVPTXAsmPrinter::GetSymbolRef(const MachineOperand &MO,
const MCSymbol *Symbol) {
const MCExpr *Expr;
switch (MO.getTargetFlags()) {
default: {
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
OutContext);
break;
}
}
return MCOperand::CreateExpr(Expr);
}
void NVPTXAsmPrinter::printReturnValStr(const Function *F, raw_ostream &O) {
@ -552,268 +649,6 @@ void NVPTXAsmPrinter::printVecModifiedImmediate(
llvm_unreachable("Unknown Modifier on immediate operand");
}
void NVPTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
raw_ostream &O, const char *Modifier) {
const MachineOperand &MO = MI->getOperand(opNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
if (MO.getReg() == NVPTX::VRDepot)
O << DEPOTNAME << getFunctionNumber();
else
O << getRegisterName(MO.getReg());
} else {
if (!Modifier)
emitVirtualRegister(MO.getReg(), false, O);
else {
if (strcmp(Modifier, "vecfull") == 0)
emitVirtualRegister(MO.getReg(), true, O);
else
llvm_unreachable(
"Don't know how to handle the modifier on virtual register.");
}
}
return;
case MachineOperand::MO_Immediate:
if (!Modifier)
O << MO.getImm();
else if (strstr(Modifier, "vec") == Modifier)
printVecModifiedImmediate(MO, Modifier, O);
else
llvm_unreachable(
"Don't know how to handle modifier on immediate operand");
return;
case MachineOperand::MO_FPImmediate:
printFPConstant(MO.getFPImm(), O);
break;
case MachineOperand::MO_GlobalAddress:
O << *Mang->getSymbol(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol: {
const char *symbname = MO.getSymbolName();
if (strstr(symbname, ".PARAM") == symbname) {
unsigned index;
sscanf(symbname + 6, "%u[];", &index);
printParamName(index, O);
} else if (strstr(symbname, ".HLPPARAM") == symbname) {
unsigned index;
sscanf(symbname + 9, "%u[];", &index);
O << *CurrentFnSym << "_param_" << index << "_offset";
} else
O << symbname;
break;
}
case MachineOperand::MO_MachineBasicBlock:
O << *MO.getMBB()->getSymbol();
return;
default:
llvm_unreachable("Operand type not supported.");
}
}
void NVPTXAsmPrinter::printImplicitDef(const MachineInstr *MI,
raw_ostream &O) const {
#ifndef __OPTIMIZE__
O << "\t// Implicit def :";
//printOperand(MI, 0);
O << "\n";
#endif
}
void NVPTXAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
raw_ostream &O, const char *Modifier) {
printOperand(MI, opNum, O);
if (Modifier && !strcmp(Modifier, "add")) {
O << ", ";
printOperand(MI, opNum + 1, O);
} else {
if (MI->getOperand(opNum + 1).isImm() &&
MI->getOperand(opNum + 1).getImm() == 0)
return; // don't print ',0' or '+0'
O << "+";
printOperand(MI, opNum + 1, O);
}
}
void NVPTXAsmPrinter::printLdStCode(const MachineInstr *MI, int opNum,
raw_ostream &O, const char *Modifier) {
if (Modifier) {
const MachineOperand &MO = MI->getOperand(opNum);
int Imm = (int) MO.getImm();
if (!strcmp(Modifier, "volatile")) {
if (Imm)
O << ".volatile";
} else if (!strcmp(Modifier, "addsp")) {
switch (Imm) {
case NVPTX::PTXLdStInstCode::GLOBAL:
O << ".global";
break;
case NVPTX::PTXLdStInstCode::SHARED:
O << ".shared";
break;
case NVPTX::PTXLdStInstCode::LOCAL:
O << ".local";
break;
case NVPTX::PTXLdStInstCode::PARAM:
O << ".param";
break;
case NVPTX::PTXLdStInstCode::CONSTANT:
O << ".const";
break;
case NVPTX::PTXLdStInstCode::GENERIC:
if (!nvptxSubtarget.hasGenericLdSt())
O << ".global";
break;
default:
llvm_unreachable("Wrong Address Space");
}
} else if (!strcmp(Modifier, "sign")) {
if (Imm == NVPTX::PTXLdStInstCode::Signed)
O << "s";
else if (Imm == NVPTX::PTXLdStInstCode::Unsigned)
O << "u";
else
O << "f";
} else if (!strcmp(Modifier, "vec")) {
if (Imm == NVPTX::PTXLdStInstCode::V2)
O << ".v2";
else if (Imm == NVPTX::PTXLdStInstCode::V4)
O << ".v4";
} else
llvm_unreachable("Unknown Modifier");
} else
llvm_unreachable("Empty Modifier");
}
void NVPTXAsmPrinter::printCvtMode(const MachineInstr *MI, int OpNum,
raw_ostream &O, const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNum);
int64_t Imm = MO.getImm();
if (strcmp(Modifier, "ftz") == 0) {
// FTZ flag
if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG)
O << ".ftz";
} else if (strcmp(Modifier, "sat") == 0) {
// SAT flag
if (Imm & NVPTX::PTXCvtMode::SAT_FLAG)
O << ".sat";
} else if (strcmp(Modifier, "base") == 0) {
// Default operand
switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
default:
return;
case NVPTX::PTXCvtMode::NONE:
break;
case NVPTX::PTXCvtMode::RNI:
O << ".rni";
break;
case NVPTX::PTXCvtMode::RZI:
O << ".rzi";
break;
case NVPTX::PTXCvtMode::RMI:
O << ".rmi";
break;
case NVPTX::PTXCvtMode::RPI:
O << ".rpi";
break;
case NVPTX::PTXCvtMode::RN:
O << ".rn";
break;
case NVPTX::PTXCvtMode::RZ:
O << ".rz";
break;
case NVPTX::PTXCvtMode::RM:
O << ".rm";
break;
case NVPTX::PTXCvtMode::RP:
O << ".rp";
break;
}
} else {
llvm_unreachable("Invalid conversion modifier");
}
}
void NVPTXAsmPrinter::printCmpMode(const MachineInstr *MI, int OpNum,
raw_ostream &O, const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNum);
int64_t Imm = MO.getImm();
if (strcmp(Modifier, "ftz") == 0) {
// FTZ flag
if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG)
O << ".ftz";
} else if (strcmp(Modifier, "base") == 0) {
switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
default:
return;
case NVPTX::PTXCmpMode::EQ:
O << ".eq";
break;
case NVPTX::PTXCmpMode::NE:
O << ".ne";
break;
case NVPTX::PTXCmpMode::LT:
O << ".lt";
break;
case NVPTX::PTXCmpMode::LE:
O << ".le";
break;
case NVPTX::PTXCmpMode::GT:
O << ".gt";
break;
case NVPTX::PTXCmpMode::GE:
O << ".ge";
break;
case NVPTX::PTXCmpMode::LO:
O << ".lo";
break;
case NVPTX::PTXCmpMode::LS:
O << ".ls";
break;
case NVPTX::PTXCmpMode::HI:
O << ".hi";
break;
case NVPTX::PTXCmpMode::HS:
O << ".hs";
break;
case NVPTX::PTXCmpMode::EQU:
O << ".equ";
break;
case NVPTX::PTXCmpMode::NEU:
O << ".neu";
break;
case NVPTX::PTXCmpMode::LTU:
O << ".ltu";
break;
case NVPTX::PTXCmpMode::LEU:
O << ".leu";
break;
case NVPTX::PTXCmpMode::GTU:
O << ".gtu";
break;
case NVPTX::PTXCmpMode::GEU:
O << ".geu";
break;
case NVPTX::PTXCmpMode::NUM:
O << ".num";
break;
case NVPTX::PTXCmpMode::NotANumber:
O << ".nan";
break;
}
} else {
llvm_unreachable("Empty Modifier");
}
}
void NVPTXAsmPrinter::emitDeclaration(const Function *F, raw_ostream &O) {
@ -2100,41 +1935,6 @@ bool NVPTXAsmPrinter::isImageType(const Type *Ty) {
return false;
}
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool NVPTXAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode, raw_ostream &O) {
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0)
return true; // Unknown modifier.
switch (ExtraCode[0]) {
default:
// See if this is a generic print operand
return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
case 'r':
break;
}
}
printOperand(MI, OpNo, O);
return false;
}
bool NVPTXAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant,
const char *ExtraCode, raw_ostream &O) {
if (ExtraCode && ExtraCode[0])
return true; // Unknown modifier
O << '[';
printMemOperand(MI, OpNo, O);
O << ']';
return false;
}
bool NVPTXAsmPrinter::ignoreLoc(const MachineInstr &MI) {
switch (MI.getOpcode()) {

View File

@ -190,18 +190,14 @@ private:
void EmitFunctionBodyEnd();
void EmitInstruction(const MachineInstr *);
void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol);
unsigned encodeVirtualRegister(unsigned Reg);
void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const {}
void printGlobalVariable(const GlobalVariable *GVar);
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
const char *Modifier = 0);
void printLdStCode(const MachineInstr *MI, int opNum, raw_ostream &O,
const char *Modifier = 0);
void printCvtMode(const MachineInstr *MI, int OpNum, raw_ostream &O,
const char *Modifier = 0);
void printCmpMode(const MachineInstr *MI, int OpNum, raw_ostream &O,
const char *Modifier = 0);
void printVecModifiedImmediate(const MachineOperand &MO, const char *Modifier,
raw_ostream &O);
void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
@ -224,12 +220,6 @@ private:
void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
void emitFunctionTempData(const MachineFunction &MF, unsigned &FrameSize);
bool isImageType(const Type *Ty);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode,
raw_ostream &);
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode,
raw_ostream &);
void printReturnValStr(const Function *, raw_ostream &O);
void printReturnValStr(const MachineFunction &MF, raw_ostream &O);

View File

@ -1316,7 +1316,15 @@ SDValue NVPTXTargetLowering::getExtSymb(SelectionDAG &DAG, const char *inname,
SDValue
NVPTXTargetLowering::getParamSymbol(SelectionDAG &DAG, int idx, EVT v) const {
return getExtSymb(DAG, ".PARAM", idx, v);
std::string ParamSym;
raw_string_ostream ParamStr(ParamSym);
ParamStr << DAG.getMachineFunction().getName() << "_param_" << idx;
ParamStr.flush();
std::string *SavedStr =
nvTM->getManagedStrPool()->getManagedString(ParamSym.c_str());
return DAG.getTargetExternalSymbol(SavedStr->c_str(), v);
}
SDValue NVPTXTargetLowering::getParamHelpSymbol(SelectionDAG &DAG, int idx) {

View File

@ -0,0 +1,46 @@
//===-- NVPTXMCExpr.cpp - NVPTX specific MC expression classes ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "nvptx-mcexpr"
#include "NVPTXMCExpr.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
using namespace llvm;
const NVPTXFloatMCExpr*
NVPTXFloatMCExpr::Create(VariantKind Kind, APFloat Flt, MCContext &Ctx) {
return new (Ctx) NVPTXFloatMCExpr(Kind, Flt);
}
void NVPTXFloatMCExpr::PrintImpl(raw_ostream &OS) const {
bool Ignored;
unsigned NumHex;
APFloat APF = getAPFloat();
switch (Kind) {
default: llvm_unreachable("Invalid kind!");
case VK_NVPTX_SINGLE_PREC_FLOAT:
OS << "0f";
NumHex = 8;
APF.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &Ignored);
break;
case VK_NVPTX_DOUBLE_PREC_FLOAT:
OS << "0d";
NumHex = 16;
APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &Ignored);
break;
}
APInt API = APF.bitcastToAPInt();
std::string HexStr(utohexstr(API.getZExtValue()));
if (HexStr.length() < NumHex)
OS << std::string(NumHex - HexStr.length(), '0');
OS << utohexstr(API.getZExtValue());
}

View File

@ -0,0 +1,83 @@
//===-- NVPTXMCExpr.h - NVPTX specific MC expression classes ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Modeled after ARMMCExpr
#ifndef NVPTXMCEXPR_H
#define NVPTXMCEXPR_H
#include "llvm/ADT/APFloat.h"
#include "llvm/MC/MCExpr.h"
namespace llvm {
class NVPTXFloatMCExpr : public MCTargetExpr {
public:
enum VariantKind {
VK_NVPTX_None,
VK_NVPTX_SINGLE_PREC_FLOAT, // FP constant in single-precision
VK_NVPTX_DOUBLE_PREC_FLOAT // FP constant in double-precision
};
private:
const VariantKind Kind;
const APFloat Flt;
explicit NVPTXFloatMCExpr(VariantKind _Kind, APFloat _Flt)
: Kind(_Kind), Flt(_Flt) {}
public:
/// @name Construction
/// @{
static const NVPTXFloatMCExpr *Create(VariantKind Kind, APFloat Flt,
MCContext &Ctx);
static const NVPTXFloatMCExpr *CreateConstantFPSingle(APFloat Flt,
MCContext &Ctx) {
return Create(VK_NVPTX_SINGLE_PREC_FLOAT, Flt, Ctx);
}
static const NVPTXFloatMCExpr *CreateConstantFPDouble(APFloat Flt,
MCContext &Ctx) {
return Create(VK_NVPTX_DOUBLE_PREC_FLOAT, Flt, Ctx);
}
/// @}
/// @name Accessors
/// @{
/// getOpcode - Get the kind of this expression.
VariantKind getKind() const { return Kind; }
/// getSubExpr - Get the child of this expression.
APFloat getAPFloat() const { return Flt; }
/// @}
void PrintImpl(raw_ostream &OS) const;
bool EvaluateAsRelocatableImpl(MCValue &Res,
const MCAsmLayout *Layout) const {
return false;
}
void AddValueSymbols(MCAssembler *) const {};
const MCSection *FindAssociatedSection() const {
return NULL;
}
// There are no TLS NVPTXMCExprs at the moment.
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {}
static bool classof(const MCExpr *E) {
return E->getKind() == MCExpr::Target;
}
};
} // end namespace llvm
#endif

View File

@ -0,0 +1,18 @@
; RUN: llc < %s -march=nvptx -mcpu=sm_20 | FileCheck %s
; Make sure we can properly differentiate between single-precision and
; double-precision FP literals.
; CHECK: myaddf
; CHECK: add.f32 %f{{[0-9]+}}, %f{{[0-9]+}}, 0f3F800000
define float @myaddf(float %a) {
%ret = fadd float %a, 1.0
ret float %ret
}
; CHECK: myaddd
; CHECK: add.f64 %fl{{[0-9]+}}, %fl{{[0-9]+}}, 0d3FF0000000000000
define double @myaddd(double %a) {
%ret = fadd double %a, 1.0
ret double %ret
}