@@ -282,11 +282,34 @@ 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
+ std::optional<unsigned > encodePacked (const TypeSigTy &TypeSig) {
287
+ if (TypeSig.size () > 8 )
288
+ return std::nullopt;
289
+
290
+ unsigned 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 EncodingTy =
305
+ std::conditional_t <Use16BitFixedEncoding, uint16_t , unsigned >;
306
+ const unsigned Mask = Use16BitFixedEncoding ? 0x7FFF : 0x7FFFFFFF ;
307
+ const unsigned MSBPostion = Use16BitFixedEncoding ? 15 : 31 ;
308
+ StringRef TypeName = Use16BitFixedEncoding ? " uint16_t" : " unsigned" ;
309
+
310
+ // If we can compute a 16/32-bit fixed encoding for this intrinsic, do so and
288
311
// capture it in this vector, otherwise store a ~0U.
289
- std::vector<unsigned > FixedEncodings;
312
+ std::vector<EncodingTy > FixedEncodings;
290
313
SequenceToOffsetTable<TypeSigTy> LongEncodingTable;
291
314
292
315
FixedEncodings.reserve (Ints.size ());
@@ -296,69 +319,59 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
296
319
// Get the signature for the intrinsic.
297
320
TypeSigTy TypeSig = ComputeTypeSignature (Int);
298
321
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
- }
322
+ // Check to see if we can encode it into a 16/32 bit word.
323
+ std::optional<unsigned > Result = encodePacked (TypeSig);
324
+ if (Result && (*Result & Mask) == Result) {
325
+ FixedEncodings.push_back (static_cast <EncodingTy>(*Result));
326
+ continue ;
319
327
}
320
328
321
- // Otherwise, we're going to unique the sequence into the
322
- // LongEncodingTable, and use its offset in the 32-bit table instead.
323
329
LongEncodingTable.add (TypeSig);
324
330
325
331
// This is a placehold that we'll replace after the table is laid out.
326
- FixedEncodings.push_back (~0U );
332
+ FixedEncodings.push_back (static_cast <EncodingTy>( ~0U ) );
327
333
}
328
334
329
335
LongEncodingTable.layout ();
330
336
331
- OS << R"( // Global intrinsic function declaration type table.
337
+ OS << formatv ( R"( // Global intrinsic function declaration type table.
332
338
#ifdef GET_INTRINSIC_GENERATOR_GLOBAL
333
- static constexpr unsigned IIT_Table[] = {
334
- )" ;
339
+ static constexpr {0} IIT_Table[] = {{
340
+ )" ,
341
+ TypeName);
335
342
343
+ unsigned MaxOffset = 0 ;
336
344
for (auto [Idx, FixedEncoding, Int] : enumerate(FixedEncodings, Ints)) {
337
345
if ((Idx & 7 ) == 7 )
338
346
OS << " \n " ;
339
347
340
348
// If the entry fit in the table, just emit it.
341
- if (FixedEncoding != ~ 0U ) {
349
+ if (( FixedEncoding & Mask) == FixedEncoding ) {
342
350
OS << " 0x" << Twine::utohexstr (FixedEncoding) << " , " ;
343
351
continue ;
344
352
}
345
353
346
354
TypeSigTy TypeSig = ComputeTypeSignature (Int);
355
+ unsigned Offset = LongEncodingTable.get (TypeSig);
356
+ MaxOffset = std::max (MaxOffset, Offset);
347
357
348
358
// Otherwise, emit the offset into the long encoding table. We emit it this
349
359
// way so that it is easier to read the offset in the .def file.
350
- OS << " (1U<<31 ) | " << LongEncodingTable. get (TypeSig) << " , " ;
360
+ OS << formatv ( " (1U<<{0} ) | {1}, " , MSBPostion, Offset) ;
351
361
}
352
362
353
363
OS << " 0\n };\n\n " ;
354
364
365
+ // verify that all offsets will fit in 16/32 bits.
366
+ if ((MaxOffset & Mask) != MaxOffset)
367
+ PrintFatalError (" Offset of long encoding table exceeds encoding bits" );
368
+
355
369
// Emit the shared table of register lists.
356
370
OS << " static constexpr unsigned char IIT_LongEncodingTable[] = {\n " ;
357
371
if (!LongEncodingTable.empty ())
358
372
LongEncodingTable.emit (
359
373
OS, [](raw_ostream &OS, unsigned char C) { OS << (unsigned )C; });
360
- OS << " 255\n };\n\n " ;
361
-
374
+ OS << " 255\n };\n " ;
362
375
OS << " #endif\n\n " ; // End of GET_INTRINSIC_GENERATOR_GLOBAL
363
376
}
364
377
0 commit comments