Index: llvm/test/TableGen/dag-isel-subregs.td =================================================================== --- /dev/null +++ llvm/test/TableGen/dag-isel-subregs.td @@ -0,0 +1,141 @@ +// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s | FileCheck %s + +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)>; + +// 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)>; Index: llvm/utils/TableGen/CodeGenRegisters.h =================================================================== --- llvm/utils/TableGen/CodeGenRegisters.h +++ llvm/utils/TableGen/CodeGenRegisters.h @@ -787,6 +787,10 @@ // another sub-register with the same or larger lane mask. LaneBitmask CoveringLanes; + // \returns SubRegIndex by \p SubRegIndexName or nullptr + const CodeGenSubRegIndex * + lookupSubRegIndex(StringRef SubRegIndexName) const; + // Helper function for printing debug information. Handles artificial // (non-native) reg units. void printRegUnitName(unsigned Unit) const; Index: llvm/utils/TableGen/CodeGenRegisters.cpp =================================================================== --- llvm/utils/TableGen/CodeGenRegisters.cpp +++ llvm/utils/TableGen/CodeGenRegisters.cpp @@ -2422,6 +2422,15 @@ return BV; } +const CodeGenSubRegIndex * +CodeGenRegBank::lookupSubRegIndex(StringRef SubRegIndexName) const { + auto I = std::find_if(SubRegIndices.cbegin(), SubRegIndices.cend(), + [&SubRegIndexName](const CodeGenSubRegIndex &I) { + return SubRegIndexName.equals(I.getName()); + }); + return (I == SubRegIndices.cend()) ? nullptr : &*I; +} + void CodeGenRegBank::printRegUnitName(unsigned Unit) const { if (Unit < NumNativeRegUnits) dbgs() << ' ' << RegUnits[Unit].Roots[0]->getName(); Index: llvm/utils/TableGen/DAGISelEmitter.cpp =================================================================== --- llvm/utils/TableGen/DAGISelEmitter.cpp +++ llvm/utils/TableGen/DAGISelEmitter.cpp @@ -163,9 +163,10 @@ // Convert each variant of each pattern into a Matcher. std::vector PatternMatchers; + const CodeGenRegBank &RB = CGP.getTargetInfo().getRegBank(); for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { for (unsigned Variant = 0; ; ++Variant) { - if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP)) + if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP, RB)) PatternMatchers.push_back(M); else break; Index: llvm/utils/TableGen/DAGISelMatcher.h =================================================================== --- llvm/utils/TableGen/DAGISelMatcher.h +++ llvm/utils/TableGen/DAGISelMatcher.h @@ -9,6 +9,7 @@ #ifndef LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H #define LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H +#include "CodeGenRegisters.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -28,7 +29,8 @@ class TreePattern; Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant, - const CodeGenDAGPatterns &CGP); + const CodeGenDAGPatterns &CGP, + const CodeGenRegBank &RB); void OptimizeMatcher(std::unique_ptr &Matcher, const CodeGenDAGPatterns &CGP); void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP, Index: llvm/utils/TableGen/DAGISelMatcherEmitter.cpp =================================================================== --- llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ 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"; Index: llvm/utils/TableGen/DAGISelMatcherGen.cpp =================================================================== --- llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -53,6 +53,7 @@ class MatcherGen { const PatternToMatch &Pattern; const CodeGenDAGPatterns &CGP; + const CodeGenRegBank &RB; /// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts /// out with all of the types removed. This allows us to insert type checks @@ -98,7 +99,8 @@ /// which should have future checks stuck into its Next position. Matcher *CurPredicate; public: - MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp); + MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp, + const CodeGenRegBank &RB); bool EmitMatcherCode(unsigned Variant); void EmitResultCode(); @@ -144,8 +146,9 @@ } // end anonymous namespace MatcherGen::MatcherGen(const PatternToMatch &pattern, - const CodeGenDAGPatterns &cgp) -: Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0), + const CodeGenDAGPatterns &cgp, + const CodeGenRegBank &rb) +: Pattern(pattern), CGP(cgp), RB(rb), NextRecordedOperandNo(0), TheMatcher(nullptr), CurPredicate(nullptr) { // We need to produce the matcher tree for the patterns source pattern. To do // this we need to match the structure as well as the types. To do the type @@ -715,6 +718,18 @@ // Handle a subregister index. This is used for INSERT_SUBREG etc. if (Def->isSubClassOf("SubRegIndex")) { + // If we have more than 127 subreg indices the encoding can overflow + // 7 bit and we cannot use StringInteger. + if (RB.getSubRegIndices().size() > 127) { + StringRef Name = Def->getName(); + const CodeGenSubRegIndex *I = RB.lookupSubRegIndex(Name); + 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++); @@ -1062,10 +1077,11 @@ /// ConvertPatternToMatcher - Create the matcher for the specified pattern with /// the specified variant. If the variant number is invalid, this returns null. -Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern, - unsigned Variant, - const CodeGenDAGPatterns &CGP) { - MatcherGen Gen(Pattern, CGP); +Matcher * +llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern, unsigned Variant, + const CodeGenDAGPatterns &CGP, + const CodeGenRegBank &RB) { + MatcherGen Gen(Pattern, CGP, RB); // Generate the code for the matcher. if (Gen.EmitMatcherCode(Variant)) Index: llvm/utils/TableGen/RegisterInfoEmitter.cpp =================================================================== --- llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ 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";