mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-09 01:38:03 +00:00
[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:
parent
8775a51d94
commit
82767327c5
@ -25,6 +25,7 @@ set(NVPTXCodeGen_sources
|
||||
NVVMReflect.cpp
|
||||
NVPTXGenericToNVVM.cpp
|
||||
NVPTXPrologEpilogPass.cpp
|
||||
NVPTXMCExpr.cpp
|
||||
)
|
||||
|
||||
add_llvm_target(NVPTXCodeGen ${NVPTXCodeGen_sources})
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
52
lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h
Normal file
52
lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
46
lib/Target/NVPTX/NVPTXMCExpr.cpp
Normal file
46
lib/Target/NVPTX/NVPTXMCExpr.cpp
Normal 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());
|
||||
}
|
83
lib/Target/NVPTX/NVPTXMCExpr.h
Normal file
83
lib/Target/NVPTX/NVPTXMCExpr.h
Normal 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
|
18
test/CodeGen/NVPTX/fp-literals.ll
Normal file
18
test/CodeGen/NVPTX/fp-literals.ll
Normal 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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user