@@ -142,27 +142,94 @@ static unsigned computeSubelement(SILValue Pointer,
142
142
}
143
143
}
144
144
145
+ // ===----------------------------------------------------------------------===//
146
+ // Available Value
147
+ // ===----------------------------------------------------------------------===//
148
+
149
+ namespace {
150
+
151
+ struct AvailableValue {
152
+ SILValue Value;
153
+ unsigned SubElementNumber;
154
+
155
+ public:
156
+ AvailableValue () = default ;
157
+
158
+ AvailableValue (SILValue Value, unsigned SubElementNumber)
159
+ : Value(Value), SubElementNumber(SubElementNumber) {}
160
+
161
+ // / Deleted copy constructor. This is a move only type.
162
+ AvailableValue (const AvailableValue &) = delete ;
163
+
164
+ // / Deleted copy operator. This is a move only type.
165
+ AvailableValue &operator =(const AvailableValue &) = delete ;
166
+
167
+ // / Move constructor.
168
+ AvailableValue (AvailableValue &&Other)
169
+ : Value(nullptr ), SubElementNumber(~0 ) {
170
+ std::swap (Value, Other.Value );
171
+ std::swap (SubElementNumber, Other.SubElementNumber );
172
+ }
173
+
174
+ // / Move operator.
175
+ AvailableValue &operator =(AvailableValue &&Other) {
176
+ std::swap (Value, Other.Value );
177
+ std::swap (SubElementNumber, Other.SubElementNumber );
178
+ return *this ;
179
+ }
180
+
181
+ operator bool () const { return bool (Value); }
182
+
183
+ bool operator ==(const AvailableValue &Other) const {
184
+ return Value == Other.Value && SubElementNumber == Other.SubElementNumber ;
185
+ }
186
+
187
+ bool operator !=(const AvailableValue &Other) const {
188
+ return !(*this == Other);
189
+ }
190
+
191
+ SILValue getValue () const { return Value; }
192
+ SILType getType () const { return Value->getType (); }
193
+ unsigned getSubElementNumber () const { return SubElementNumber; }
194
+
195
+ // / TODO: This needs a better name.
196
+ AvailableValue emitStructExtract (SILBuilder &B, SILLocation Loc, VarDecl *D,
197
+ unsigned SubEltNumber) const {
198
+ SILValue NewValue = B.emitStructExtract (Loc, Value, D);
199
+ return {NewValue, SubEltNumber};
200
+ }
201
+
202
+ // / TODO: This needs a better name.
203
+ AvailableValue emitTupleExtract (SILBuilder &B, SILLocation Loc,
204
+ unsigned EltNo, unsigned SubEltNumber) const {
205
+ SILValue NewValue = B.emitTupleExtract (Loc, Value, EltNo);
206
+ return {NewValue, SubEltNumber};
207
+ }
208
+ };
209
+
210
+ } // end anonymous namespace
211
+
145
212
// ===----------------------------------------------------------------------===//
146
213
// Subelement Extraction
147
214
// ===----------------------------------------------------------------------===//
148
215
149
216
// / Given an aggregate value and an access path, non-destructively extract the
150
217
// / value indicated by the path.
151
- static SILValue nonDestructivelyExtractSubElement (SILValue Val,
152
- unsigned SubElementNumber,
218
+ static SILValue nonDestructivelyExtractSubElement (const AvailableValue &Val,
153
219
SILBuilder &B,
154
220
SILLocation Loc) {
155
- SILType ValTy = Val->getType ();
156
-
221
+ SILType ValTy = Val.getType ();
222
+ unsigned SubElementNumber = Val.SubElementNumber ;
223
+
157
224
// Extract tuple elements.
158
225
if (auto TT = ValTy.getAs <TupleType>()) {
159
226
for (unsigned EltNo : indices (TT.getElementTypes ())) {
160
227
// Keep track of what subelement is being referenced.
161
228
SILType EltTy = ValTy.getTupleElementType (EltNo);
162
229
unsigned NumSubElt = getNumSubElements (EltTy, B.getModule ());
163
230
if (SubElementNumber < NumSubElt) {
164
- Val = B .emitTupleExtract (Loc, Val , EltNo, EltTy );
165
- return nonDestructivelyExtractSubElement (Val, SubElementNumber , B, Loc);
231
+ auto NewVal = Val .emitTupleExtract (B, Loc , EltNo, SubElementNumber );
232
+ return nonDestructivelyExtractSubElement (NewVal , B, Loc);
166
233
}
167
234
168
235
SubElementNumber -= NumSubElt;
@@ -178,8 +245,8 @@ static SILValue nonDestructivelyExtractSubElement(SILValue Val,
178
245
unsigned NumSubElt = getNumSubElements (fieldType, B.getModule ());
179
246
180
247
if (SubElementNumber < NumSubElt) {
181
- Val = B .emitStructExtract (Loc, Val , D);
182
- return nonDestructivelyExtractSubElement (Val, SubElementNumber , B, Loc);
248
+ auto NewVal = Val .emitStructExtract (B, Loc , D, SubElementNumber );
249
+ return nonDestructivelyExtractSubElement (NewVal , B, Loc);
183
250
}
184
251
185
252
SubElementNumber -= NumSubElt;
@@ -190,24 +257,17 @@ static SILValue nonDestructivelyExtractSubElement(SILValue Val,
190
257
191
258
// Otherwise, we're down to a scalar.
192
259
assert (SubElementNumber == 0 && " Miscalculation indexing subelements" );
193
- return Val;
260
+ return Val. getValue () ;
194
261
}
195
262
196
263
// ===----------------------------------------------------------------------===//
197
264
// Available Value Aggregation
198
265
// ===----------------------------------------------------------------------===//
199
266
200
- namespace {
201
-
202
- // / Our available value representation. Will become a struct later.
203
- using AvailableValue = std::pair<SILValue, unsigned >;
204
-
205
- } // end anonymous namespace
206
-
207
267
static bool anyMissing (unsigned StartSubElt, unsigned NumSubElts,
208
268
ArrayRef<AvailableValue> &Values) {
209
269
while (NumSubElts) {
210
- if (!Values[StartSubElt]. first )
270
+ if (!Values[StartSubElt])
211
271
return true ;
212
272
++StartSubElt;
213
273
--NumSubElts;
@@ -240,6 +300,9 @@ class AvailableValueAggregator {
240
300
241
301
SILValue aggregateValues (SILType LoadTy, SILValue Address, unsigned FirstElt);
242
302
303
+ void print (llvm::raw_ostream &os) const ;
304
+ void dump () const ;
305
+
243
306
private:
244
307
SILValue aggregateFullyAvailableValue (SILType LoadTy, unsigned FirstElt);
245
308
SILValue aggregateTupleSubElts (TupleType *TT, SILType LoadTy,
@@ -252,6 +315,17 @@ class AvailableValueAggregator {
252
315
253
316
} // end anonymous namespace
254
317
318
+ void AvailableValueAggregator::dump () const { print (llvm::dbgs ()); }
319
+
320
+ void AvailableValueAggregator::print (llvm::raw_ostream &os) const {
321
+ os << " Available Value List, N = " << AvailableValueList.size ()
322
+ << " . Elts:\n " ;
323
+ for (auto &V : AvailableValueList) {
324
+ os << " Value: " << V.getValue ()
325
+ << " SubElementNumber: " << V.getSubElementNumber () << " \n " ;
326
+ }
327
+ }
328
+
255
329
// / Given a bunch of primitive subelement values, build out the right aggregate
256
330
// / type (LoadTy) by emitting tuple and struct instructions as necessary.
257
331
SILValue AvailableValueAggregator::aggregateValues (SILType LoadTy,
@@ -287,23 +361,23 @@ AvailableValueAggregator::aggregateFullyAvailableValue(SILType LoadTy,
287
361
return SILValue ();
288
362
}
289
363
290
- SILValue FirstVal = AvailableValueList[FirstElt]. first ;
291
- // Make sure that the first element is available.
292
- if (!FirstVal || AvailableValueList[FirstElt]. second != 0 ||
293
- FirstVal-> getType () != LoadTy) {
364
+ auto & FirstVal = AvailableValueList[FirstElt];
365
+
366
+ // Make sure that the first element is available and is the correct type.
367
+ if (!FirstVal || FirstVal. getType () != LoadTy)
294
368
return SILValue ();
295
- }
296
369
297
370
// If the first element of this value is available, check that any extra
298
- // available values match our first value.
299
- if (llvm::any_of (
300
- range (getNumSubElements (LoadTy, M)), [&](unsigned Index) -> bool {
301
- return AvailableValueList[FirstElt + Index].first != FirstVal ||
302
- AvailableValueList[FirstElt + Index].second != Index;
303
- }))
371
+ // available values are from the same place as our first value.
372
+ if (llvm::any_of (range (getNumSubElements (LoadTy, M)),
373
+ [&](unsigned Index) -> bool {
374
+ auto &Val = AvailableValueList[FirstElt + Index];
375
+ return Val.getValue () != FirstVal.getValue () ||
376
+ Val.getSubElementNumber () != Index;
377
+ }))
304
378
return SILValue ();
305
379
306
- return FirstVal;
380
+ return FirstVal. getValue () ;
307
381
}
308
382
309
383
SILValue AvailableValueAggregator::aggregateTupleSubElts (TupleType *TT,
@@ -362,7 +436,7 @@ SILValue AvailableValueAggregator::handlePrimitiveValue(SILType LoadTy,
362
436
auto &Val = AvailableValueList[FirstElt];
363
437
364
438
// If the value is not available, load the value.
365
- if (!Val. first ) {
439
+ if (!Val) {
366
440
return B.createLoad (Loc, Address, LoadOwnershipQualifier::Unqualified);
367
441
}
368
442
@@ -371,12 +445,9 @@ SILValue AvailableValueAggregator::handlePrimitiveValue(SILType LoadTy,
371
445
// insert a copy of EltVal after we extract it if we do not have a trivial
372
446
// value. We use SILBuilder::emit*Operation to handle both trivial/non-trivial
373
447
// cases without needing to introduce control flow here.
374
- SILValue Aggregate = Val.first ;
375
- unsigned AggregateSubElementNumber = Val.second ;
376
448
377
449
// Then extract the subelement from the borrowed aggregate.
378
- SILValue EltVal = nonDestructivelyExtractSubElement (
379
- Aggregate, AggregateSubElementNumber, B, Loc);
450
+ SILValue EltVal = nonDestructivelyExtractSubElement (Val, B, Loc);
380
451
assert (EltVal->getType () == LoadTy && " Subelement types mismatch" );
381
452
return EltVal;
382
453
}
@@ -517,11 +588,11 @@ void AllocOptimize::updateAvailableValues(
517
588
SmallVectorImpl<AvailableValue> &Result,
518
589
llvm::SmallBitVector &ConflictingValues) {
519
590
// Handle store and assign.
520
- if (isa <StoreInst>(Inst)) {
521
- unsigned StartSubElt = computeSubelement (Inst-> getOperand ( 1 ), TheMemory);
591
+ if (auto *SI = dyn_cast <StoreInst>(Inst)) {
592
+ unsigned StartSubElt = computeSubelement (SI-> getDest ( ), TheMemory);
522
593
assert (StartSubElt != ~0U && " Store within enum projection not handled" );
523
- SILType ValTy = Inst-> getOperand ( 0 )->getType ();
524
-
594
+ SILType ValTy = SI-> getSrc ( )->getType ();
595
+
525
596
for (unsigned i = 0 , e = getNumSubElements (ValTy, Module); i != e; ++i) {
526
597
// If this element is not required, don't fill it in.
527
598
if (!RequiredElts[StartSubElt+i]) continue ;
@@ -530,9 +601,10 @@ void AllocOptimize::updateAvailableValues(
530
601
// there already is a result, check it for conflict. If there is no
531
602
// conflict, then we're ok.
532
603
auto &Entry = Result[StartSubElt+i];
533
- if (Entry.first == SILValue ())
534
- Entry = { Inst->getOperand (0 ), i };
535
- else if (Entry.first != Inst->getOperand (0 ) || Entry.second != i)
604
+ if (!Entry)
605
+ Entry = {SI->getSrc (), i};
606
+ else if (Entry.getValue () != SI->getSrc () ||
607
+ Entry.getSubElementNumber () != i)
536
608
ConflictingValues[StartSubElt+i] = true ;
537
609
538
610
// This element is now provided.
@@ -760,7 +832,7 @@ bool AllocOptimize::promoteLoad(SILInstruction *Inst) {
760
832
// promote this load and there is nothing to do.
761
833
bool AnyAvailable = false ;
762
834
for (unsigned i = FirstElt, e = i+NumLoadSubElements; i != e; ++i)
763
- if (AvailableValues[i].first ) {
835
+ if (AvailableValues[i].getValue () ) {
764
836
AnyAvailable = true ;
765
837
break ;
766
838
}
@@ -838,11 +910,11 @@ bool AllocOptimize::promoteDestroyAddr(DestroyAddrInst *DAI) {
838
910
// trivially succeed. This can happen when there is a load of an empty struct.
839
911
if (NumLoadSubElements != 0 ) {
840
912
computeAvailableValues (DAI, RequiredElts, AvailableValues);
841
-
913
+
842
914
// If some value is not available at this load point, then we fail.
843
- for ( unsigned i = FirstElt, e = FirstElt+NumLoadSubElements; i != e; ++i)
844
- if ( !AvailableValues[i]. first )
845
- return false ;
915
+ if ( llvm::any_of ( range ( FirstElt, FirstElt + NumLoadSubElements),
916
+ [&]( unsigned i) -> bool { return !AvailableValues[i]; }) )
917
+ return false ;
846
918
}
847
919
848
920
// Aggregate together all of the subelements into something that has the same
0 commit comments