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