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