From cc88ce36ed6dd8f87b3045da30d224adc64815cc Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 12 Oct 2016 18:00:51 +0000 Subject: [PATCH] AMDGPU: Add instruction definitions for VGPR indexing VI added a second method of indexing into VGPRs besides using v_movrel* llvm-svn: 284027 --- llvm/lib/Target/AMDGPU/AMDGPU.td | 18 +++++-- llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp | 2 + llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h | 10 ++++ .../AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 5 ++ .../AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp | 27 +++++++++- .../AMDGPU/InstPrinter/AMDGPUInstPrinter.h | 5 +- llvm/lib/Target/AMDGPU/SIDefines.h | 9 ++++ llvm/lib/Target/AMDGPU/SIInstructions.td | 4 ++ llvm/lib/Target/AMDGPU/SOPInstructions.td | 52 ++++++++++++++++++- llvm/lib/Target/AMDGPU/VOP1Instructions.td | 2 +- llvm/test/MC/AMDGPU/sop1.s | 8 ++- llvm/test/MC/AMDGPU/sopc-err.s | 10 ++++ llvm/test/MC/AMDGPU/sopc.s | 16 ++++++ llvm/test/MC/AMDGPU/sopp.s | 16 +++++- 14 files changed, 172 insertions(+), 12 deletions(-) create mode 100644 llvm/test/MC/AMDGPU/sopc-err.s diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td index 14c79d2c8168..e0bde330449e 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPU.td +++ b/llvm/lib/Target/AMDGPU/AMDGPU.td @@ -168,6 +168,18 @@ def Feature16BitInsts : SubtargetFeature<"16-bit-insts", "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) //===------------------------------------------------------------===// @@ -295,20 +307,20 @@ def FeatureNorthernIslands : SubtargetFeatureGeneration<"NORTHERN_ISLANDS", 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 ] >; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp index 586d0478a5d1..aba12635453d 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -107,6 +107,8 @@ AMDGPUSubtarget::AMDGPUSubtarget(const Triple &TT, StringRef GPU, StringRef FS, SGPRInitBug(false), HasSMemRealTime(false), Has16BitInsts(false), + HasMovrel(false), + HasVGPRIndexMode(false), FlatAddressSpace(false), R600ALUInst(false), diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h index c0ebab06f768..1dd650652015 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -99,6 +99,8 @@ protected: bool SGPRInitBug; bool HasSMemRealTime; bool Has16BitInsts; + bool HasMovrel; + bool HasVGPRIndexMode; bool FlatAddressSpace; bool R600ALUInst; bool CaymanISA; @@ -501,6 +503,14 @@ public: return Has16BitInsts; } + bool hasMovrel() const { + return HasMovrel; + } + + bool hasVGPRIndexMode() const { + return HasVGPRIndexMode; + } + bool hasScalarCompareEq64() const { return getGeneration() >= VOLCANIC_ISLANDS; } diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index 6d8a7a5d4f66..957233caa9f8 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -344,6 +344,7 @@ public: bool isSMRDOffset() const; bool isSMRDLiteralOffset() const; bool isDPPCtrl() const; + bool isGPRIdxMode() const; StringRef getExpressionAsToken() const { assert(isExpr()); @@ -2744,6 +2745,10 @@ bool AMDGPUOperand::isDPPCtrl() const { return false; } +bool AMDGPUOperand::isGPRIdxMode() const { + return isImm() && isUInt<4>(getImm()); +} + AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) { SMLoc S = Parser.getTok().getLoc(); diff --git a/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp b/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp index 56a6a0413c8a..cb10ec116713 100644 --- a/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp @@ -34,6 +34,7 @@ void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, } void AMDGPUInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O) { O << formatHex(MI->getOperand(OpNo).getImm() & 0xf); } @@ -510,14 +511,14 @@ void AMDGPUInstPrinter::printRowMask(const MCInst *MI, unsigned OpNo, 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, @@ -598,6 +599,28 @@ void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNo, } } +void AMDGPUInstPrinter::printVGPRIndexMode(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { + unsigned Val = MI->getOperand(OpNo).getImm(); + if (Val == 0) { + O << " 0"; + return; + } + + if (Val & VGPRIndexMode::DST_ENABLE) + O << " dst"; + + if (Val & VGPRIndexMode::SRC0_ENABLE) + O << " src0"; + + if (Val & VGPRIndexMode::SRC1_ENABLE) + O << " src1"; + + if (Val & VGPRIndexMode::SRC2_ENABLE) + O << " src2"; +} + void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O) { diff --git a/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h b/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h index 53b1966dfe07..2c54e4832716 100644 --- a/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h +++ b/llvm/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h @@ -34,7 +34,8 @@ public: 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); @@ -107,6 +108,8 @@ private: const MCSubtargetInfo &STI, raw_ostream &O); void printInterpSlot(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); + void printVGPRIndexMode(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O); void printMemOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); static void printIfSet(const MCInst *MI, unsigned OpNo, raw_ostream &O, diff --git a/llvm/lib/Target/AMDGPU/SIDefines.h b/llvm/lib/Target/AMDGPU/SIDefines.h index 2e4d0ecc8ce5..ad1bec25801d 100644 --- a/llvm/lib/Target/AMDGPU/SIDefines.h +++ b/llvm/lib/Target/AMDGPU/SIDefines.h @@ -110,6 +110,15 @@ namespace SIOutMods { }; } +namespace VGPRIndexMode { + enum { + SRC0_ENABLE = 1 << 0, + SRC1_ENABLE = 1 << 1, + SRC2_ENABLE = 1 << 2, + DST_ENABLE = 1 << 3 + }; +} + namespace AMDGPUAsmVariants { enum { DEFAULT = 0, diff --git a/llvm/lib/Target/AMDGPU/SIInstructions.td b/llvm/lib/Target/AMDGPU/SIInstructions.td index cbff609684bc..38374000a958 100644 --- a/llvm/lib/Target/AMDGPU/SIInstructions.td +++ b/llvm/lib/Target/AMDGPU/SIInstructions.td @@ -20,6 +20,10 @@ def isSI : Predicate<"Subtarget->getGeneration() " 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" diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td index 404ee4260aaa..7056b41c6956 100644 --- a/llvm/lib/Target/AMDGPU/SOPInstructions.td +++ b/llvm/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 = "printVGPRIndexMode"; + let ParserMatchClass = GPRIdxModeMatchClass; + let OperandType = "OPERAND_IMMEDIATE"; +} + //===----------------------------------------------------------------------===// // SOP1 Instructions //===----------------------------------------------------------------------===// @@ -63,6 +75,13 @@ class SOP1_32 pattern=[]> : SOP1_Pseudo < "$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 @@ -198,6 +217,12 @@ def S_ABS_I32 : SOP1_32 <"s_abs_i32">; } // 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 @@ -597,7 +622,8 @@ class SOPCe op> : Enc32 { 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; @@ -670,6 +696,17 @@ def S_CMP_EQ_U64 : SOPC_CMP_64 <0x12, "s_cmp_eq_u64", COND_EQ>; 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 //===----------------------------------------------------------------------===// @@ -809,8 +846,20 @@ def S_DECPERFLEVEL : SOPP <0x00000015, (ins i32imm:$simm16), "s_decperflevel $si 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 { @@ -1071,6 +1120,7 @@ def S_CBRANCH_JOIN_vi : SOP1_Real_vi <0x2e, S_CBRANCH_JOIN>; 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>; diff --git a/llvm/lib/Target/AMDGPU/VOP1Instructions.td b/llvm/lib/Target/AMDGPU/VOP1Instructions.td index f108922b213f..77b39d717270 100644 --- a/llvm/lib/Target/AMDGPU/VOP1Instructions.td +++ b/llvm/lib/Target/AMDGPU/VOP1Instructions.td @@ -229,7 +229,7 @@ def VOP_MOVRELD : VOPProfile<[untyped, i32, untyped, untyped]> { 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 diff --git a/llvm/test/MC/AMDGPU/sop1.s b/llvm/test/MC/AMDGPU/sop1.s index c0985f144c97..f611b022fb4b 100644 --- a/llvm/test/MC/AMDGPU/sop1.s +++ b/llvm/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_abs_i32 s1, s2 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 diff --git a/llvm/test/MC/AMDGPU/sopc-err.s b/llvm/test/MC/AMDGPU/sopc-err.s new file mode 100644 index 000000000000..b6d954271d34 --- /dev/null +++ b/llvm/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 diff --git a/llvm/test/MC/AMDGPU/sopc.s b/llvm/test/MC/AMDGPU/sopc.s index ef4351d06599..dc922b65a6e9 100644 --- a/llvm/test/MC/AMDGPU/sopc.s +++ b/llvm/test/MC/AMDGPU/sopc.s @@ -64,3 +64,19 @@ s_cmp_eq_u64 s[0:1], s[2:3] 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, 0 ; 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, src0 ; 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, src0 src1 ; 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, dst src0 src1 src2 ; encoding: [0x00,0x0f,0x11,0xbf] +// NOSICI: error: instruction not supported on this GPU diff --git a/llvm/test/MC/AMDGPU/sopp.s b/llvm/test/MC/AMDGPU/sopp.s index 59de24533e0e..b073c8dfc635 100644 --- a/llvm/test/MC/AMDGPU/sopp.s +++ b/llvm/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_decperflevel 6 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 0 ; 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 dst src0 src1 src2 ; encoding: [0x0f,0x00,0x9d,0xbf] +// NOSICI: error: instruction not supported on this GPU