mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-05 13:26:55 +00:00
R600/SI: Initial support for assembler and inline assembly
This is currently considered experimental, but most of the more commonly used instructions should work. So far only SI has been extensively tested, CI and VI probably work too, but may be buggy. The current set of tests cases do not give complete coverage, but I think it is sufficient for an experimental assembler. See the documentation in R600Usage for more information. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@234381 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -133,6 +133,20 @@ class SubtargetFeatureLocalMemorySize <int Value> : SubtargetFeature<
|
||||
!cast<string>(Value),
|
||||
"The size of local memory in bytes">;
|
||||
|
||||
def FeatureGCN : SubtargetFeature<"gcn",
|
||||
"IsGCN",
|
||||
"true",
|
||||
"GCN or newer GPU">;
|
||||
|
||||
def FeatureGCN1Encoding : SubtargetFeature<"gcn1-encoding",
|
||||
"GCN1Encoding",
|
||||
"true",
|
||||
"Encoding format for SI and CI">;
|
||||
|
||||
def FeatureGCN3Encoding : SubtargetFeature<"gcn3-encoding",
|
||||
"GCN3Encoding",
|
||||
"true",
|
||||
"Encoding format for VI">;
|
||||
class SubtargetFeatureGeneration <string Value,
|
||||
list<SubtargetFeature> Implies> :
|
||||
SubtargetFeature <Value, "Gen", "AMDGPUSubtarget::"#Value,
|
||||
@@ -158,15 +172,17 @@ def FeatureNorthernIslands : SubtargetFeatureGeneration<"NORTHERN_ISLANDS",
|
||||
|
||||
def FeatureSouthernIslands : SubtargetFeatureGeneration<"SOUTHERN_ISLANDS",
|
||||
[Feature64BitPtr, FeatureFP64, FeatureLocalMemorySize32768,
|
||||
FeatureWavefrontSize64]>;
|
||||
FeatureWavefrontSize64, FeatureGCN, FeatureGCN1Encoding]>;
|
||||
|
||||
def FeatureSeaIslands : SubtargetFeatureGeneration<"SEA_ISLANDS",
|
||||
[Feature64BitPtr, FeatureFP64, FeatureLocalMemorySize65536,
|
||||
FeatureWavefrontSize64, FeatureFlatAddressSpace]>;
|
||||
FeatureWavefrontSize64, FeatureGCN, FeatureFlatAddressSpace,
|
||||
FeatureGCN1Encoding]>;
|
||||
|
||||
def FeatureVolcanicIslands : SubtargetFeatureGeneration<"VOLCANIC_ISLANDS",
|
||||
[Feature64BitPtr, FeatureFP64, FeatureLocalMemorySize65536,
|
||||
FeatureWavefrontSize64, FeatureFlatAddressSpace]>;
|
||||
FeatureWavefrontSize64, FeatureFlatAddressSpace, FeatureGCN,
|
||||
FeatureGCN3Encoding]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -197,8 +213,10 @@ def NullALU : InstrItinClass;
|
||||
|
||||
class PredicateControl {
|
||||
Predicate SubtargetPredicate;
|
||||
list<Predicate> AssemblerPredicates = [];
|
||||
list<Predicate> OtherPredicates = [];
|
||||
list<Predicate> Predicates = !listconcat([SubtargetPredicate],
|
||||
AssemblerPredicates,
|
||||
OtherPredicates);
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
//
|
||||
|
||||
#include "AMDGPUAsmPrinter.h"
|
||||
#include "InstPrinter/AMDGPUInstPrinter.h"
|
||||
#include "AMDGPU.h"
|
||||
#include "AMDKernelCodeT.h"
|
||||
#include "AMDGPUSubtarget.h"
|
||||
@@ -574,3 +575,24 @@ void AMDGPUAsmPrinter::EmitAmdKernelCodeT(const MachineFunction &MF,
|
||||
|
||||
OutStreamer.EmitBytes(StringRef((char*)&header, sizeof(header)));
|
||||
}
|
||||
|
||||
bool AMDGPUAsmPrinter::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;
|
||||
}
|
||||
}
|
||||
|
||||
AMDGPUInstPrinter::printRegOperand(MI->getOperand(OpNo).getReg(), O,
|
||||
*TM.getSubtargetImpl(*MF->getFunction())->getRegisterInfo());
|
||||
return false;
|
||||
}
|
||||
|
@@ -99,6 +99,10 @@ public:
|
||||
|
||||
void EmitEndOfAsmFile(Module &M) override;
|
||||
|
||||
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O);
|
||||
|
||||
protected:
|
||||
std::vector<std::string> DisasmLines, HexLines;
|
||||
size_t DisasmLineMaxLen;
|
||||
|
@@ -71,6 +71,7 @@ AMDGPUSubtarget::AMDGPUSubtarget(StringRef TT, StringRef GPU, StringRef FS,
|
||||
EnablePromoteAlloca(false), EnableIfCvt(true), EnableLoadStoreOpt(false),
|
||||
WavefrontSize(0), CFALUBug(false), LocalMemorySize(0),
|
||||
EnableVGPRSpilling(false), SGPRInitBug(false),
|
||||
IsGCN(false), GCN1Encoding(false), GCN3Encoding(false),
|
||||
FrameLowering(TargetFrameLowering::StackGrowsUp,
|
||||
64 * 16, // Maximum stack alignment (long16)
|
||||
0),
|
||||
|
@@ -71,6 +71,9 @@ private:
|
||||
int LocalMemorySize;
|
||||
bool EnableVGPRSpilling;
|
||||
bool SGPRInitBug;
|
||||
bool IsGCN;
|
||||
bool GCN1Encoding;
|
||||
bool GCN3Encoding;
|
||||
|
||||
AMDGPUFrameLowering FrameLowering;
|
||||
std::unique_ptr<AMDGPUTargetLowering> TLInfo;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -127,7 +127,8 @@ void AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo,
|
||||
O << " tfe";
|
||||
}
|
||||
|
||||
void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) {
|
||||
void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O,
|
||||
const MCRegisterInfo &MRI) {
|
||||
switch (reg) {
|
||||
case AMDGPU::VCC:
|
||||
O << "vcc";
|
||||
@@ -297,7 +298,7 @@ void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
break;
|
||||
|
||||
default:
|
||||
printRegOperand(Op.getReg(), O);
|
||||
printRegOperand(Op.getReg(), O, MRI);
|
||||
break;
|
||||
}
|
||||
} else if (Op.isImm()) {
|
||||
|
@@ -31,6 +31,8 @@ public:
|
||||
|
||||
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot,
|
||||
const MCSubtargetInfo &STI) override;
|
||||
static void printRegOperand(unsigned RegNo, raw_ostream &O,
|
||||
const MCRegisterInfo &MRI);
|
||||
|
||||
private:
|
||||
void printU8ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||
|
@@ -2089,3 +2089,38 @@ SDValue SITargetLowering::CreateLiveInRegister(SelectionDAG &DAG,
|
||||
return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(DAG.getEntryNode()),
|
||||
cast<RegisterSDNode>(VReg)->getReg(), VT);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SI Inline Assembly Support
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass *>
|
||||
SITargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
||||
const std::string &Constraint,
|
||||
MVT VT) const {
|
||||
if (Constraint == "r") {
|
||||
switch(VT.SimpleTy) {
|
||||
default: llvm_unreachable("Unhandled type for 'r' inline asm constraint");
|
||||
case MVT::i64:
|
||||
return std::make_pair(0U, &AMDGPU::SGPR_64RegClass);
|
||||
case MVT::i32:
|
||||
return std::make_pair(0U, &AMDGPU::SGPR_32RegClass);
|
||||
}
|
||||
}
|
||||
|
||||
if (Constraint.size() > 1) {
|
||||
const TargetRegisterClass *RC = nullptr;
|
||||
if (Constraint[1] == 'v') {
|
||||
RC = &AMDGPU::VGPR_32RegClass;
|
||||
} else if (Constraint[1] == 's') {
|
||||
RC = &AMDGPU::SGPR_32RegClass;
|
||||
}
|
||||
|
||||
if (RC) {
|
||||
unsigned Idx = std::atoi(Constraint.substr(2).c_str());
|
||||
if (Idx < RC->getNumRegs())
|
||||
return std::make_pair(RC->getRegister(Idx), RC);
|
||||
}
|
||||
}
|
||||
return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
|
||||
}
|
||||
|
@@ -113,6 +113,10 @@ public:
|
||||
MachineSDNode *buildScratchRSRC(SelectionDAG &DAG,
|
||||
SDLoc DL,
|
||||
SDValue Ptr) const;
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass *> getRegForInlineAsmConstraint(
|
||||
const TargetRegisterInfo *TRI,
|
||||
const std::string &Constraint, MVT VT) const;
|
||||
};
|
||||
|
||||
} // End namespace llvm
|
||||
|
@@ -130,6 +130,11 @@ class VOP3Common <dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
let AddedComplexity = -1000;
|
||||
|
||||
let VOP3 = 1;
|
||||
let VALU = 1;
|
||||
|
||||
let AsmMatchConverter = "cvtVOP3";
|
||||
let isCodeGenOnly = 0;
|
||||
|
||||
int Size = 8;
|
||||
}
|
||||
|
||||
@@ -221,6 +226,7 @@ class SOP1 <dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
let mayLoad = 0;
|
||||
let mayStore = 0;
|
||||
let hasSideEffects = 0;
|
||||
let isCodeGenOnly = 0;
|
||||
let SALU = 1;
|
||||
let SOP1 = 1;
|
||||
}
|
||||
@@ -231,6 +237,7 @@ class SOP2 <dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
let mayLoad = 0;
|
||||
let mayStore = 0;
|
||||
let hasSideEffects = 0;
|
||||
let isCodeGenOnly = 0;
|
||||
let SALU = 1;
|
||||
let SOP2 = 1;
|
||||
|
||||
@@ -246,6 +253,7 @@ class SOPC <bits<7> op, dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
let hasSideEffects = 0;
|
||||
let SALU = 1;
|
||||
let SOPC = 1;
|
||||
let isCodeGenOnly = 0;
|
||||
|
||||
let UseNamedOperandTable = 1;
|
||||
}
|
||||
@@ -563,10 +571,14 @@ let Uses = [EXEC] in {
|
||||
|
||||
class VOP1 <bits<8> op, dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
VOP1Common <outs, ins, asm, pattern>,
|
||||
VOP1e<op>;
|
||||
VOP1e<op> {
|
||||
let isCodeGenOnly = 0;
|
||||
}
|
||||
|
||||
class VOP2 <bits<6> op, dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
VOP2Common <outs, ins, asm, pattern>, VOP2e<op>;
|
||||
VOP2Common <outs, ins, asm, pattern>, VOP2e<op> {
|
||||
let isCodeGenOnly = 0;
|
||||
}
|
||||
|
||||
class VOPC <bits<8> op, dag ins, string asm, list<dag> pattern> :
|
||||
VOPCCommon <ins, asm, pattern>, VOPCe <op>;
|
||||
@@ -599,6 +611,7 @@ class DS <dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
let mayStore = 1;
|
||||
|
||||
let hasSideEffects = 0;
|
||||
let AsmMatchConverter = "cvtDS";
|
||||
let SchedRW = [WriteLDS];
|
||||
}
|
||||
|
||||
@@ -611,6 +624,7 @@ class MUBUF <dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
|
||||
let hasSideEffects = 0;
|
||||
let UseNamedOperandTable = 1;
|
||||
let AsmMatchConverter = "cvtMubuf";
|
||||
let SchedRW = [WriteVMEM];
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,15 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
def isSICI : Predicate<
|
||||
"Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS ||"
|
||||
"Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS"
|
||||
>, AssemblerPredicate<"FeatureGCN1Encoding">;
|
||||
def isCI : Predicate<"Subtarget->getGeneration() "
|
||||
">= AMDGPUSubtarget::SEA_ISLANDS">;
|
||||
def isVI : Predicate <
|
||||
"Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS">,
|
||||
AssemblerPredicate<"FeatureGCN3Encoding">;
|
||||
|
||||
class vop {
|
||||
field bits<9> SI3;
|
||||
@@ -233,14 +242,88 @@ def FRAMEri32 : Operand<iPTR> {
|
||||
let MIOperandInfo = (ops i32:$ptr, i32imm:$index);
|
||||
}
|
||||
|
||||
def SoppBrTarget : AsmOperandClass {
|
||||
let Name = "SoppBrTarget";
|
||||
let ParserMethod = "parseSOppBrTarget";
|
||||
}
|
||||
|
||||
def sopp_brtarget : Operand<OtherVT> {
|
||||
let EncoderMethod = "getSOPPBrEncoding";
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
let ParserMatchClass = SoppBrTarget;
|
||||
}
|
||||
|
||||
include "SIInstrFormats.td"
|
||||
include "VIInstrFormats.td"
|
||||
|
||||
def MubufOffsetMatchClass : AsmOperandClass {
|
||||
let Name = "MubufOffset";
|
||||
let ParserMethod = "parseMubufOptionalOps";
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
|
||||
class DSOffsetBaseMatchClass <string parser> : AsmOperandClass {
|
||||
let Name = "DSOffset"#parser;
|
||||
let ParserMethod = parser;
|
||||
let RenderMethod = "addImmOperands";
|
||||
let PredicateMethod = "isDSOffset";
|
||||
}
|
||||
|
||||
def DSOffsetMatchClass : DSOffsetBaseMatchClass <"parseDSOptionalOps">;
|
||||
def DSOffsetGDSMatchClass : DSOffsetBaseMatchClass <"parseDSOffsetOptional">;
|
||||
|
||||
def DSOffset01MatchClass : AsmOperandClass {
|
||||
let Name = "DSOffset1";
|
||||
let ParserMethod = "parseDSOff01OptionalOps";
|
||||
let RenderMethod = "addImmOperands";
|
||||
let PredicateMethod = "isDSOffset01";
|
||||
}
|
||||
|
||||
class GDSBaseMatchClass <string parser> : AsmOperandClass {
|
||||
let Name = "GDS"#parser;
|
||||
let PredicateMethod = "isImm";
|
||||
let ParserMethod = parser;
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
|
||||
def GDSMatchClass : GDSBaseMatchClass <"parseDSOptionalOps">;
|
||||
def GDS01MatchClass : GDSBaseMatchClass <"parseDSOff01OptionalOps">;
|
||||
|
||||
def GLCMatchClass : AsmOperandClass {
|
||||
let Name = "GLC";
|
||||
let PredicateMethod = "isImm";
|
||||
let ParserMethod = "parseMubufOptionalOps";
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
|
||||
def SLCMatchClass : AsmOperandClass {
|
||||
let Name = "SLC";
|
||||
let PredicateMethod = "isImm";
|
||||
let ParserMethod = "parseMubufOptionalOps";
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
|
||||
def TFEMatchClass : AsmOperandClass {
|
||||
let Name = "TFE";
|
||||
let PredicateMethod = "isImm";
|
||||
let ParserMethod = "parseMubufOptionalOps";
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
|
||||
def OModMatchClass : AsmOperandClass {
|
||||
let Name = "OMod";
|
||||
let PredicateMethod = "isImm";
|
||||
let ParserMethod = "parseVOP3OptionalOps";
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
|
||||
def ClampMatchClass : AsmOperandClass {
|
||||
let Name = "Clamp";
|
||||
let PredicateMethod = "isImm";
|
||||
let ParserMethod = "parseVOP3OptionalOps";
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
|
||||
let OperandType = "OPERAND_IMMEDIATE" in {
|
||||
|
||||
def offen : Operand<i1> {
|
||||
@@ -254,35 +337,52 @@ def addr64 : Operand<i1> {
|
||||
}
|
||||
def mbuf_offset : Operand<i16> {
|
||||
let PrintMethod = "printMBUFOffset";
|
||||
let ParserMatchClass = MubufOffsetMatchClass;
|
||||
}
|
||||
def ds_offset : Operand<i16> {
|
||||
class ds_offset_base <AsmOperandClass mc> : Operand<i16> {
|
||||
let PrintMethod = "printDSOffset";
|
||||
let ParserMatchClass = mc;
|
||||
}
|
||||
def ds_offset : ds_offset_base <DSOffsetMatchClass>;
|
||||
def ds_offset_gds : ds_offset_base <DSOffsetGDSMatchClass>;
|
||||
|
||||
def ds_offset0 : Operand<i8> {
|
||||
let PrintMethod = "printDSOffset0";
|
||||
let ParserMatchClass = DSOffset01MatchClass;
|
||||
}
|
||||
def ds_offset1 : Operand<i8> {
|
||||
let PrintMethod = "printDSOffset1";
|
||||
let ParserMatchClass = DSOffset01MatchClass;
|
||||
}
|
||||
def gds : Operand <i1> {
|
||||
class gds_base <AsmOperandClass mc> : Operand <i1> {
|
||||
let PrintMethod = "printGDS";
|
||||
let ParserMatchClass = mc;
|
||||
}
|
||||
def gds : gds_base <GDSMatchClass>;
|
||||
|
||||
def gds01 : gds_base <GDS01MatchClass>;
|
||||
|
||||
def glc : Operand <i1> {
|
||||
let PrintMethod = "printGLC";
|
||||
let ParserMatchClass = GLCMatchClass;
|
||||
}
|
||||
def slc : Operand <i1> {
|
||||
let PrintMethod = "printSLC";
|
||||
let ParserMatchClass = SLCMatchClass;
|
||||
}
|
||||
def tfe : Operand <i1> {
|
||||
let PrintMethod = "printTFE";
|
||||
let ParserMatchClass = TFEMatchClass;
|
||||
}
|
||||
|
||||
def omod : Operand <i32> {
|
||||
let PrintMethod = "printOModSI";
|
||||
let ParserMatchClass = OModMatchClass;
|
||||
}
|
||||
|
||||
def ClampMod : Operand <i1> {
|
||||
let PrintMethod = "printClampSI";
|
||||
let ParserMatchClass = ClampMatchClass;
|
||||
}
|
||||
|
||||
} // End OperandType = "OPERAND_IMMEDIATE"
|
||||
@@ -392,12 +492,18 @@ class SOP1_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
|
||||
class SOP1_Real_si <sop1 op, string opName, dag outs, dag ins, string asm> :
|
||||
SOP1 <outs, ins, asm, []>,
|
||||
SOP1e <op.SI>,
|
||||
SIMCInstr<opName, SISubtarget.SI>;
|
||||
SIMCInstr<opName, SISubtarget.SI> {
|
||||
let isCodeGenOnly = 0;
|
||||
let AssemblerPredicates = [isSICI];
|
||||
}
|
||||
|
||||
class SOP1_Real_vi <sop1 op, string opName, dag outs, dag ins, string asm> :
|
||||
SOP1 <outs, ins, asm, []>,
|
||||
SOP1e <op.VI>,
|
||||
SIMCInstr<opName, SISubtarget.VI>;
|
||||
SIMCInstr<opName, SISubtarget.VI> {
|
||||
let isCodeGenOnly = 0;
|
||||
let AssemblerPredicates = [isVI];
|
||||
}
|
||||
|
||||
multiclass SOP1_m <sop1 op, string opName, dag outs, dag ins, string asm,
|
||||
list<dag> pattern> {
|
||||
@@ -473,12 +579,16 @@ class SOP2_Pseudo<string opName, dag outs, dag ins, list<dag> pattern> :
|
||||
class SOP2_Real_si<sop2 op, string opName, dag outs, dag ins, string asm> :
|
||||
SOP2<outs, ins, asm, []>,
|
||||
SOP2e<op.SI>,
|
||||
SIMCInstr<opName, SISubtarget.SI>;
|
||||
SIMCInstr<opName, SISubtarget.SI> {
|
||||
let AssemblerPredicates = [isSICI];
|
||||
}
|
||||
|
||||
class SOP2_Real_vi<sop2 op, string opName, dag outs, dag ins, string asm> :
|
||||
SOP2<outs, ins, asm, []>,
|
||||
SOP2e<op.VI>,
|
||||
SIMCInstr<opName, SISubtarget.VI>;
|
||||
SIMCInstr<opName, SISubtarget.VI> {
|
||||
let AssemblerPredicates = [isVI];
|
||||
}
|
||||
|
||||
multiclass SOP2_SELECT_32 <sop2 op, string opName, list<dag> pattern> {
|
||||
def "" : SOP2_Pseudo <opName, (outs SReg_32:$dst),
|
||||
@@ -540,12 +650,18 @@ class SOPK_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
|
||||
class SOPK_Real_si <sopk op, string opName, dag outs, dag ins, string asm> :
|
||||
SOPK <outs, ins, asm, []>,
|
||||
SOPKe <op.SI>,
|
||||
SIMCInstr<opName, SISubtarget.SI>;
|
||||
SIMCInstr<opName, SISubtarget.SI> {
|
||||
let AssemblerPredicates = [isSICI];
|
||||
let isCodeGenOnly = 0;
|
||||
}
|
||||
|
||||
class SOPK_Real_vi <sopk op, string opName, dag outs, dag ins, string asm> :
|
||||
SOPK <outs, ins, asm, []>,
|
||||
SOPKe <op.VI>,
|
||||
SIMCInstr<opName, SISubtarget.VI>;
|
||||
SIMCInstr<opName, SISubtarget.VI> {
|
||||
let AssemblerPredicates = [isVI];
|
||||
let isCodeGenOnly = 0;
|
||||
}
|
||||
|
||||
multiclass SOPK_m <sopk op, string opName, dag outs, dag ins, string opAsm,
|
||||
string asm = opName#opAsm> {
|
||||
@@ -620,13 +736,17 @@ class SMRD_Real_si <bits<5> op, string opName, bit imm, dag outs, dag ins,
|
||||
string asm> :
|
||||
SMRD <outs, ins, asm, []>,
|
||||
SMRDe <op, imm>,
|
||||
SIMCInstr<opName, SISubtarget.SI>;
|
||||
SIMCInstr<opName, SISubtarget.SI> {
|
||||
let AssemblerPredicates = [isSICI];
|
||||
}
|
||||
|
||||
class SMRD_Real_vi <bits<8> op, string opName, bit imm, dag outs, dag ins,
|
||||
string asm> :
|
||||
SMRD <outs, ins, asm, []>,
|
||||
SMEMe_vi <op, imm>,
|
||||
SIMCInstr<opName, SISubtarget.VI>;
|
||||
SIMCInstr<opName, SISubtarget.VI> {
|
||||
let AssemblerPredicates = [isVI];
|
||||
}
|
||||
|
||||
multiclass SMRD_m <bits<5> op, string opName, bit imm, dag outs, dag ins,
|
||||
string asm, list<dag> pattern> {
|
||||
@@ -665,8 +785,14 @@ multiclass SMRD_Helper <bits<5> op, string opName, RegisterClass baseClass,
|
||||
def InputMods : OperandWithDefaultOps <i32, (ops (i32 0))> {
|
||||
let PrintMethod = "printOperandAndMods";
|
||||
}
|
||||
|
||||
def InputModsMatchClass : AsmOperandClass {
|
||||
let Name = "RegWithInputMods";
|
||||
}
|
||||
|
||||
def InputModsNoDefault : Operand <i32> {
|
||||
let PrintMethod = "printOperandAndMods";
|
||||
let ParserMatchClass = InputModsMatchClass;
|
||||
}
|
||||
|
||||
class getNumSrcArgs<ValueType Src1, ValueType Src2> {
|
||||
@@ -874,7 +1000,8 @@ class AtomicNoRet <string noRetOp, bit isRet> {
|
||||
class VOP1_Pseudo <dag outs, dag ins, list<dag> pattern, string opName> :
|
||||
VOP1Common <outs, ins, "", pattern>,
|
||||
VOP <opName>,
|
||||
SIMCInstr <opName#"_e32", SISubtarget.NONE> {
|
||||
SIMCInstr <opName#"_e32", SISubtarget.NONE>,
|
||||
MnemonicAlias<opName#"_e32", opName> {
|
||||
let isPseudo = 1;
|
||||
let isCodeGenOnly = 1;
|
||||
|
||||
@@ -909,18 +1036,23 @@ multiclass VOP1SI_m <vop1 op, dag outs, dag ins, string asm, list<dag> pattern,
|
||||
class VOP2_Pseudo <dag outs, dag ins, list<dag> pattern, string opName> :
|
||||
VOP2Common <outs, ins, "", pattern>,
|
||||
VOP <opName>,
|
||||
SIMCInstr<opName#"_e32", SISubtarget.NONE> {
|
||||
SIMCInstr<opName#"_e32", SISubtarget.NONE>,
|
||||
MnemonicAlias<opName#"_e32", opName> {
|
||||
let isPseudo = 1;
|
||||
let isCodeGenOnly = 1;
|
||||
}
|
||||
|
||||
class VOP2_Real_si <string opName, vop2 op, dag outs, dag ins, string asm> :
|
||||
VOP2 <op.SI, outs, ins, opName#asm, []>,
|
||||
SIMCInstr <opName#"_e32", SISubtarget.SI>;
|
||||
SIMCInstr <opName#"_e32", SISubtarget.SI> {
|
||||
let AssemblerPredicates = [isSICI];
|
||||
}
|
||||
|
||||
class VOP2_Real_vi <string opName, vop2 op, dag outs, dag ins, string asm> :
|
||||
VOP2 <op.VI, outs, ins, opName#asm, []>,
|
||||
SIMCInstr <opName#"_e32", SISubtarget.VI>;
|
||||
SIMCInstr <opName#"_e32", SISubtarget.VI> {
|
||||
let AssemblerPredicates = [isVI];
|
||||
}
|
||||
|
||||
multiclass VOP2SI_m <vop2 op, dag outs, dag ins, string asm, list<dag> pattern,
|
||||
string opName, string revOp> {
|
||||
@@ -966,7 +1098,8 @@ class VOP3DisableModFields <bit HasSrc0Mods,
|
||||
class VOP3_Pseudo <dag outs, dag ins, list<dag> pattern, string opName> :
|
||||
VOP3Common <outs, ins, "", pattern>,
|
||||
VOP <opName>,
|
||||
SIMCInstr<opName#"_e64", SISubtarget.NONE> {
|
||||
SIMCInstr<opName#"_e64", SISubtarget.NONE>,
|
||||
MnemonicAlias<opName#"_e64", opName> {
|
||||
let isPseudo = 1;
|
||||
let isCodeGenOnly = 1;
|
||||
}
|
||||
@@ -974,22 +1107,30 @@ class VOP3_Pseudo <dag outs, dag ins, list<dag> pattern, string opName> :
|
||||
class VOP3_Real_si <bits<9> op, dag outs, dag ins, string asm, string opName> :
|
||||
VOP3Common <outs, ins, asm, []>,
|
||||
VOP3e <op>,
|
||||
SIMCInstr<opName#"_e64", SISubtarget.SI>;
|
||||
SIMCInstr<opName#"_e64", SISubtarget.SI> {
|
||||
let AssemblerPredicates = [isSICI];
|
||||
}
|
||||
|
||||
class VOP3_Real_vi <bits<10> op, dag outs, dag ins, string asm, string opName> :
|
||||
VOP3Common <outs, ins, asm, []>,
|
||||
VOP3e_vi <op>,
|
||||
SIMCInstr <opName#"_e64", SISubtarget.VI>;
|
||||
SIMCInstr <opName#"_e64", SISubtarget.VI> {
|
||||
let AssemblerPredicates = [isVI];
|
||||
}
|
||||
|
||||
class VOP3b_Real_si <bits<9> op, dag outs, dag ins, string asm, string opName> :
|
||||
VOP3Common <outs, ins, asm, []>,
|
||||
VOP3be <op>,
|
||||
SIMCInstr<opName#"_e64", SISubtarget.SI>;
|
||||
SIMCInstr<opName#"_e64", SISubtarget.SI> {
|
||||
let AssemblerPredicates = [isSICI];
|
||||
}
|
||||
|
||||
class VOP3b_Real_vi <bits<10> op, dag outs, dag ins, string asm, string opName> :
|
||||
VOP3Common <outs, ins, asm, []>,
|
||||
VOP3be_vi <op>,
|
||||
SIMCInstr <opName#"_e64", SISubtarget.VI>;
|
||||
SIMCInstr <opName#"_e64", SISubtarget.VI> {
|
||||
let AssemblerPredicates = [isVI];
|
||||
}
|
||||
|
||||
multiclass VOP3_m <vop op, dag outs, dag ins, string asm, list<dag> pattern,
|
||||
string opName, int NumSrcArgs, bit HasMods = 1> {
|
||||
@@ -1131,12 +1272,16 @@ multiclass VOP2SI_3VI_m <vop3 op, string opName, dag outs, dag ins,
|
||||
}
|
||||
|
||||
def _si : VOP2 <op.SI3{5-0}, outs, ins, asm, []>,
|
||||
SIMCInstr <opName, SISubtarget.SI>;
|
||||
SIMCInstr <opName, SISubtarget.SI> {
|
||||
let AssemblerPredicates = [isSICI];
|
||||
}
|
||||
|
||||
def _vi : VOP3Common <outs, ins, asm, []>,
|
||||
VOP3e_vi <op.VI3>,
|
||||
VOP3DisableFields <1, 0, 0>,
|
||||
SIMCInstr <opName, SISubtarget.VI>;
|
||||
SIMCInstr <opName, SISubtarget.VI> {
|
||||
let AssemblerPredicates = [isVI];
|
||||
}
|
||||
}
|
||||
|
||||
multiclass VOP1_Helper <vop1 op, string opName, dag outs,
|
||||
@@ -1289,7 +1434,8 @@ let isCodeGenOnly = 0 in {
|
||||
class VOPC_Pseudo <dag outs, dag ins, list<dag> pattern, string opName> :
|
||||
VOPCCommon <ins, "", pattern>,
|
||||
VOP <opName>,
|
||||
SIMCInstr<opName#"_e32", SISubtarget.NONE> {
|
||||
SIMCInstr<opName#"_e32", SISubtarget.NONE>,
|
||||
MnemonicAlias<opName#"_e32", opName> {
|
||||
let isPseudo = 1;
|
||||
let isCodeGenOnly = 1;
|
||||
}
|
||||
@@ -1540,7 +1686,9 @@ class DS_Pseudo <string opName, dag outs, dag ins, list<dag> pattern> :
|
||||
class DS_Real_si <bits<8> op, string opName, dag outs, dag ins, string asm> :
|
||||
DS <outs, ins, asm, []>,
|
||||
DSe <op>,
|
||||
SIMCInstr <opName, SISubtarget.SI>;
|
||||
SIMCInstr <opName, SISubtarget.SI> {
|
||||
let isCodeGenOnly = 0;
|
||||
}
|
||||
|
||||
class DS_Real_vi <bits<8> op, string opName, dag outs, dag ins, string asm> :
|
||||
DS <outs, ins, asm, []>,
|
||||
@@ -1554,6 +1702,7 @@ class DS_Off16_Real_si <bits<8> op, string opName, dag outs, dag ins, string asm
|
||||
bits<16> offset;
|
||||
let offset0 = offset{7-0};
|
||||
let offset1 = offset{15-8};
|
||||
let isCodeGenOnly = 0;
|
||||
}
|
||||
|
||||
class DS_Off16_Real_vi <bits<8> op, string opName, dag outs, dag ins, string asm> :
|
||||
@@ -1581,12 +1730,12 @@ multiclass DS_1A_RET <bits<8> op, string opName, RegisterClass rc,
|
||||
multiclass DS_1A_Off8_RET <bits<8> op, string opName, RegisterClass rc,
|
||||
dag outs = (outs rc:$vdst),
|
||||
dag ins = (ins VGPR_32:$addr, ds_offset0:$offset0, ds_offset1:$offset1,
|
||||
gds:$gds, M0Reg:$m0),
|
||||
gds01:$gds, M0Reg:$m0),
|
||||
string asm = opName#" $vdst, $addr"#"$offset0"#"$offset1$gds"> {
|
||||
|
||||
def "" : DS_Pseudo <opName, outs, ins, []>;
|
||||
|
||||
let data0 = 0, data1 = 0 in {
|
||||
let data0 = 0, data1 = 0, AsmMatchConverter = "cvtDSOffset01" in {
|
||||
def _si : DS_Real_si <op, opName, outs, ins, asm>;
|
||||
def _vi : DS_Real_vi <op, opName, outs, ins, asm>;
|
||||
}
|
||||
@@ -1610,12 +1759,12 @@ multiclass DS_1A1D_NORET <bits<8> op, string opName, RegisterClass rc,
|
||||
multiclass DS_1A1D_Off8_NORET <bits<8> op, string opName, RegisterClass rc,
|
||||
dag outs = (outs),
|
||||
dag ins = (ins VGPR_32:$addr, rc:$data0, rc:$data1,
|
||||
ds_offset0:$offset0, ds_offset1:$offset1, gds:$gds, M0Reg:$m0),
|
||||
ds_offset0:$offset0, ds_offset1:$offset1, gds01:$gds, M0Reg:$m0),
|
||||
string asm = opName#" $addr, $data0, $data1"#"$offset0"#"$offset1"#"$gds"> {
|
||||
|
||||
def "" : DS_Pseudo <opName, outs, ins, []>;
|
||||
|
||||
let vdst = 0 in {
|
||||
let vdst = 0, AsmMatchConverter = "cvtDSOffset01" in {
|
||||
def _si : DS_Real_si <op, opName, outs, ins, asm>;
|
||||
def _vi : DS_Real_vi <op, opName, outs, ins, asm>;
|
||||
}
|
||||
@@ -1689,7 +1838,7 @@ multiclass DS_0A_RET <bits<8> op, string opName,
|
||||
|
||||
multiclass DS_1A_RET_GDS <bits<8> op, string opName,
|
||||
dag outs = (outs VGPR_32:$vdst),
|
||||
dag ins = (ins VGPR_32:$addr, ds_offset:$offset, M0Reg:$m0),
|
||||
dag ins = (ins VGPR_32:$addr, ds_offset_gds:$offset, M0Reg:$m0),
|
||||
string asm = opName#" $vdst, $addr"#"$offset gds"> {
|
||||
|
||||
def "" : DS_Pseudo <opName, outs, ins, []>;
|
||||
@@ -1798,6 +1947,20 @@ class mubuf <bits<7> si, bits<7> vi = si> {
|
||||
field bits<7> VI = vi;
|
||||
}
|
||||
|
||||
let isCodeGenOnly = 0 in {
|
||||
|
||||
class MUBUF_si <bits<7> op, dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
MUBUF <outs, ins, asm, pattern>, MUBUFe <op> {
|
||||
let lds = 0;
|
||||
}
|
||||
|
||||
} // End let isCodeGenOnly = 0
|
||||
|
||||
class MUBUF_vi <bits<7> op, dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
MUBUF <outs, ins, asm, pattern>, MUBUFe_vi <op> {
|
||||
let lds = 0;
|
||||
}
|
||||
|
||||
class MUBUFAddr64Table <bit is_addr64, string suffix = ""> {
|
||||
bit IsAddr64 = is_addr64;
|
||||
string OpName = NAME # suffix;
|
||||
@@ -1841,7 +2004,7 @@ multiclass MUBUF_m <mubuf op, string opName, dag outs, dag ins, string asm,
|
||||
def "" : MUBUF_Pseudo <opName, outs, ins, pattern>,
|
||||
MUBUFAddr64Table <0>;
|
||||
|
||||
let addr64 = 0 in {
|
||||
let addr64 = 0, isCodeGenOnly = 0 in {
|
||||
def _si : MUBUF_Real_si <op, opName, outs, ins, asm>;
|
||||
}
|
||||
|
||||
@@ -1854,7 +2017,7 @@ multiclass MUBUFAddr64_m <mubuf op, string opName, dag outs,
|
||||
def "" : MUBUF_Pseudo <opName, outs, ins, pattern>,
|
||||
MUBUFAddr64Table <1>;
|
||||
|
||||
let addr64 = 1 in {
|
||||
let addr64 = 1, isCodeGenOnly = 0 in {
|
||||
def _si : MUBUF_Real_si <op, opName, outs, ins, asm>;
|
||||
}
|
||||
|
||||
@@ -1862,11 +2025,6 @@ multiclass MUBUFAddr64_m <mubuf op, string opName, dag outs,
|
||||
// for VI appropriately.
|
||||
}
|
||||
|
||||
class MUBUF_si <bits<7> op, dag outs, dag ins, string asm, list<dag> pattern> :
|
||||
MUBUF <outs, ins, asm, pattern>, MUBUFe <op> {
|
||||
let lds = 0;
|
||||
}
|
||||
|
||||
multiclass MUBUFAtomicOffset_m <mubuf op, string opName, dag outs, dag ins,
|
||||
string asm, list<dag> pattern, bit is_return> {
|
||||
|
||||
|
@@ -27,18 +27,10 @@ def SendMsgImm : Operand<i32> {
|
||||
}
|
||||
|
||||
def isGCN : Predicate<"Subtarget->getGeneration() "
|
||||
">= AMDGPUSubtarget::SOUTHERN_ISLANDS">;
|
||||
">= AMDGPUSubtarget::SOUTHERN_ISLANDS">,
|
||||
AssemblerPredicate<"FeatureGCN">;
|
||||
def isSI : Predicate<"Subtarget->getGeneration() "
|
||||
"== AMDGPUSubtarget::SOUTHERN_ISLANDS">;
|
||||
def isSICI : Predicate<
|
||||
"Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS ||"
|
||||
"Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS"
|
||||
>;
|
||||
def isCI : Predicate<"Subtarget->getGeneration() "
|
||||
">= AMDGPUSubtarget::SEA_ISLANDS">;
|
||||
def isVI : Predicate <
|
||||
"Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS"
|
||||
>;
|
||||
|
||||
def HasFlatAddressSpace : Predicate<"Subtarget.hasFlatAddressSpace()">;
|
||||
|
||||
@@ -242,9 +234,9 @@ defm S_MAX_U32 : SOP2_32 <sop2<0x09>, "s_max_u32",
|
||||
>;
|
||||
} // End Defs = [SCC]
|
||||
|
||||
defm S_CSELECT_B32 : SOP2_SELECT_32 <sop2<0x0a>, "s_cselect_b32", []>;
|
||||
|
||||
let Uses = [SCC] in {
|
||||
defm S_CSELECT_B32 : SOP2_32 <sop2<0x0a>, "s_cselect_b32", []>;
|
||||
defm S_CSELECT_B64 : SOP2_64 <sop2<0x0b>, "s_cselect_b64", []>;
|
||||
} // End Uses = [SCC]
|
||||
|
||||
@@ -1640,7 +1632,6 @@ defm V_LDEXP_F32 : VOP2_VI3_Inst <vop23<0x2b, 0x288>, "v_ldexp_f32",
|
||||
VOP_F32_F32_I32, AMDGPUldexp
|
||||
>;
|
||||
|
||||
|
||||
defm V_CVT_PKACCUM_U8_F32 : VOP2_VI3_Inst <vop23<0x2c, 0x1f0>, "v_cvt_pkaccum_u8_f32",
|
||||
VOP_I32_F32_I32>; // TODO: set "Uses = dst"
|
||||
|
||||
|
@@ -66,7 +66,7 @@ foreach Index = 0-255 in {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// SGPR 32-bit registers
|
||||
def SGPR_32 : RegisterClass<"AMDGPU", [f32, i32], 32,
|
||||
def SGPR_32 : RegisterClass<"AMDGPU", [i32, f32], 32,
|
||||
(add (sequence "SGPR%u", 0, 101))>;
|
||||
|
||||
// SGPR 64-bit registers
|
||||
@@ -113,7 +113,7 @@ def SGPR_512 : RegisterTuples<[sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7,
|
||||
(add (decimate (shl SGPR_32, 15), 4))]>;
|
||||
|
||||
// VGPR 32-bit registers
|
||||
def VGPR_32 : RegisterClass<"AMDGPU", [f32, i32], 32,
|
||||
def VGPR_32 : RegisterClass<"AMDGPU", [i32, f32], 32,
|
||||
(add (sequence "VGPR%u", 0, 255))>;
|
||||
|
||||
// VGPR 64-bit registers
|
||||
@@ -169,6 +169,11 @@ def VGPR_512 : RegisterTuples<[sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7,
|
||||
// Register classes used as source and destination
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class RegImmMatcher<string name> : AsmOperandClass {
|
||||
let Name = name;
|
||||
let RenderMethod = "addRegOrImmOperands";
|
||||
}
|
||||
|
||||
// Special register classes for predicates and the M0 register
|
||||
def SCCReg : RegisterClass<"AMDGPU", [i32, i1], 32, (add SCC)> {
|
||||
let CopyCost = -1; // Theoretically it is possible to read from SCC,
|
||||
@@ -180,7 +185,7 @@ def EXECReg : RegisterClass<"AMDGPU", [i64, i1], 64, (add EXEC)>;
|
||||
def M0Reg : RegisterClass<"AMDGPU", [i32], 32, (add M0)>;
|
||||
|
||||
// Register class for all scalar registers (SGPRs + Special Registers)
|
||||
def SReg_32 : RegisterClass<"AMDGPU", [f32, i32], 32,
|
||||
def SReg_32 : RegisterClass<"AMDGPU", [i32, f32], 32,
|
||||
(add SGPR_32, M0Reg, VCC_LO, VCC_HI, EXEC_LO, EXEC_HI, FLAT_SCR_LO, FLAT_SCR_HI)
|
||||
>;
|
||||
|
||||
@@ -227,15 +232,21 @@ class RegInlineOperand <RegisterClass rc> : RegisterOperand<rc> {
|
||||
// SSrc_* Operands with an SGPR or a 32-bit immediate
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def SSrc_32 : RegImmOperand<SReg_32>;
|
||||
def SSrc_32 : RegImmOperand<SReg_32> {
|
||||
let ParserMatchClass = RegImmMatcher<"SSrc32">;
|
||||
}
|
||||
|
||||
def SSrc_64 : RegImmOperand<SReg_64>;
|
||||
def SSrc_64 : RegImmOperand<SReg_64> {
|
||||
let ParserMatchClass = RegImmMatcher<"SSrc64">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SCSrc_* Operands with an SGPR or a inline constant
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def SCSrc_32 : RegInlineOperand<SReg_32>;
|
||||
def SCSrc_32 : RegInlineOperand<SReg_32> {
|
||||
let ParserMatchClass = RegImmMatcher<"SCSrc32">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// VSrc_* Operands with an SGPR, VGPR or a 32-bit immediate
|
||||
@@ -245,14 +256,30 @@ def VS_32 : RegisterClass<"AMDGPU", [i32, f32], 32, (add VGPR_32, SReg_32)>;
|
||||
|
||||
def VS_64 : RegisterClass<"AMDGPU", [i64, f64], 64, (add VReg_64, SReg_64)>;
|
||||
|
||||
def VSrc_32 : RegImmOperand<VS_32>;
|
||||
def VSrc_32 : RegisterOperand<VS_32> {
|
||||
let OperandNamespace = "AMDGPU";
|
||||
let OperandType = "OPERAND_REG_IMM32";
|
||||
let ParserMatchClass = RegImmMatcher<"VSrc32">;
|
||||
}
|
||||
|
||||
def VSrc_64 : RegImmOperand<VS_64>;
|
||||
def VSrc_64 : RegisterOperand<VS_64> {
|
||||
let OperandNamespace = "AMDGPU";
|
||||
let OperandType = "OPERAND_REG_IMM32";
|
||||
let ParserMatchClass = RegImmMatcher<"VSrc64">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// VCSrc_* Operands with an SGPR, VGPR or an inline constant
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def VCSrc_32 : RegInlineOperand<VS_32>;
|
||||
def VCSrc_32 : RegisterOperand<VS_32> {
|
||||
let OperandNamespace = "AMDGPU";
|
||||
let OperandType = "OPERAND_REG_INLINE_C";
|
||||
let ParserMatchClass = RegImmMatcher<"VCSrc32">;
|
||||
}
|
||||
|
||||
def VCSrc_64 : RegInlineOperand<VS_64>;
|
||||
def VCSrc_64 : RegisterOperand<VS_64> {
|
||||
let OperandNamespace = "AMDGPU";
|
||||
let OperandType = "OPERAND_REG_INLINE_C";
|
||||
let ParserMatchClass = RegImmMatcher<"VCSrc64">;
|
||||
}
|
||||
|
Reference in New Issue
Block a user