17
17
#include " swift/AST/Expr.h"
18
18
#include " swift/AST/Stmt.h"
19
19
#include " swift/ClangImporter/ClangModule.h"
20
+ #include " swift/SIL/BasicBlockData.h"
21
+ #include " swift/SIL/SILBitfield.h"
20
22
#include " swift/SIL/SILValue.h"
21
23
#include " swift/SIL/InstructionUtils.h"
22
24
#include " swift/SIL/SILArgument.h"
@@ -136,7 +138,12 @@ namespace {
136
138
// T,F -> Partial
137
139
SmallBitVector Data;
138
140
public:
139
- AvailabilitySet (unsigned NumElts) {
141
+ AvailabilitySet () {}
142
+
143
+ AvailabilitySet (unsigned NumElts) { init (NumElts); }
144
+
145
+ void init (unsigned NumElts) {
146
+ Data.set ();
140
147
Data.resize (NumElts*2 , true );
141
148
}
142
149
@@ -270,11 +277,15 @@ namespace {
270
277
// / plus the information merged-in from the predecessor blocks.
271
278
Optional<DIKind> OutSelfInitialized;
272
279
273
- LiveOutBlockState (unsigned NumElements)
274
- : HasNonLoadUse(false ),
275
- isInWorkList (false ),
276
- LocalAvailability(NumElements),
277
- OutAvailability(NumElements) {
280
+ LiveOutBlockState () { init (0 ); }
281
+
282
+ void init (unsigned NumElements) {
283
+ HasNonLoadUse = false ;
284
+ isInWorkList = false ;
285
+ LocalAvailability.init (NumElements);
286
+ OutAvailability.init (NumElements);
287
+ LocalSelfInitialized = None;
288
+ OutSelfInitialized = None;
278
289
}
279
290
280
291
// / Sets all unknown elements to not-available.
@@ -371,9 +382,8 @@ namespace {
371
382
DIKind SelfInitialized;
372
383
};
373
384
374
- } // end anonymous namespace
385
+ using BlockStates = BasicBlockData<LiveOutBlockState>;
375
386
376
- namespace {
377
387
// / LifetimeChecker - This is the main heavy lifting for definite
378
388
// / initialization checking of a memory object.
379
389
class LifetimeChecker {
@@ -390,7 +400,8 @@ namespace {
390
400
SmallVector<unsigned , 8 > NeedsUpdateForInitState;
391
401
std::vector<ConditionalDestroy> ConditionalDestroys;
392
402
393
- llvm::SmallDenseMap<SILBasicBlock*, LiveOutBlockState, 32 > PerBlockInfo;
403
+ BlockStates &blockStates;
404
+ BasicBlockFlag blockStateInitialized;
394
405
395
406
// / This is a map of uses that are not loads (i.e., they are Stores,
396
407
// / InOutUses, and Escapes), to their entry in Uses.
@@ -427,7 +438,8 @@ namespace {
427
438
428
439
public:
429
440
LifetimeChecker (const DIMemoryObjectInfo &TheMemory,
430
- DIElementUseInfo &UseInfo);
441
+ DIElementUseInfo &UseInfo,
442
+ BlockStates &blockStates);
431
443
432
444
void doIt ();
433
445
@@ -436,9 +448,10 @@ namespace {
436
448
void emitSelfConsumedDiagnostic (SILInstruction *Inst);
437
449
438
450
LiveOutBlockState &getBlockInfo (SILBasicBlock *BB) {
439
- return PerBlockInfo
440
- .insert ({BB, LiveOutBlockState (TheMemory.getNumElements ())})
441
- .first ->second ;
451
+ auto &state = blockStates.get (BB, []() { return LiveOutBlockState (); });
452
+ if (!blockStateInitialized.testAndSet (BB))
453
+ state.init (TheMemory.getNumElements ());
454
+ return state;
442
455
}
443
456
444
457
AvailabilitySet getLivenessAtInst (SILInstruction *Inst, unsigned FirstElt,
@@ -514,10 +527,12 @@ namespace {
514
527
} // end anonymous namespace
515
528
516
529
LifetimeChecker::LifetimeChecker (const DIMemoryObjectInfo &TheMemory,
517
- DIElementUseInfo &UseInfo)
530
+ DIElementUseInfo &UseInfo,
531
+ BlockStates &blockStates)
518
532
: F(TheMemory.getFunction()), Module(TheMemory.getModule()),
519
533
TheMemory(TheMemory), Uses(UseInfo.Uses),
520
- StoresToSelf(UseInfo.StoresToSelf), Destroys(UseInfo.Releases) {
534
+ StoresToSelf(UseInfo.StoresToSelf), Destroys(UseInfo.Releases),
535
+ blockStates(blockStates), blockStateInitialized(&F) {
521
536
522
537
// The first step of processing an element is to collect information about the
523
538
// element into data structures we use later.
@@ -3087,7 +3102,8 @@ bool LifetimeChecker::isInitializedAtUse(const DIMemoryUse &Use,
3087
3102
// Top Level Driver
3088
3103
// ===----------------------------------------------------------------------===//
3089
3104
3090
- static void processMemoryObject (MarkUninitializedInst *I) {
3105
+ static void processMemoryObject (MarkUninitializedInst *I,
3106
+ BlockStates &blockStates) {
3091
3107
LLVM_DEBUG (llvm::dbgs () << " *** Definite Init looking at: " << *I << " \n " );
3092
3108
DIMemoryObjectInfo MemInfo (I);
3093
3109
@@ -3097,7 +3113,7 @@ static void processMemoryObject(MarkUninitializedInst *I) {
3097
3113
// Walk the use list of the pointer, collecting them into the Uses array.
3098
3114
collectDIElementUsesFrom (MemInfo, UseInfo);
3099
3115
3100
- LifetimeChecker (MemInfo, UseInfo).doIt ();
3116
+ LifetimeChecker (MemInfo, UseInfo, blockStates ).doIt ();
3101
3117
}
3102
3118
3103
3119
// / Check that all memory objects that require initialization before use are
@@ -3108,6 +3124,8 @@ static bool checkDefiniteInitialization(SILFunction &Fn) {
3108
3124
<< Fn.getName () << " \n " );
3109
3125
bool Changed = false ;
3110
3126
3127
+ BlockStates blockStates (&Fn);
3128
+
3111
3129
for (auto &BB : Fn) {
3112
3130
for (auto I = BB.begin (), E = BB.end (); I != E;) {
3113
3131
SILInstruction *Inst = &*I;
@@ -3119,7 +3137,7 @@ static bool checkDefiniteInitialization(SILFunction &Fn) {
3119
3137
}
3120
3138
3121
3139
// Then process the memory object.
3122
- processMemoryObject (MUI);
3140
+ processMemoryObject (MUI, blockStates );
3123
3141
3124
3142
// Move off of the MUI only after we have processed memory objects. The
3125
3143
// lifetime checker may rewrite instructions, so it is important to not
0 commit comments