@@ -282,11 +282,37 @@ static TypeSigTy ComputeTypeSignature(const CodeGenIntrinsic &Int) {
282
282
return TypeSig;
283
283
}
284
284
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
+
285
299
void IntrinsicEmitter::EmitGenerator (const CodeGenIntrinsicTable &Ints,
286
300
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
288
314
// capture it in this vector, otherwise store a ~0U.
289
- std::vector<unsigned > FixedEncodings;
315
+ std::vector<FixedEncodingTy > FixedEncodings;
290
316
SequenceToOffsetTable<TypeSigTy> LongEncodingTable;
291
317
292
318
FixedEncodings.reserve (Ints.size ());
@@ -296,69 +322,59 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
296
322
// Get the signature for the intrinsic.
297
323
TypeSigTy TypeSig = ComputeTypeSignature (Int);
298
324
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 ;
319
330
}
320
331
321
- // Otherwise, we're going to unique the sequence into the
322
- // LongEncodingTable, and use its offset in the 32-bit table instead.
323
332
LongEncodingTable.add (TypeSig);
324
333
325
334
// 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 ) );
327
336
}
328
337
329
338
LongEncodingTable.layout ();
330
339
331
- OS << R"( // Global intrinsic function declaration type table.
340
+ OS << formatv ( R"( // Global intrinsic function declaration type table.
332
341
#ifdef GET_INTRINSIC_GENERATOR_GLOBAL
333
- static constexpr unsigned IIT_Table[] = {
334
- )" ;
342
+ static constexpr {0} IIT_Table[] = {{
343
+ )" ,
344
+ FixedEncodingTypeName);
335
345
346
+ unsigned MaxOffset = 0 ;
336
347
for (auto [Idx, FixedEncoding, Int] : enumerate(FixedEncodings, Ints)) {
337
348
if ((Idx & 7 ) == 7 )
338
349
OS << " \n " ;
339
350
340
351
// If the entry fit in the table, just emit it.
341
- if (FixedEncoding != ~ 0U ) {
352
+ if (( FixedEncoding & Mask) == FixedEncoding ) {
342
353
OS << " 0x" << Twine::utohexstr (FixedEncoding) << " , " ;
343
354
continue ;
344
355
}
345
356
346
357
TypeSigTy TypeSig = ComputeTypeSignature (Int);
358
+ unsigned Offset = LongEncodingTable.get (TypeSig);
359
+ MaxOffset = std::max (MaxOffset, Offset);
347
360
348
361
// Otherwise, emit the offset into the long encoding table. We emit it this
349
362
// 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) ;
351
364
}
352
365
353
366
OS << " 0\n };\n\n " ;
354
367
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
+
355
372
// Emit the shared table of register lists.
356
373
OS << " static constexpr unsigned char IIT_LongEncodingTable[] = {\n " ;
357
374
if (!LongEncodingTable.empty ())
358
375
LongEncodingTable.emit (
359
376
OS, [](raw_ostream &OS, unsigned char C) { OS << (unsigned )C; });
360
- OS << " 255\n };\n\n " ;
361
-
377
+ OS << " 255\n };\n " ;
362
378
OS << " #endif\n\n " ; // End of GET_INTRINSIC_GENERATOR_GLOBAL
363
379
}
364
380
0 commit comments