diff --git a/llvm/test/TableGen/Common/reg-with-subregs-common.td b/llvm/test/TableGen/Common/reg-with-subregs-common.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/Common/reg-with-subregs-common.td @@ -0,0 +1,128 @@ +include "llvm/Target/Target.td" + +def TestTargetInstrInfo : InstrInfo; + +def TestTarget : Target { + let InstructionSet = TestTargetInstrInfo; +} + +class Indexes { + list all = [0, 1, 2, 3, 4, 5, 6 , 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31]; + list slice = + !foldl([], all, acc, cur, + !listconcat(acc, !if(!lt(cur, N), [cur], []))); +} + +foreach Index = 0-31 in { + def sub#Index : SubRegIndex<32, !shl(Index, 5)>; +} + +foreach Size = {2,4,8,16} in { + foreach Index = Indexes.slice in { + def !foldl("", Indexes.slice, acc, cur, + !strconcat(acc#!if(!eq(acc,""),"","_"), "sub"#!add(cur, Index))) : + SubRegIndex { + let CoveringSubRegIndices = + !foldl([], Indexes.slice, acc, cur, + !listconcat(acc, [!cast(sub#!add(cur, Index))])); + } + } +} + +foreach Index = 0-255 in { + def R#Index : Register <"r"#Index>; +} + +def GPR32 : RegisterClass<"TestTarget", [i32], 32, + (add (sequence "R%u", 0, 255))>; + +def GPR64 : RegisterTuples<[sub0, sub1], + [(decimate (shl GPR32, 0), 1), + (decimate (shl GPR32, 1), 1) + ]>; + +def GPR128 : RegisterTuples<[sub0, sub1, sub2, sub3], + [ + (decimate (shl GPR32, 0), 1), + (decimate (shl GPR32, 1), 1), + (decimate (shl GPR32, 2), 1), + (decimate (shl GPR32, 3), 1) + ]>; + +def GPR256 : RegisterTuples<[sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7], + [ + (decimate (shl GPR32, 0), 1), + (decimate (shl GPR32, 1), 1), + (decimate (shl GPR32, 2), 1), + (decimate (shl GPR32, 3), 1), + (decimate (shl GPR32, 4), 1), + (decimate (shl GPR32, 5), 1), + (decimate (shl GPR32, 6), 1), + (decimate (shl GPR32, 7), 1) + ]>; + +def GPR512 : RegisterTuples<[sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7, + sub8, sub9, sub10, sub11, sub12, sub13, sub14, sub15], + [ + (decimate (shl GPR32, 0), 1), + (decimate (shl GPR32, 1), 1), + (decimate (shl GPR32, 2), 1), + (decimate (shl GPR32, 3), 1), + (decimate (shl GPR32, 4), 1), + (decimate (shl GPR32, 5), 1), + (decimate (shl GPR32, 6), 1), + (decimate (shl GPR32, 7), 1), + (decimate (shl GPR32, 8), 1), + (decimate (shl GPR32, 9), 1), + (decimate (shl GPR32, 10), 1), + (decimate (shl GPR32, 11), 1), + (decimate (shl GPR32, 12), 1), + (decimate (shl GPR32, 13), 1), + (decimate (shl GPR32, 14), 1), + (decimate (shl GPR32, 15), 1) + ]>; + +def GPR1024 : RegisterTuples<[sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7, + sub8, sub9, sub10, sub11, sub12, sub13, sub14, sub15, + sub16, sub17, sub18, sub19, sub20, sub21, sub22, sub23, + sub24, sub25, sub26, sub27, sub28, sub29, sub30, sub31], + [ + (decimate (shl GPR32, 0), 1), + (decimate (shl GPR32, 1), 1), + (decimate (shl GPR32, 2), 1), + (decimate (shl GPR32, 3), 1), + (decimate (shl GPR32, 4), 1), + (decimate (shl GPR32, 5), 1), + (decimate (shl GPR32, 6), 1), + (decimate (shl GPR32, 7), 1), + (decimate (shl GPR32, 8), 1), + (decimate (shl GPR32, 9), 1), + (decimate (shl GPR32, 10), 1), + (decimate (shl GPR32, 11), 1), + (decimate (shl GPR32, 12), 1), + (decimate (shl GPR32, 13), 1), + (decimate (shl GPR32, 14), 1), + (decimate (shl GPR32, 15), 1), + (decimate (shl GPR32, 16), 1), + (decimate (shl GPR32, 17), 1), + (decimate (shl GPR32, 18), 1), + (decimate (shl GPR32, 19), 1), + (decimate (shl GPR32, 20), 1), + (decimate (shl GPR32, 21), 1), + (decimate (shl GPR32, 22), 1), + (decimate (shl GPR32, 23), 1), + (decimate (shl GPR32, 24), 1), + (decimate (shl GPR32, 25), 1), + (decimate (shl GPR32, 26), 1), + (decimate (shl GPR32, 27), 1), + (decimate (shl GPR32, 28), 1), + (decimate (shl GPR32, 29), 1), + (decimate (shl GPR32, 30), 1), + (decimate (shl GPR32, 31), 1) + ]>; + +def GPR_64 : RegisterClass<"", [v2i32], 64, (add GPR64)>; +def GPR_1024 : RegisterClass<"", [v32i32], 1024, (add GPR1024)>; diff --git a/llvm/test/TableGen/dag-isel-subregs.td b/llvm/test/TableGen/dag-isel-subregs.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/dag-isel-subregs.td @@ -0,0 +1,14 @@ +// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include -I %p/Common %s | FileCheck %s + +include "reg-with-subregs-common.td" + +// CHECK-LABEL: OPC_CheckOpcode, TARGET_VAL(ISD::EXTRACT_SUBVECTOR), +// CHECK: OPC_CheckChild1Integer, 0, +// CHECK: OPC_EmitInteger, MVT::i32, sub0_sub1, +def : Pat<(v2i32 (extract_subvector v32i32:$src, (i32 0))), + (EXTRACT_SUBREG GPR_1024:$src, sub0_sub1)>; + +// CHECK: OPC_CheckChild1Integer, 15, +// CHECK: OPC_EmitInteger, MVT::i32, 5|128,1/*133*/, +def : Pat<(v2i32 (extract_subvector v32i32:$src, (i32 15))), + (EXTRACT_SUBREG GPR_1024:$src, sub30_sub31)>; diff --git a/llvm/utils/TableGen/CodeGenRegisters.h b/llvm/utils/TableGen/CodeGenRegisters.h --- a/llvm/utils/TableGen/CodeGenRegisters.h +++ b/llvm/utils/TableGen/CodeGenRegisters.h @@ -626,9 +626,13 @@ return SubRegIndices; } - // Find a SubRegIndex form its Record def. + // Find a SubRegIndex from its Record def or add to the list if it does + // not exist there yet. CodeGenSubRegIndex *getSubRegIdx(Record*); + // Find a SubRegIndex from its Record def. + const CodeGenSubRegIndex *findSubRegIdx(const Record* Def) const; + // Find or create a sub-register index representing the A+B composition. CodeGenSubRegIndex *getCompositeSubRegIndex(CodeGenSubRegIndex *A, CodeGenSubRegIndex *B); diff --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/CodeGenRegisters.cpp --- a/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -1220,6 +1220,12 @@ return Idx; } +const CodeGenSubRegIndex * +CodeGenRegBank::findSubRegIdx(const Record* Def) const { + auto I = Def2SubRegIdx.find(Def); + return (I == Def2SubRegIdx.end()) ? nullptr : I->second; +} + CodeGenRegister *CodeGenRegBank::getReg(Record *Def) { CodeGenRegister *&Reg = Def2Reg[Def]; if (Reg) diff --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp --- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -619,7 +619,7 @@ } case Matcher::EmitStringInteger: { const std::string &Val = cast(N)->getValue(); - // These should always fit into one byte. + // These should always fit into 7 bits. OS << "OPC_EmitInteger, " << getEnumName(cast(N)->getVT()) << ", " << Val << ",\n"; diff --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp --- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -715,6 +715,18 @@ // Handle a subregister index. This is used for INSERT_SUBREG etc. if (Def->isSubClassOf("SubRegIndex")) { + const CodeGenRegBank &RB = CGP.getTargetInfo().getRegBank(); + // If we have more than 127 subreg indices the encoding can overflow + // 7 bit and we cannot use StringInteger. + if (RB.getSubRegIndices().size() > 127) { + const CodeGenSubRegIndex *I = RB.findSubRegIdx(Def); + assert(I && "Cannot find subreg index by name!"); + if (I->EnumValue > 127) { + AddMatcher(new EmitIntegerMatcher(I->EnumValue, MVT::i32)); + ResultOps.push_back(NextRecordedOperandNo++); + return; + } + } std::string Value = getQualifiedName(Def); AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32)); ResultOps.push_back(NextRecordedOperandNo++); diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -173,7 +173,7 @@ std::string Namespace = SubRegIndices.front().getNamespace(); if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; - OS << "enum {\n NoSubRegister,\n"; + OS << "enum : uint16_t {\n NoSubRegister,\n"; unsigned i = 0; for (const auto &Idx : SubRegIndices) OS << " " << Idx.getName() << ",\t// " << ++i << "\n";