f785676f2a
all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC after: 1 month
290 lines
7.6 KiB
C++
290 lines
7.6 KiB
C++
//===-- 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/MCSymbol.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:
|
|
// This is actually a physical register, so defer to the autogenerated
|
|
// register printer
|
|
OS << getRegisterName(RegNo);
|
|
return;
|
|
case 1:
|
|
OS << "%p";
|
|
break;
|
|
case 2:
|
|
OS << "%rs";
|
|
break;
|
|
case 3:
|
|
OS << "%r";
|
|
break;
|
|
case 4:
|
|
OS << "%rl";
|
|
break;
|
|
case 5:
|
|
OS << "%f";
|
|
break;
|
|
case 6:
|
|
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);
|
|
}
|
|
}
|
|
|
|
void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum,
|
|
raw_ostream &O, const char *Modifier) {
|
|
const MCOperand &Op = MI->getOperand(OpNum);
|
|
assert(Op.isExpr() && "Call prototype is not an MCExpr?");
|
|
const MCExpr *Expr = Op.getExpr();
|
|
const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
|
|
O << Sym.getName();
|
|
}
|