@@ -335,6 +335,16 @@ struct FrameDataInfo {
335
335
" Cannot set the index for the same field twice." );
336
336
FieldIndexMap[V] = Index;
337
337
}
338
+ uint64_t getAlign (Value *V) const {
339
+ auto Iter = FieldAlignMap.find (V);
340
+ assert (Iter != FieldAlignMap.end ());
341
+ return Iter->second ;
342
+ }
343
+
344
+ void setAlign (Value *V, uint64_t Align) {
345
+ assert (FieldAlignMap.count (V) == 0 );
346
+ FieldAlignMap.insert ({V, Align});
347
+ }
338
348
339
349
// Remap the index of every field in the frame, using the final layout index.
340
350
void updateLayoutIndex (FrameTypeBuilder &B);
@@ -347,6 +357,9 @@ struct FrameDataInfo {
347
357
// with their original insertion field index. After the frame is built, their
348
358
// indexes will be updated into the final layout index.
349
359
DenseMap<Value *, uint32_t > FieldIndexMap;
360
+ // Map from values to their alignment on the frame. They would be set after
361
+ // the frame is built.
362
+ DenseMap<Value *, uint64_t > FieldAlignMap;
350
363
};
351
364
} // namespace
352
365
@@ -392,12 +405,15 @@ class FrameTypeBuilder {
392
405
Align StructAlign;
393
406
bool IsFinished = false ;
394
407
408
+ Optional<Align> MaxFrameAlignment;
409
+
395
410
SmallVector<Field, 8 > Fields;
396
411
DenseMap<Value*, unsigned > FieldIndexByKey;
397
412
398
413
public:
399
- FrameTypeBuilder (LLVMContext &Context, DataLayout const &DL)
400
- : DL(DL), Context(Context) {}
414
+ FrameTypeBuilder (LLVMContext &Context, DataLayout const &DL,
415
+ Optional<Align> MaxFrameAlignment)
416
+ : DL(DL), Context(Context), MaxFrameAlignment(MaxFrameAlignment) {}
401
417
402
418
// / Add a field to this structure for the storage of an `alloca`
403
419
// / instruction.
@@ -448,7 +464,8 @@ class FrameTypeBuilder {
448
464
449
465
// / Add a field to this structure.
450
466
LLVM_NODISCARD FieldIDType addField (Type *Ty, MaybeAlign FieldAlignment,
451
- bool IsHeader = false ) {
467
+ bool IsHeader = false ,
468
+ bool IsSpillOfValue = false ) {
452
469
assert (!IsFinished && " adding fields to a finished builder" );
453
470
assert (Ty && " must provide a type for a field" );
454
471
@@ -457,8 +474,16 @@ class FrameTypeBuilder {
457
474
458
475
// The field alignment might not be the type alignment, but we need
459
476
// to remember the type alignment anyway to build the type.
460
- Align TyAlignment = DL.getABITypeAlign (Ty);
461
- if (!FieldAlignment) FieldAlignment = TyAlignment;
477
+ // If we are spilling values we don't need to worry about ABI alignment
478
+ // concerns.
479
+ auto ABIAlign = DL.getABITypeAlign (Ty);
480
+ Align TyAlignment =
481
+ (IsSpillOfValue && MaxFrameAlignment)
482
+ ? (*MaxFrameAlignment < ABIAlign ? *MaxFrameAlignment : ABIAlign)
483
+ : ABIAlign;
484
+ if (!FieldAlignment) {
485
+ FieldAlignment = TyAlignment;
486
+ }
462
487
463
488
// Lay out header fields immediately.
464
489
uint64_t Offset;
@@ -492,12 +517,18 @@ class FrameTypeBuilder {
492
517
assert (IsFinished && " not yet finished!" );
493
518
return Fields[Id].LayoutFieldIndex ;
494
519
}
520
+ Field getLayoutField (FieldIDType Id) const {
521
+ assert (IsFinished && " not yet finished!" );
522
+ return Fields[Id];
523
+ }
495
524
};
496
525
} // namespace
497
526
498
527
void FrameDataInfo::updateLayoutIndex (FrameTypeBuilder &B) {
499
528
auto Updater = [&](Value *I) {
500
- setFieldIndex (I, B.getLayoutFieldIndex (getFieldIndex (I)));
529
+ auto Field = B.getLayoutField (getFieldIndex (I));
530
+ setFieldIndex (I, Field.LayoutFieldIndex );
531
+ setAlign (I, Field.Alignment .value ());
501
532
};
502
533
LayoutIndexUpdateStarted = true ;
503
534
for (auto &S : Spills)
@@ -722,7 +753,11 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
722
753
return StructType::create (C, Name);
723
754
}();
724
755
725
- FrameTypeBuilder B (C, DL);
756
+ // We will use this value to cap the alignment of spilled values.
757
+ Optional<Align> MaxFrameAlignment;
758
+ if (Shape.ABI == coro::ABI::Async)
759
+ MaxFrameAlignment = Shape.AsyncLowering .getContextAlignment ();
760
+ FrameTypeBuilder B (C, DL, MaxFrameAlignment);
726
761
727
762
AllocaInst *PromiseAlloca = Shape.getPromiseAlloca ();
728
763
Optional<FieldIDType> SwitchIndexFieldId;
@@ -760,7 +795,8 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
760
795
B.addFieldForAllocas (F, FrameData, Shape);
761
796
// Create an entry for every spilled value.
762
797
for (auto &S : FrameData.Spills ) {
763
- FieldIDType Id = B.addField (S.first ->getType (), None);
798
+ FieldIDType Id = B.addField (S.first ->getType (), None, false /* header*/ ,
799
+ true /* IsSpillOfValue*/ );
764
800
FrameData.setFieldIndex (S.first , Id);
765
801
}
766
802
@@ -1122,6 +1158,7 @@ static Instruction *insertSpills(const FrameDataInfo &FrameData,
1122
1158
1123
1159
for (auto const &E : FrameData.Spills ) {
1124
1160
Value *Def = E.first ;
1161
+ auto SpillAlignment = Align (FrameData.getAlign (Def));
1125
1162
// Create a store instruction storing the value into the
1126
1163
// coroutine frame.
1127
1164
Instruction *InsertPt = nullptr ;
@@ -1169,7 +1206,7 @@ static Instruction *insertSpills(const FrameDataInfo &FrameData,
1169
1206
Builder.SetInsertPoint (InsertPt);
1170
1207
auto *G = Builder.CreateConstInBoundsGEP2_32 (
1171
1208
FrameTy, FramePtr, 0 , Index, Def->getName () + Twine (" .spill.addr" ));
1172
- Builder.CreateStore (Def, G);
1209
+ Builder.CreateAlignedStore (Def, G, SpillAlignment );
1173
1210
1174
1211
BasicBlock *CurrentBlock = nullptr ;
1175
1212
Value *CurrentReload = nullptr ;
@@ -1183,9 +1220,9 @@ static Instruction *insertSpills(const FrameDataInfo &FrameData,
1183
1220
1184
1221
auto *GEP = GetFramePointer (E.first );
1185
1222
GEP->setName (E.first ->getName () + Twine (" .reload.addr" ));
1186
- CurrentReload = Builder.CreateLoad (
1223
+ CurrentReload = Builder.CreateAlignedLoad (
1187
1224
FrameTy->getElementType (FrameData.getFieldIndex (E.first )), GEP,
1188
- E.first ->getName () + Twine (" .reload" ));
1225
+ SpillAlignment, E.first ->getName () + Twine (" .reload" ));
1189
1226
1190
1227
TinyPtrVector<DbgDeclareInst *> DIs = FindDbgDeclareUses (Def);
1191
1228
for (DbgDeclareInst *DDI : DIs) {
0 commit comments