@@ -3406,10 +3406,19 @@ void TypeConverter::SignatureConversion::remapInput(
3406
3406
SmallVector<Value, 1 >(replacements.begin (), replacements.end ())};
3407
3407
}
3408
3408
3409
- LogicalResult TypeConverter::convertType (Type t,
3410
- SmallVectorImpl<Type> &results) const {
3411
- assert (t && " expected non-null type" );
3412
-
3409
+ // / Internal implementation of the type conversion.
3410
+ // / This is used with either a Type or a Value as the first argument.
3411
+ // / - we can cache the context-free conversions until the last registered
3412
+ // / context-aware conversion.
3413
+ // / - we can't cache the result of type conversion happening after context-aware
3414
+ // / conversions, because the type converter may return different results for the
3415
+ // / same input type.
3416
+ LogicalResult
3417
+ TypeConverter::convertTypeImpl (PointerUnion<Type, Value> typeOrValue,
3418
+ SmallVectorImpl<Type> &results) const {
3419
+ assert (typeOrValue && " expected non-null type" );
3420
+ Type t = (isa<Value>(typeOrValue)) ? cast<Value>(typeOrValue).getType ()
3421
+ : cast<Type>(typeOrValue);
3413
3422
{
3414
3423
std::shared_lock<decltype (cacheMutex)> cacheReadLock (cacheMutex,
3415
3424
std::defer_lock);
@@ -3431,52 +3440,53 @@ LogicalResult TypeConverter::convertType(Type t,
3431
3440
// registered first.
3432
3441
size_t currentCount = results.size ();
3433
3442
3443
+ // We can cache the context-free conversions until the last registered
3444
+ // context-aware conversion. But only if we're processing a Value right now.
3445
+ auto isCacheable = [&](int index) {
3446
+ int numberOfConversionsUntilContextAware =
3447
+ conversions.size () - 1 - contextAwareTypeConversionsIndex;
3448
+ return index < numberOfConversionsUntilContextAware;
3449
+ };
3450
+
3434
3451
std::unique_lock<decltype (cacheMutex)> cacheWriteLock (cacheMutex,
3435
3452
std::defer_lock);
3436
3453
3437
- for (const ConversionCallbackFn &converter : llvm::reverse (conversions)) {
3438
- if (std::optional<LogicalResult> result = converter (t, results)) {
3439
- if (t.getContext ()->isMultithreadingEnabled ())
3440
- cacheWriteLock.lock ();
3441
- if (!succeeded (*result)) {
3442
- assert (results.size () == currentCount &&
3443
- " failed type conversion should not change results" );
3444
- cachedDirectConversions.try_emplace (t, nullptr );
3445
- return failure ();
3446
- }
3447
- auto newTypes = ArrayRef<Type>(results).drop_front (currentCount);
3448
- if (newTypes.size () == 1 )
3449
- cachedDirectConversions.try_emplace (t, newTypes.front ());
3450
- else
3451
- cachedMultiConversions.try_emplace (t, llvm::to_vector<2 >(newTypes));
3454
+ for (auto indexedConverter : llvm::enumerate (llvm::reverse (conversions))) {
3455
+ const ConversionCallbackFn &converter = indexedConverter.value ();
3456
+ std::optional<LogicalResult> result = converter (typeOrValue, results);
3457
+ if (!result) {
3458
+ assert (results.size () == currentCount &&
3459
+ " failed type conversion should not change results" );
3460
+ continue ;
3461
+ }
3462
+ if (!isCacheable (indexedConverter.index ()))
3452
3463
return success ();
3453
- } else {
3464
+ if (t.getContext ()->isMultithreadingEnabled ())
3465
+ cacheWriteLock.lock ();
3466
+ if (!succeeded (*result)) {
3454
3467
assert (results.size () == currentCount &&
3455
3468
" failed type conversion should not change results" );
3469
+ cachedDirectConversions.try_emplace (t, nullptr );
3470
+ return failure ();
3456
3471
}
3472
+ auto newTypes = ArrayRef<Type>(results).drop_front (currentCount);
3473
+ if (newTypes.size () == 1 )
3474
+ cachedDirectConversions.try_emplace (t, newTypes.front ());
3475
+ else
3476
+ cachedMultiConversions.try_emplace (t, llvm::to_vector<2 >(newTypes));
3477
+ return success ();
3457
3478
}
3458
3479
return failure ();
3459
3480
}
3460
3481
3461
- LogicalResult TypeConverter::convertType (Value v ,
3482
+ LogicalResult TypeConverter::convertType (Type t ,
3462
3483
SmallVectorImpl<Type> &results) const {
3463
- assert (v && " expected non-null value" );
3464
-
3465
- // If this type converter does not have context-aware type conversions, call
3466
- // the type-based overload, which has caching.
3467
- if (!hasContextAwareTypeConversions)
3468
- return convertType (v.getType (), results);
3484
+ return convertTypeImpl (t, results);
3485
+ }
3469
3486
3470
- // Walk the added converters in reverse order to apply the most recently
3471
- // registered first.
3472
- for (const ConversionCallbackFn &converter : llvm::reverse (conversions)) {
3473
- if (std::optional<LogicalResult> result = converter (v, results)) {
3474
- if (!succeeded (*result))
3475
- return failure ();
3476
- return success ();
3477
- }
3478
- }
3479
- return failure ();
3487
+ LogicalResult TypeConverter::convertType (Value v,
3488
+ SmallVectorImpl<Type> &results) const {
3489
+ return convertTypeImpl (v, results);
3480
3490
}
3481
3491
3482
3492
Type TypeConverter::convertType (Type t) const {
0 commit comments