diff --git a/include/llvm/CodeGen/DAGISelHeader.h b/include/llvm/CodeGen/DAGISelHeader.h index 29d66f59954..d28f4dad044 100644 --- a/include/llvm/CodeGen/DAGISelHeader.h +++ b/include/llvm/CodeGen/DAGISelHeader.h @@ -200,6 +200,24 @@ GetInt8(const unsigned char *MatcherTable, unsigned &Idx) { return Val; } +/// GetVBR - decode a vbr encoding whose top bit is set. +ALWAYS_INLINE static unsigned +GetVBR(unsigned Val, const unsigned char *MatcherTable, unsigned &Idx) { + assert(Val >= 128 && "Not a VBR"); + Val &= 127; // Remove first vbr bit. + + unsigned Shift = 7; + unsigned NextBits; + do { + NextBits = GetInt1(MatcherTable, Idx); + Val |= (NextBits&127) << Shift; + Shift += 7; + } while (NextBits & 128); + + return Val; +} + + enum BuiltinOpcodes { OPC_Push, OPC_Push2, OPC_RecordNode, @@ -691,6 +709,9 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, SmallVector Ops; for (unsigned i = 0; i != NumOps; ++i) { unsigned RecNo = MatcherTable[MatcherIndex++]; + if (RecNo & 128) + RecNo = GetVBR(RecNo, MatcherTable, MatcherIndex); + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); Ops.push_back(RecordedNodes[RecNo]); } @@ -763,6 +784,9 @@ SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, for (unsigned i = 0; i != NumResults; ++i) { unsigned ResSlot = MatcherTable[MatcherIndex++]; + if (ResSlot & 128) + ResSlot = GetVBR(ResSlot, MatcherTable, MatcherIndex); + assert(ResSlot < RecordedNodes.size() && "Invalid CheckSame"); SDValue Res = RecordedNodes[ResSlot]; diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 33e37fae949..ed720df8081 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -127,6 +127,25 @@ private: }; } // end anonymous namespace. +/// EmitVBRValue - Emit the specified value as a VBR, returning the number of +/// bytes emitted. +static unsigned EmitVBRValue(unsigned Val, raw_ostream &OS) { + if (Val <= 127) { + OS << Val << ", "; + return 1; + } + + unsigned InVal = Val; + unsigned NumBytes = 0; + while (Val > 128) { + OS << (Val&127) << "|128,"; + Val >>= 7; + ++NumBytes; + } + OS << Val << "/*" << InVal << "*/, "; + return NumBytes+1; +} + /// EmitMatcherOpcodes - Emit bytes for the specified matcher and return /// the number of bytes emitted. unsigned MatcherTableEmitter:: @@ -309,22 +328,27 @@ EmitMatcher(const MatcherNode *N, unsigned Indent, formatted_raw_ostream &OS) { OS << getEnumName(EN->getVT(i)) << ", "; OS << EN->getNumOperands() << "/*#Ops*/, "; - for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i) - OS << EN->getOperand(i) << ", "; + unsigned NumOperandBytes = 0; + for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i) { + // We emit the operand numbers in VBR encoded format, in case the number + // is too large to represent with a byte. + NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS); + } OS << '\n'; - return 6+EN->getNumVTs()+EN->getNumOperands(); + return 6+EN->getNumVTs()+NumOperandBytes; } case MatcherNode::CompleteMatch: { const CompleteMatchMatcherNode *CM = cast(N); OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", "; + unsigned NumResultBytes = 0; for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i) - OS << CM->getResult(i) << ", "; + NumResultBytes += EmitVBRValue(CM->getResult(i), OS); OS << '\n'; OS.PadToColumn(Indent*2) << "// Src: " << *CM->getPattern().getSrcPattern() << '\n'; OS.PadToColumn(Indent*2) << "// Dst: " << *CM->getPattern().getDstPattern() << '\n'; - return 2+CM->getNumResults(); + return 2 + NumResultBytes; } } assert(0 && "Unreachable");