Skip to content

Commit 1f5a6b3

Browse files
committed
Allow caching in conditional dominance scopes and fix some
severe problems with the implementation thereof.
1 parent 9ad406d commit 1f5a6b3

File tree

8 files changed

+89
-37
lines changed

8 files changed

+89
-37
lines changed

lib/IRGen/Fulfillment.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "Fulfillment.h"
19+
#include "IRGen.h"
1920

2021
#include "swift/AST/Decl.h"
2122
#include "swift/SIL/TypeLowering.h"

lib/IRGen/Fulfillment.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
namespace swift {
2727
namespace irgen {
28+
enum IsExact_t : bool;
2829

2930
/// The metadata value can be fulfilled by following the given metadata
3031
/// path from the given source.
@@ -46,10 +47,6 @@ class FulfillmentMap {
4647
llvm::DenseMap<FulfillmentKey, Fulfillment> Fulfillments;
4748

4849
public:
49-
/// Given that we have metadata for a type, is it exactly of the
50-
/// specified type, or might it be a subtype?
51-
enum IsExact_t : bool { IsInexact = false, IsExact = true };
52-
5350
struct InterestingKeysCallback {
5451
/// Is the given type something that we should add fulfillments for?
5552
virtual bool isInterestingType(CanType type) const = 0;

lib/IRGen/GenMeta.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
namespace llvm {
2424
template <class T> class ArrayRef;
2525
class Constant;
26+
class Function;
27+
class GlobalVariable;
2628
class Value;
2729
}
2830

lib/IRGen/GenProto.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,8 +1843,7 @@ namespace {
18431843
}
18441844
} callback;
18451845
Fulfillments->searchTypeMetadata(*IGM.SILMod->getSwiftModule(),
1846-
ConcreteType,
1847-
FulfillmentMap::IsExact,
1846+
ConcreteType, IsExact,
18481847
/*sourceIndex*/ 0, MetadataPath(),
18491848
callback);
18501849
}
@@ -2707,7 +2706,7 @@ namespace {
27072706
auto paramType = FnType->getParameters()[0].getType();
27082707
Sources.emplace_back(SourceKind::Metadata, 0, paramType);
27092708

2710-
considerType(paramType, FulfillmentMap::IsInexact, 0, MetadataPath());
2709+
considerType(paramType, IsInexact, 0, MetadataPath());
27112710
}
27122711

27132712
ArrayRef<Source> getSources() const { return Sources; }
@@ -2746,8 +2745,7 @@ namespace {
27462745
}
27472746

27482747
void considerNewTypeSource(SourceKind kind, unsigned paramIndex,
2749-
CanType type,
2750-
FulfillmentMap::IsExact_t isExact) {
2748+
CanType type, IsExact_t isExact) {
27512749
if (!Fulfillments.isInterestingTypeForFulfillments(type)) return;
27522750

27532751
// Prospectively add a source.
@@ -2760,7 +2758,7 @@ namespace {
27602758
}
27612759
}
27622760

2763-
bool considerType(CanType type, FulfillmentMap::IsExact_t isExact,
2761+
bool considerType(CanType type, IsExact_t isExact,
27642762
unsigned sourceIndex, MetadataPath &&path) {
27652763
struct Callback : FulfillmentMap::InterestingKeysCallback {
27662764
PolymorphicConvention &Self;
@@ -2794,8 +2792,7 @@ namespace {
27942792
if (auto paramTy = dyn_cast<GenericTypeParamType>(selfTy))
27952793
considerWitnessParamType(paramTy);
27962794
else
2797-
considerType(selfTy, FulfillmentMap::IsInexact,
2798-
Sources.size() - 1, MetadataPath());
2795+
considerType(selfTy, IsInexact, Sources.size() - 1, MetadataPath());
27992796
}
28002797

28012798
void considerParameter(SILParameterInfo param, unsigned paramIndex,
@@ -2816,8 +2813,7 @@ namespace {
28162813
if (!isSelfParameter) return;
28172814
if (type->getNominalOrBoundGenericNominal()) {
28182815
considerNewTypeSource(SourceKind::GenericLValueMetadata,
2819-
paramIndex, type,
2820-
FulfillmentMap::IsExact);
2816+
paramIndex, type, IsExact);
28212817
}
28222818
return;
28232819

@@ -2828,7 +2824,7 @@ namespace {
28282824
// Classes are sources of metadata.
28292825
if (type->getClassOrBoundGenericClass()) {
28302826
considerNewTypeSource(SourceKind::ClassPointer, paramIndex, type,
2831-
FulfillmentMap::IsInexact);
2827+
IsInexact);
28322828
return;
28332829
}
28342830

@@ -2839,7 +2835,7 @@ namespace {
28392835

28402836
CanType objTy = metatypeTy.getInstanceType();
28412837
considerNewTypeSource(SourceKind::Metadata, paramIndex, objTy,
2842-
FulfillmentMap::IsInexact);
2838+
IsInexact);
28432839
return;
28442840
}
28452841

lib/IRGen/IRGen.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ enum class ExtraData : unsigned char {
136136
Last_ExtraData = Block
137137
};
138138

139+
/// Given that we have metadata for a type, is it for exactly the
140+
/// specified type, or might it be a subtype?
141+
enum IsExact_t : bool {
142+
IsInexact = false,
143+
IsExact = true
144+
};
145+
139146
/// ResilienceScope - The compiler is often able to pursue
140147
/// optimizations based on its knowledge of the implementation of some
141148
/// language structure. However, optimizations which affect

lib/IRGen/IRGenFunction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,11 @@ class IRGenFunction {
396396
setScopedLocalTypeData(type.getSwiftRValueType(), kind, data);
397397
}
398398

399+
/// Given a concrete type metadata node, add all the local type data
400+
/// that we can reach from it.
401+
void addLocalTypeDataForTypeMetadata(CanType type, IsExact_t isExact,
402+
llvm::Value *metadata);
403+
399404
void setDominanceResolver(DominanceResolverFunction resolver) {
400405
assert(DominanceResolver == nullptr);
401406
DominanceResolver = resolver;

lib/IRGen/LocalTypeData.cpp

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "LocalTypeData.h"
1919
#include "Fulfillment.h"
20+
#include "GenMeta.h"
2021
#include "IRGenFunction.h"
2122
#include "IRGenModule.h"
2223
#include "swift/SIL/SILModule.h"
@@ -78,8 +79,7 @@ llvm::Value *LocalTypeDataCache::tryGet(IRGenFunction &IGF, Key key) {
7879
Optional<unsigned> bestCost;
7980

8081
CacheEntry *next = chain.Root, *nextPrev = nullptr;
81-
do {
82-
assert(next);
82+
while (next) {
8383
CacheEntry *cur = next, *curPrev = nextPrev;
8484
nextPrev = cur;
8585
next = cur->getNext();
@@ -105,7 +105,7 @@ llvm::Value *LocalTypeDataCache::tryGet(IRGenFunction &IGF, Key key) {
105105
}
106106
best = cur;
107107
bestPrev = curPrev;
108-
} while (next);
108+
}
109109

110110
// If we didn't find anything, we're done.
111111
if (!best) return nullptr;
@@ -126,9 +126,17 @@ llvm::Value *LocalTypeDataCache::tryGet(IRGenFunction &IGF, Key key) {
126126
auto result = entry->follow(IGF, source);
127127

128128
// Make a new concrete entry at the active definition point.
129+
130+
// Register witih the active ConditionalDominanceScope if necessary.
131+
bool isConditional = IGF.isConditionalDominancePoint();
132+
if (isConditional) {
133+
IGF.registerConditionalLocalTypeDataKey(key);
134+
}
135+
136+
// Allocate the new entry.
129137
auto newEntry =
130138
new ConcreteCacheEntry(IGF.getActiveDominancePoint(),
131-
IGF.isConditionalDominancePoint(), result);
139+
isConditional, result);
132140

133141
// If the active definition point is the same as the old entry's
134142
// definition point, delete the old entry.
@@ -164,13 +172,16 @@ LocalTypeDataCache::AbstractCacheEntry::follow(IRGenFunction &IGF,
164172

165173
void IRGenFunction::setScopedLocalTypeData(CanType type, LocalTypeDataKind kind,
166174
llvm::Value *data) {
167-
if (isConditionalDominancePoint())
168-
return;
175+
auto key = LocalTypeDataCache::getKey(type, kind);
176+
177+
// Register with the active ConditionalDominanceScope if necessary.
178+
bool isConditional = isConditionalDominancePoint();
179+
if (isConditional) {
180+
registerConditionalLocalTypeDataKey(key);
181+
}
169182

170183
getOrCreateLocalTypeData().addConcrete(getActiveDominancePoint(),
171-
isConditionalDominancePoint(),
172-
LocalTypeDataCache::getKey(type, kind),
173-
data);
184+
isConditional, key, data);
174185
}
175186

176187
void IRGenFunction::setUnscopedLocalTypeData(CanType type,
@@ -181,33 +192,46 @@ void IRGenFunction::setUnscopedLocalTypeData(CanType type,
181192
LocalTypeDataCache::getKey(type, kind), data);
182193
}
183194

184-
void LocalTypeDataCache::addAbstractForTypeMetadata(IRGenFunction &IGF,
185-
CanType type,
195+
void IRGenFunction::addLocalTypeDataForTypeMetadata(CanType type,
196+
IsExact_t isExact,
186197
llvm::Value *metadata) {
187-
// Don't bother doing this at a conditional dominance point; we're too
188-
// likely to throw it all away.
189-
if (IGF.isConditionalDominancePoint())
198+
// Remember that we have this type metadata concretely.
199+
if (isExact) {
200+
setScopedLocalTypeData(type, LocalTypeDataKind::forMetatype(), metadata);
201+
}
202+
203+
// Don't bother adding abstract fulfillments at a conditional dominance
204+
// point; we're too likely to throw them all away.
205+
if (isConditionalDominancePoint())
190206
return;
191207

208+
getOrCreateLocalTypeData()
209+
.addAbstractForTypeMetadata(*this, type, isExact, metadata);
210+
}
211+
212+
void LocalTypeDataCache::addAbstractForTypeMetadata(IRGenFunction &IGF,
213+
CanType type,
214+
IsExact_t isExact,
215+
llvm::Value *metadata) {
192216
// Look for anything at all that's fulfilled by this. If we don't find
193217
// anything, stop.
194218
FulfillmentMap fulfillments;
195219
if (!fulfillments.searchTypeMetadata(*IGF.IGM.SILMod->getSwiftModule(),
196-
type, FulfillmentMap::IsExact,
220+
type, isExact,
197221
/*source*/ 0, MetadataPath(),
198222
FulfillmentMap::Everything())) {
199223
return;
200224
}
201225

202226
addAbstractForFulfillments(IGF, std::move(fulfillments),
203-
[&]() -> AbstractSource {
227+
[&]() -> AbstractSource {
204228
return AbstractSource(AbstractSource::Kind::TypeMetadata, type, metadata);
205229
});
206230
}
207231

208232
void LocalTypeDataCache::
209233
addAbstractForFulfillments(IRGenFunction &IGF, FulfillmentMap &&fulfillments,
210-
llvm::function_ref<AbstractSource()> createSource) {
234+
llvm::function_ref<AbstractSource()> createSource) {
211235
// Add the source lazily.
212236
Optional<unsigned> sourceIndex;
213237
auto getSourceIndex = [&]() -> unsigned {
@@ -233,7 +257,18 @@ addAbstractForFulfillments(IRGenFunction &IGF, FulfillmentMap &&fulfillments,
233257
} else {
234258
continue;
235259
}
260+
236261
} else {
262+
// Ignore type metadata fulfillments for non-dependent types that
263+
// we can produce very cheaply. We don't want to end up emitting
264+
// the type metadata for Int by chasing through N layers of metadata
265+
// just because that path happens to be in the cache.
266+
if (!type->hasArchetype() &&
267+
getTypeMetadataAccessStrategy(IGF.IGM, type, /*preferDirect*/ true)
268+
== MetadataAccessStrategy::Direct) {
269+
continue;
270+
}
271+
237272
localDataKind = LocalTypeDataKind::forMetatype();
238273
}
239274

@@ -276,8 +311,16 @@ addAbstractForFulfillments(IRGenFunction &IGF, FulfillmentMap &&fulfillments,
276311
if (foundBetter) continue;
277312

278313
// Okay, make a new entry.
314+
315+
// Register with the conditional dominance scope if necessary.
316+
bool isConditional = IGF.isConditionalDominancePoint();
317+
if (isConditional) {
318+
IGF.registerConditionalLocalTypeDataKey(key);
319+
}
320+
321+
// Allocate the new entry.
279322
auto newEntry = new AbstractCacheEntry(IGF.getActiveDominancePoint(),
280-
IGF.isConditionalDominancePoint(),
323+
isConditional,
281324
getSourceIndex(),
282325
std::move(fulfillment.second.Path));
283326

lib/IRGen/LocalTypeData.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ namespace swift {
3737

3838
namespace irgen {
3939
class FulfillmentMap;
40+
enum IsExact_t : bool;
41+
4042

4143
/// A cache of local type data.
4244
///
@@ -250,10 +252,9 @@ class LocalTypeDataCache {
250252
Map[key].push_front(newEntry);
251253
}
252254

253-
/// Add abstract entries based on what can be fulfilled from the given
254-
/// type metadata.
255+
/// Add entries based on what can be fulfilled from the given type metadata.
255256
void addAbstractForTypeMetadata(IRGenFunction &IGF, CanType type,
256-
llvm::Value *metadata);
257+
IsExact_t isExact, llvm::Value *metadata);
257258

258259
void eraseConditional(ArrayRef<LocalTypeDataKey> keys);
259260
};

0 commit comments

Comments
 (0)