Skip to content

Commit

Permalink
[AMDGPU][MC][GFX9] Enable inline constants for SDWA operands
Browse files Browse the repository at this point in the history
See bug 35771: https://bugs.llvm.org/show_bug.cgi?id=35771

Differential Revision: https://reviews.llvm.org/D42058

Reviewers: vpykhtin, artem.tamazov, arsenm
llvm-svn: 322655
  • Loading branch information
dpreobra committed Jan 17, 2018
1 parent 243ea5b commit 6b65f7c
Show file tree
Hide file tree
Showing 7 changed files with 473 additions and 85 deletions.
28 changes: 24 additions & 4 deletions llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Expand Up @@ -267,7 +267,11 @@ class AMDGPUOperand : public MCParsedAsmOperand {
return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
}

bool isSDWARegKind() const;
bool isSDWAOperand(MVT type) const;
bool isSDWAFP16Operand() const;
bool isSDWAFP32Operand() const;
bool isSDWAInt16Operand() const;
bool isSDWAInt32Operand() const;

bool isImmTy(ImmTy ImmT) const {
return isImm() && Imm.Type == ImmT;
Expand Down Expand Up @@ -1285,15 +1289,31 @@ bool AMDGPUOperand::isRegClass(unsigned RCID) const {
return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
}

bool AMDGPUOperand::isSDWARegKind() const {
bool AMDGPUOperand::isSDWAOperand(MVT type) const {
if (AsmParser->isVI())
return isVReg();
else if (AsmParser->isGFX9())
return isRegKind();
return isRegKind() || isInlinableImm(type);
else
return false;
}

bool AMDGPUOperand::isSDWAFP16Operand() const {
return isSDWAOperand(MVT::f16);
}

bool AMDGPUOperand::isSDWAFP32Operand() const {
return isSDWAOperand(MVT::f32);
}

bool AMDGPUOperand::isSDWAInt16Operand() const {
return isSDWAOperand(MVT::i16);
}

bool AMDGPUOperand::isSDWAInt32Operand() const {
return isSDWAOperand(MVT::i32);
}

uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
{
assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
Expand Down Expand Up @@ -4799,7 +4819,7 @@ void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
}
}
if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
Op.addRegWithInputModsOperands(Inst, 2);
Op.addRegOrImmWithInputModsOperands(Inst, 2);
} else if (Op.isImm()) {
// Handle optional arguments
OptionalIdx[Op.getImmTy()] = I;
Expand Down
13 changes: 11 additions & 2 deletions llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
Expand Up @@ -732,8 +732,9 @@ MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
}

MCOperand AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width,
unsigned Val) const {
const unsigned Val) const {
using namespace AMDGPU::SDWA;
using namespace AMDGPU::EncValues;

if (STI.getFeatureBits()[AMDGPU::FeatureGFX9]) {
// XXX: static_cast<int> is needed to avoid stupid warning:
Expand All @@ -754,7 +755,15 @@ MCOperand AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width,
Val - SDWA9EncValues::SRC_TTMP_MIN);
}

return decodeSpecialReg32(Val - SDWA9EncValues::SRC_SGPR_MIN);
const unsigned SVal = Val - SDWA9EncValues::SRC_SGPR_MIN;

if (INLINE_INTEGER_C_MIN <= SVal && SVal <= INLINE_INTEGER_C_MAX)
return decodeIntImmed(SVal);

if (INLINE_FLOATING_C_MIN <= SVal && SVal <= INLINE_FLOATING_C_MAX)
return decodeFPImmed(Width, SVal);

return decodeSpecialReg32(SVal);
} else if (STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands]) {
return createRegOperand(getVgprClassId(Width), Val);
}
Expand Down
23 changes: 17 additions & 6 deletions llvm/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp
Expand Up @@ -335,13 +335,24 @@ SIMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,

const MCOperand &MO = MI.getOperand(OpNo);

unsigned Reg = MO.getReg();
RegEnc |= MRI.getEncodingValue(Reg);
RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
if (AMDGPU::isSGPR(AMDGPU::mc2PseudoReg(Reg), &MRI)) {
RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
if (MO.isReg()) {
unsigned Reg = MO.getReg();
RegEnc |= MRI.getEncodingValue(Reg);
RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
if (AMDGPU::isSGPR(AMDGPU::mc2PseudoReg(Reg), &MRI)) {
RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
}
return RegEnc;
} else {
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
uint32_t Enc = getLitEncoding(MO, Desc.OpInfo[OpNo], STI);
if (Enc != ~0U && Enc != 255) {
return Enc | SDWA9EncValues::SRC_SGPR_MASK;
}
}
return RegEnc;

llvm_unreachable("Unsupported operand kind");
return 0;
}

unsigned
Expand Down
1 change: 0 additions & 1 deletion llvm/lib/Target/AMDGPU/SIDefines.h
Expand Up @@ -137,7 +137,6 @@ namespace AMDGPU {
OPERAND_INPUT_MODS,

// Operand for SDWA instructions
OPERAND_SDWA_SRC,
OPERAND_SDWA_VOPC_DST,

/// Operand with 32-bit immediate that uses the constant bus.
Expand Down
124 changes: 72 additions & 52 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.td
Expand Up @@ -168,6 +168,36 @@ def SIpc_add_rel_offset : SDNode<"AMDGPUISD::PC_ADD_REL_OFFSET",
SDTypeProfile<1, 2, [SDTCisVT<0, iPTR>, SDTCisSameAs<0,1>, SDTCisSameAs<0,2>]>
>;

//===----------------------------------------------------------------------===//
// ValueType helpers
//===----------------------------------------------------------------------===//

// Returns 1 if the source arguments have modifiers, 0 if they do not.
// XXX - do f16 instructions?
class isFloatType<ValueType SrcVT> {
bit ret =
!if(!eq(SrcVT.Value, f16.Value), 1,
!if(!eq(SrcVT.Value, f32.Value), 1,
!if(!eq(SrcVT.Value, f64.Value), 1,
!if(!eq(SrcVT.Value, v2f16.Value), 1,
0))));
}

class isIntType<ValueType SrcVT> {
bit ret =
!if(!eq(SrcVT.Value, i16.Value), 1,
!if(!eq(SrcVT.Value, i32.Value), 1,
!if(!eq(SrcVT.Value, i64.Value), 1,
0)));
}

class isPackedType<ValueType SrcVT> {
bit ret =
!if(!eq(SrcVT.Value, v2i16.Value), 1,
!if(!eq(SrcVT.Value, v2f16.Value), 1, 0)
);
}

//===----------------------------------------------------------------------===//
// PatFrags for global memory operations
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -566,19 +596,18 @@ def ExpSrc3 : RegisterOperand<VGPR_32> {
let ParserMatchClass = VReg32OrOffClass;
}

class SDWASrc : RegisterOperand<VS_32> {
class SDWASrc<ValueType vt> : RegisterOperand<VS_32> {
let OperandNamespace = "AMDGPU";
let OperandType = "OPERAND_SDWA_SRC";
string Type = !if(isFloatType<vt>.ret, "FP", "INT");
let OperandType = "OPERAND_REG_INLINE_C_"#Type#vt.Size;
let DecoderMethod = "decodeSDWASrc"#vt.Size;
let EncoderMethod = "getSDWASrcEncoding";
}

def SDWASrc32 : SDWASrc {
let DecoderMethod = "decodeSDWASrc32";
}

def SDWASrc16 : SDWASrc {
let DecoderMethod = "decodeSDWASrc16";
}
def SDWASrc_i32 : SDWASrc<i32>;
def SDWASrc_i16 : SDWASrc<i16>;
def SDWASrc_f32 : SDWASrc<f32>;
def SDWASrc_f16 : SDWASrc<f16>;

def SDWAVopcDst : VOPDstOperand<SReg_64> {
let OperandNamespace = "AMDGPU";
Expand Down Expand Up @@ -761,16 +790,23 @@ class OpSelModsMatchClass : AsmOperandClass {
def IntOpSelModsMatchClass : OpSelModsMatchClass;
def IntOpSelMods : InputMods<IntOpSelModsMatchClass>;

def FPRegSDWAInputModsMatchClass : AsmOperandClass {
let Name = "SDWARegWithFPInputMods";
let ParserMethod = "parseRegWithFPInputMods";
let PredicateMethod = "isSDWARegKind";
class FPSDWAInputModsMatchClass <int opSize> : AsmOperandClass {
let Name = "SDWAWithFP"#opSize#"InputMods";
let ParserMethod = "parseRegOrImmWithFPInputMods";
let PredicateMethod = "isSDWAFP"#opSize#"Operand";
}

def FPRegSDWAInputMods : InputMods <FPRegSDWAInputModsMatchClass> {
def FP16SDWAInputModsMatchClass : FPSDWAInputModsMatchClass<16>;
def FP32SDWAInputModsMatchClass : FPSDWAInputModsMatchClass<32>;

class FPSDWAInputMods <FPSDWAInputModsMatchClass matchClass> :
InputMods <matchClass> {
let PrintMethod = "printOperandAndFPInputMods";
}

def FP16SDWAInputMods : FPSDWAInputMods<FP16SDWAInputModsMatchClass>;
def FP32SDWAInputMods : FPSDWAInputMods<FP32SDWAInputModsMatchClass>;

def FPVRegInputModsMatchClass : AsmOperandClass {
let Name = "VRegWithFPInputMods";
let ParserMethod = "parseRegWithFPInputMods";
Expand All @@ -781,17 +817,23 @@ def FPVRegInputMods : InputMods <FPVRegInputModsMatchClass> {
let PrintMethod = "printOperandAndFPInputMods";
}


def IntRegSDWAInputModsMatchClass : AsmOperandClass {
let Name = "SDWARegWithIntInputMods";
let ParserMethod = "parseRegWithIntInputMods";
let PredicateMethod = "isSDWARegKind";
class IntSDWAInputModsMatchClass <int opSize> : AsmOperandClass {
let Name = "SDWAWithInt"#opSize#"InputMods";
let ParserMethod = "parseRegOrImmWithIntInputMods";
let PredicateMethod = "isSDWAInt"#opSize#"Operand";
}

def IntRegSDWAInputMods : InputMods <IntRegSDWAInputModsMatchClass> {
def Int16SDWAInputModsMatchClass : IntSDWAInputModsMatchClass<16>;
def Int32SDWAInputModsMatchClass : IntSDWAInputModsMatchClass<32>;

class IntSDWAInputMods <IntSDWAInputModsMatchClass matchClass> :
InputMods <matchClass> {
let PrintMethod = "printOperandAndIntInputMods";
}

def Int16SDWAInputMods : IntSDWAInputMods<Int16SDWAInputModsMatchClass>;
def Int32SDWAInputMods : IntSDWAInputMods<Int32SDWAInputModsMatchClass>;

def IntVRegInputModsMatchClass : AsmOperandClass {
let Name = "VRegWithIntInputMods";
let ParserMethod = "parseRegWithIntInputMods";
Expand Down Expand Up @@ -1037,7 +1079,12 @@ class getVregSrcForVT<ValueType VT> {
}

class getSDWASrcForVT <ValueType VT> {
RegisterOperand ret = !if(!eq(VT.Size, 16), SDWASrc16, SDWASrc32);
bit isFP = !if(!eq(VT.Value, f16.Value), 1,
!if(!eq(VT.Value, f32.Value), 1,
0));
RegisterOperand retFlt = !if(!eq(VT.Size, 16), SDWASrc_f16, SDWASrc_f32);
RegisterOperand retInt = !if(!eq(VT.Size, 16), SDWASrc_i16, SDWASrc_i32);
RegisterOperand ret = !if(isFP, retFlt, retInt);
}

// Returns the register class to use for sources of VOP3 instructions for the
Expand Down Expand Up @@ -1078,32 +1125,6 @@ class getVOP3SrcForVT<ValueType VT> {
);
}

// Returns 1 if the source arguments have modifiers, 0 if they do not.
// XXX - do f16 instructions?
class isFloatType<ValueType SrcVT> {
bit ret =
!if(!eq(SrcVT.Value, f16.Value), 1,
!if(!eq(SrcVT.Value, f32.Value), 1,
!if(!eq(SrcVT.Value, f64.Value), 1,
!if(!eq(SrcVT.Value, v2f16.Value), 1,
0))));
}

class isIntType<ValueType SrcVT> {
bit ret =
!if(!eq(SrcVT.Value, i16.Value), 1,
!if(!eq(SrcVT.Value, i32.Value), 1,
!if(!eq(SrcVT.Value, i64.Value), 1,
0)));
}

class isPackedType<ValueType SrcVT> {
bit ret =
!if(!eq(SrcVT.Value, v2i16.Value), 1,
!if(!eq(SrcVT.Value, v2f16.Value), 1, 0)
);
}

// Float or packed int
class isModifierType<ValueType SrcVT> {
bit ret =
Expand Down Expand Up @@ -1148,11 +1169,10 @@ class getSrcModExt <ValueType VT> {

// Return type of input modifiers operand specified input operand for SDWA
class getSrcModSDWA <ValueType VT> {
bit isFP = !if(!eq(VT.Value, f16.Value), 1,
!if(!eq(VT.Value, f32.Value), 1,
!if(!eq(VT.Value, f64.Value), 1,
0)));
Operand ret = !if(isFP, FPRegSDWAInputMods, IntRegSDWAInputMods);
Operand ret = !if(!eq(VT.Value, f16.Value), FP16SDWAInputMods,
!if(!eq(VT.Value, f32.Value), FP32SDWAInputMods,
!if(!eq(VT.Value, i16.Value), Int16SDWAInputMods,
Int32SDWAInputMods)));
}

// Returns the input arguments for VOP[12C] instructions for the given SrcVT.
Expand Down

0 comments on commit 6b65f7c

Please sign in to comment.