@@ -282,11 +282,37 @@ static TypeSigTy ComputeTypeSignature(const CodeGenIntrinsic &Int) {
282282 return TypeSig;
283283}
284284
285+ // Pack the type signature into 32-bit fixed encoding word.
286+ static std::optional<uint32_t > encodePacked (const TypeSigTy &TypeSig) {
287+ if (TypeSig.size () > 8 )
288+ return std::nullopt ;
289+
290+ uint32_t Result = 0 ;
291+ for (unsigned char C : reverse (TypeSig)) {
292+ if (C > 15 )
293+ return std::nullopt ;
294+ Result = (Result << 4 ) | C;
295+ }
296+ return Result;
297+ }
298+
285299void IntrinsicEmitter::EmitGenerator (const CodeGenIntrinsicTable &Ints,
286300 raw_ostream &OS) {
287- // If we can compute a 32-bit fixed encoding for this intrinsic, do so and
301+ // Note: the code below can be switched to use 32-bit fixed encoding by
302+ // flipping the flag below.
303+ constexpr bool Use16BitFixedEncoding = true ;
304+ using FixedEncodingTy =
305+ std::conditional_t <Use16BitFixedEncoding, uint16_t , uint32_t >;
306+ constexpr unsigned FixedEncodingBits = sizeof (FixedEncodingTy) * CHAR_BIT;
307+ // Mask with all bits 1 except the most significant bit.
308+ const unsigned Mask = (1U << (FixedEncodingBits - 1 )) - 1 ;
309+ const unsigned MSBPostion = FixedEncodingBits - 1 ;
310+ StringRef FixedEncodingTypeName =
311+ Use16BitFixedEncoding ? " uint16_t" : " uint32_t" ;
312+
313+ // If we can compute a 16/32-bit fixed encoding for this intrinsic, do so and
288314 // capture it in this vector, otherwise store a ~0U.
289- std::vector<unsigned > FixedEncodings;
315+ std::vector<FixedEncodingTy > FixedEncodings;
290316 SequenceToOffsetTable<TypeSigTy> LongEncodingTable;
291317
292318 FixedEncodings.reserve (Ints.size ());
@@ -296,69 +322,59 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
296322 // Get the signature for the intrinsic.
297323 TypeSigTy TypeSig = ComputeTypeSignature (Int);
298324
299- // Check to see if we can encode it into a 32-bit word. We can only encode
300- // 8 nibbles into a 32-bit word.
301- if (TypeSig.size () <= 8 ) {
302- // Attempt to pack elements of TypeSig into a 32-bit word, starting from
303- // the most significant nibble.
304- unsigned Result = 0 ;
305- bool Failed = false ;
306- for (unsigned char C : reverse (TypeSig)) {
307- if (C > 15 ) {
308- Failed = true ;
309- break ;
310- }
311- Result = (Result << 4 ) | C;
312- }
313-
314- // If this could be encoded into a 31-bit word, return it.
315- if (!Failed && (Result >> 31 ) == 0 ) {
316- FixedEncodings.push_back (Result);
317- continue ;
318- }
325+ // Check to see if we can encode it into a 16/32 bit word.
326+ std::optional<uint32_t > Result = encodePacked (TypeSig);
327+ if (Result && (*Result & Mask) == Result) {
328+ FixedEncodings.push_back (static_cast <FixedEncodingTy>(*Result));
329+ continue ;
319330 }
320331
321- // Otherwise, we're going to unique the sequence into the
322- // LongEncodingTable, and use its offset in the 32-bit table instead.
323332 LongEncodingTable.add (TypeSig);
324333
325334 // This is a placehold that we'll replace after the table is laid out.
326- FixedEncodings.push_back (~0U );
335+ FixedEncodings.push_back (static_cast <FixedEncodingTy>( ~0U ) );
327336 }
328337
329338 LongEncodingTable.layout ();
330339
331- OS << R"( // Global intrinsic function declaration type table.
340+ OS << formatv ( R"( // Global intrinsic function declaration type table.
332341#ifdef GET_INTRINSIC_GENERATOR_GLOBAL
333- static constexpr unsigned IIT_Table[] = {
334- )" ;
342+ static constexpr {0} IIT_Table[] = {{
343+ )" ,
344+ FixedEncodingTypeName);
335345
346+ unsigned MaxOffset = 0 ;
336347 for (auto [Idx, FixedEncoding, Int] : enumerate(FixedEncodings, Ints)) {
337348 if ((Idx & 7 ) == 7 )
338349 OS << " \n " ;
339350
340351 // If the entry fit in the table, just emit it.
341- if (FixedEncoding != ~ 0U ) {
352+ if (( FixedEncoding & Mask) == FixedEncoding ) {
342353 OS << " 0x" << Twine::utohexstr (FixedEncoding) << " , " ;
343354 continue ;
344355 }
345356
346357 TypeSigTy TypeSig = ComputeTypeSignature (Int);
358+ unsigned Offset = LongEncodingTable.get (TypeSig);
359+ MaxOffset = std::max (MaxOffset, Offset);
347360
348361 // Otherwise, emit the offset into the long encoding table. We emit it this
349362 // way so that it is easier to read the offset in the .def file.
350- OS << " (1U<<31 ) | " << LongEncodingTable. get (TypeSig) << " , " ;
363+ OS << formatv ( " (1U<<{0} ) | {1}, " , MSBPostion, Offset) ;
351364 }
352365
353366 OS << " 0\n };\n\n " ;
354367
368+ // verify that all offsets will fit in 16/32 bits.
369+ if ((MaxOffset & Mask) != MaxOffset)
370+ PrintFatalError (" Offset of long encoding table exceeds encoding bits" );
371+
355372 // Emit the shared table of register lists.
356373 OS << " static constexpr unsigned char IIT_LongEncodingTable[] = {\n " ;
357374 if (!LongEncodingTable.empty ())
358375 LongEncodingTable.emit (
359376 OS, [](raw_ostream &OS, unsigned char C) { OS << (unsigned )C; });
360- OS << " 255\n };\n\n " ;
361-
377+ OS << " 255\n };\n " ;
362378 OS << " #endif\n\n " ; // End of GET_INTRINSIC_GENERATOR_GLOBAL
363379}
364380
0 commit comments