Index: lib/Target/AMDGPU/AMDGPU.td =================================================================== --- lib/Target/AMDGPU/AMDGPU.td +++ lib/Target/AMDGPU/AMDGPU.td @@ -167,6 +167,18 @@ "Has i16/f16 instructions" >; +def FeatureMovrel : SubtargetFeature<"movrel", + "HasMovrel", + "true", + "Has v_movrel*_b32 instructions" +>; + +def FeatureVGPRIndexMode : SubtargetFeature<"vgpr-index-mode", + "HasVGPRIndexMode", + "true", + "Has VGPR mode register indexing" +>; + //===------------------------------------------------------------===// // Subtarget Features (options and debugging) //===------------------------------------------------------------===// @@ -294,20 +306,20 @@ def FeatureSouthernIslands : SubtargetFeatureGeneration<"SOUTHERN_ISLANDS", [FeatureFP64, FeatureLocalMemorySize32768, FeatureWavefrontSize64, FeatureGCN, FeatureGCN1Encoding, - FeatureLDSBankCount32] + FeatureLDSBankCount32, FeatureMovrel] >; def FeatureSeaIslands : SubtargetFeatureGeneration<"SEA_ISLANDS", [FeatureFP64, FeatureLocalMemorySize65536, FeatureWavefrontSize64, FeatureGCN, FeatureFlatAddressSpace, - FeatureGCN1Encoding, FeatureCIInsts] + FeatureGCN1Encoding, FeatureCIInsts, FeatureMovrel] >; def FeatureVolcanicIslands : SubtargetFeatureGeneration<"VOLCANIC_ISLANDS", [FeatureFP64, FeatureLocalMemorySize65536, FeatureWavefrontSize64, FeatureFlatAddressSpace, FeatureGCN, FeatureGCN3Encoding, FeatureCIInsts, Feature16BitInsts, - FeatureSMemRealTime + FeatureSMemRealTime, FeatureVGPRIndexMode, FeatureMovrel ] >; Index: lib/Target/AMDGPU/AMDGPUSubtarget.h =================================================================== --- lib/Target/AMDGPU/AMDGPUSubtarget.h +++ lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -98,6 +98,8 @@ bool SGPRInitBug; bool HasSMemRealTime; bool Has16BitInsts; + bool HasMovrel; + bool HasVGPRIndexMode; bool FlatAddressSpace; bool R600ALUInst; bool CaymanISA; @@ -500,6 +502,14 @@ return Has16BitInsts; } + bool hasMovrel() const { + return HasMovrel; + } + + bool hasVGPRIndexMode() const { + return HasVGPRIndexMode; + } + bool hasScalarCompareEq64() const { return getGeneration() >= VOLCANIC_ISLANDS; } Index: lib/Target/AMDGPU/AMDGPUSubtarget.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -107,6 +107,8 @@ SGPRInitBug(false), HasSMemRealTime(false), Has16BitInsts(false), + HasMovrel(false), + HasVGPRIndexMode(false), FlatAddressSpace(false), R600ALUInst(false), Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -343,6 +343,7 @@ bool isSMRDOffset() const; bool isSMRDLiteralOffset() const; bool isDPPCtrl() const; + bool isGPRIdxMode() const; StringRef getExpressionAsToken() const { assert(isExpr()); @@ -2720,6 +2721,10 @@ return false; } +bool AMDGPUOperand::isGPRIdxMode() const { + return isImm() && isUInt<4>(getImm()); +} + AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) { SMLoc S = Parser.getTok().getLoc(); Index: lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h =================================================================== --- lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h +++ lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h @@ -34,7 +34,8 @@ const MCRegisterInfo &MRI); private: - void printU4ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printU4ImmOperand(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O); void printU8ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU16ImmOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); Index: lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp =================================================================== --- lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp +++ lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp @@ -31,6 +31,7 @@ } void AMDGPUInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O) { O << formatHex(MI->getOperand(OpNo).getImm() & 0xf); } @@ -507,14 +508,14 @@ const MCSubtargetInfo &STI, raw_ostream &O) { O << " row_mask:"; - printU4ImmOperand(MI, OpNo, O); + printU4ImmOperand(MI, OpNo, STI, O); } void AMDGPUInstPrinter::printBankMask(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O) { O << " bank_mask:"; - printU4ImmOperand(MI, OpNo, O); + printU4ImmOperand(MI, OpNo, STI, O); } void AMDGPUInstPrinter::printBoundCtrl(const MCInst *MI, unsigned OpNo, Index: lib/Target/AMDGPU/SIInstructions.td =================================================================== --- lib/Target/AMDGPU/SIInstructions.td +++ lib/Target/AMDGPU/SIInstructions.td @@ -20,6 +20,10 @@ def has16BankLDS : Predicate<"Subtarget->getLDSBankCount() == 16">; def has32BankLDS : Predicate<"Subtarget->getLDSBankCount() == 32">; +def HasVGPRIndexMode : Predicate<"Subtarget->hasVGPRIndexMode()">, + AssemblerPredicate<"FeatureVGPRIndexMode">; +def HasMovrel : Predicate<"Subtarget->hasMovrel()">, + AssemblerPredicate<"FeatureMovrel">; include "VOPInstructions.td" include "SOPInstructions.td" Index: lib/Target/AMDGPU/SOPInstructions.td =================================================================== --- lib/Target/AMDGPU/SOPInstructions.td +++ lib/Target/AMDGPU/SOPInstructions.td @@ -7,6 +7,18 @@ // //===----------------------------------------------------------------------===// +def GPRIdxModeMatchClass : AsmOperandClass { + let Name = "GPRIdxMode"; + let PredicateMethod = "isGPRIdxMode"; + let RenderMethod = "addImmOperands"; +} + +def GPRIdxMode : Operand { + let PrintMethod = "printU4ImmOperand"; + let ParserMatchClass = GPRIdxModeMatchClass; + let OperandType = "OPERAND_IMMEDIATE"; +} + //===----------------------------------------------------------------------===// // SOP1 Instructions //===----------------------------------------------------------------------===// @@ -61,6 +73,13 @@ "$sdst, $src0", pattern >; +// 32-bit input, no output. +class SOP1_0_32 pattern = []> : SOP1_Pseudo < + opName, (outs), (ins SSrc_b32:$src0), + "$src0", pattern> { + let has_sdst = 0; +} + class SOP1_64 pattern=[]> : SOP1_Pseudo < opName, (outs SReg_64:$sdst), (ins SSrc_b64:$src0), "$sdst, $src0", pattern @@ -196,6 +215,12 @@ } // End Defs = [SCC] def S_MOV_FED_B32 : SOP1_32 <"s_mov_fed_b32">; +let SubtargetPredicate = HasVGPRIndexMode in { +def S_SET_GPR_IDX_IDX : SOP1_0_32<"s_set_gpr_idx_idx"> { + let Uses = [M0]; + let Defs = [M0]; +} +} //===----------------------------------------------------------------------===// // SOP2 Instructions @@ -595,7 +620,8 @@ let Inst{31-23} = 0x17e; } -class SOPC op, dag outs, dag ins, string asm, list pattern> : +class SOPC op, dag outs, dag ins, string asm, + list pattern = []> : InstSI, SOPCe { let mayLoad = 0; let mayStore = 0; @@ -668,6 +694,17 @@ def S_CMP_LG_U64 : SOPC_CMP_64 <0x13, "s_cmp_lg_u64", COND_NE>; } +let SubtargetPredicate = HasVGPRIndexMode in { +def S_SET_GPR_IDX_ON : SOPC <0x11, + (outs), + (ins SSrc_b32:$src0, GPRIdxMode:$src1), + "s_set_gpr_idx_on $src0, $src1"> { + let Defs = [M0]; // No scc def + let Uses = [M0]; // Other bits of m0 unmodified. + let hasSideEffects = 1; // Sets mode.gpr_idx_en +} +} + //===----------------------------------------------------------------------===// // SOPP Instructions //===----------------------------------------------------------------------===// @@ -806,8 +843,20 @@ def S_TTRACEDATA : SOPP <0x00000016, (ins), "s_ttracedata"> { let simm16 = 0; } + +let SubtargetPredicate = HasVGPRIndexMode in { +def S_SET_GPR_IDX_OFF : SOPP<0x1c, (ins), "s_set_gpr_idx_off"> { + let simm16 = 0; +} +} } // End hasSideEffects +let SubtargetPredicate = HasVGPRIndexMode in { +def S_SET_GPR_IDX_MODE : SOPP<0x1d, (ins GPRIdxMode:$simm16), + "s_set_gpr_idx_mode $simm16"> { + let Defs = [M0]; +} +} let Predicates = [isGCN] in { @@ -1068,6 +1117,7 @@ def S_MOV_REGRD_B32_vi : SOP1_Real_vi <0x2f, S_MOV_REGRD_B32>; def S_ABS_I32_vi : SOP1_Real_vi <0x30, S_ABS_I32>; def S_MOV_FED_B32_vi : SOP1_Real_vi <0x31, S_MOV_FED_B32>; +def S_SET_GPR_IDX_IDX_vi : SOP1_Real_vi <0x32, S_SET_GPR_IDX_IDX>; def S_ADD_U32_vi : SOP2_Real_vi <0x00, S_ADD_U32>; def S_ADD_I32_vi : SOP2_Real_vi <0x02, S_ADD_I32>; Index: lib/Target/AMDGPU/VOP1Instructions.td =================================================================== --- lib/Target/AMDGPU/VOP1Instructions.td +++ lib/Target/AMDGPU/VOP1Instructions.td @@ -229,7 +229,7 @@ let EmitDst = 1; // force vdst emission } -let Uses = [M0, EXEC] in { +let SubtargetPredicate = HasMovrel, Uses = [M0, EXEC] in { // v_movreld_b32 is a special case because the destination output // register is really a source. It isn't actually read (but may be // written), and is only to provide the base register to start Index: test/MC/AMDGPU/sop1.s =================================================================== --- test/MC/AMDGPU/sop1.s +++ test/MC/AMDGPU/sop1.s @@ -1,5 +1,5 @@ -// RUN: llvm-mc -arch=amdgcn -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=SICI %s -// RUN: llvm-mc -arch=amdgcn -mcpu=SI -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=SICI %s +// RUN: not llvm-mc -arch=amdgcn -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=SICI %s +// RUN: not llvm-mc -arch=amdgcn -show-encoding %s 2>&1 | FileCheck --check-prefix=NOSICI %s // RUN: not llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=VI %s // RUN: not llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s 2>&1 | FileCheck --check-prefix=NOVI %s @@ -242,3 +242,7 @@ s_mov_fed_b32 s1, s2 // SICI: s_mov_fed_b32 s1, s2 ; encoding: [0x02,0x35,0x81,0xbe] + +s_set_gpr_idx_idx s0 +// VI: s_set_gpr_idx_idx s0 ; encoding: [0x00,0x32,0x80,0xbe] +// NOSICI: error: instruction not supported on this GPU Index: test/MC/AMDGPU/sopc-err.s =================================================================== --- /dev/null +++ test/MC/AMDGPU/sopc-err.s @@ -0,0 +1,10 @@ +// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga %s 2>&1 | FileCheck -check-prefix=GCN -check-prefix=VI %s + +s_set_gpr_idx_on s0, s1 +// GCN: error: invalid operand for instruction + +s_set_gpr_idx_on s0, 16 +// GCN: error: invalid operand for instruction + +s_set_gpr_idx_on s0, -1 +// GCN: error: invalid operand for instruction Index: test/MC/AMDGPU/sopc.s =================================================================== --- test/MC/AMDGPU/sopc.s +++ test/MC/AMDGPU/sopc.s @@ -64,3 +64,19 @@ s_cmp_lg_u64 s[0:1], s[2:3] // VI: s_cmp_lg_u64 s[0:1], s[2:3] ; encoding: [0x00,0x02,0x13,0xbf] // NOSICI: error: instruction not supported on this GPU + +s_set_gpr_idx_on s0, 0 +// VI: s_set_gpr_idx_on s0, 0x0 ; encoding: [0x00,0x00,0x11,0xbf] +// NOSICI: error: instruction not supported on this GPU + +s_set_gpr_idx_on s0, 1 +// VI: s_set_gpr_idx_on s0, 0x1 ; encoding: [0x00,0x01,0x11,0xbf] +// NOSICI: error: instruction not supported on this GPU + +s_set_gpr_idx_on s0, 3 +// VI: s_set_gpr_idx_on s0, 0x3 ; encoding: [0x00,0x03,0x11,0xbf] +// NOSICI: error: instruction not supported on this GPU + +s_set_gpr_idx_on s0, 15 +// VI: s_set_gpr_idx_on s0, 0xf ; encoding: [0x00,0x0f,0x11,0xbf] +// NOSICI: error: instruction not supported on this GPU Index: test/MC/AMDGPU/sopp.s =================================================================== --- test/MC/AMDGPU/sopp.s +++ test/MC/AMDGPU/sopp.s @@ -1,5 +1,5 @@ -// RUN: llvm-mc -arch=amdgcn -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=SICI %s -// RUN: llvm-mc -arch=amdgcn -mcpu=SI -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=SICI %s +// RUN: not llvm-mc -arch=amdgcn -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=SICI %s +// RUN: not llvm-mc -arch=amdgcn -show-encoding %s 2>&1 | FileCheck %s --check-prefix=NOSICI // RUN: llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s | FileCheck --check-prefix=GCN --check-prefix=VI %s //===----------------------------------------------------------------------===// @@ -176,3 +176,15 @@ s_ttracedata // GCN: s_ttracedata ; encoding: [0x00,0x00,0x96,0xbf] + +s_set_gpr_idx_off +// VI: s_set_gpr_idx_off ; encoding: [0x00,0x00,0x9c,0xbf] +// NOSICI: error: instruction not supported on this GPU + +s_set_gpr_idx_mode 0 +// VI: s_set_gpr_idx_mode 0x0 ; encoding: [0x00,0x00,0x9d,0xbf] +// NOSICI: error: instruction not supported on this GPU + +s_set_gpr_idx_mode 15 +// VI: s_set_gpr_idx_mode 0xf ; encoding: [0x0f,0x00,0x9d,0xbf] +// NOSICI: error: instruction not supported on this GPU