121
121
#include " llvm/Support/ErrorHandling.h"
122
122
#include < cassert>
123
123
#include < cstdint>
124
+ #include < stack>
124
125
125
126
using namespace llvm ;
126
127
@@ -299,21 +300,22 @@ class TBAAStructTypeNode {
299
300
return TBAAStructTypeNode (TypeNode);
300
301
}
301
302
302
- // / Get this TBAAStructTypeNode's field in the type DAG with
303
+ // / Get this TBAAStructTypeNode's fields in the type DAG with
303
304
// / given offset. Update the offset to be relative to the field type.
304
- TBAAStructTypeNode getField (uint64_t &Offset) const {
305
+ // / There could be multiple fields with same offset.
306
+ std::vector<TBAAStructTypeNode> getField (uint64_t &Offset) const {
305
307
bool NewFormat = isNewFormat ();
306
308
const ArrayRef<MDOperand> Operands = Node->operands ();
307
309
const unsigned NumOperands = Operands.size ();
308
310
309
311
if (NewFormat) {
310
312
// New-format root and scalar type nodes have no fields.
311
313
if (NumOperands < 6 )
312
- return TBAAStructTypeNode ();
314
+ return { TBAAStructTypeNode ()} ;
313
315
} else {
314
316
// Parent can be omitted for the root node.
315
317
if (NumOperands < 2 )
316
- return TBAAStructTypeNode ();
318
+ return { TBAAStructTypeNode ()} ;
317
319
318
320
// Fast path for a scalar type node and a struct type node with a single
319
321
// field.
@@ -325,8 +327,8 @@ class TBAAStructTypeNode {
325
327
Offset -= Cur;
326
328
MDNode *P = dyn_cast_or_null<MDNode>(Operands[1 ]);
327
329
if (!P)
328
- return TBAAStructTypeNode ();
329
- return TBAAStructTypeNode (P);
330
+ return { TBAAStructTypeNode ()} ;
331
+ return { TBAAStructTypeNode (P)} ;
330
332
}
331
333
}
332
334
@@ -336,6 +338,8 @@ class TBAAStructTypeNode {
336
338
unsigned NumOpsPerField = NewFormat ? 3 : 2 ;
337
339
unsigned TheIdx = 0 ;
338
340
341
+ std::vector<TBAAStructTypeNode> Ret;
342
+
339
343
for (unsigned Idx = FirstFieldOpNo; Idx < NumOperands;
340
344
Idx += NumOpsPerField) {
341
345
uint64_t Cur =
@@ -353,10 +357,20 @@ class TBAAStructTypeNode {
353
357
uint64_t Cur =
354
358
mdconst::extract<ConstantInt>(Operands[TheIdx + 1 ])->getZExtValue ();
355
359
Offset -= Cur;
360
+
361
+ // Collect all fields that have right offset.
356
362
MDNode *P = dyn_cast_or_null<MDNode>(Operands[TheIdx]);
357
- if (!P)
358
- return TBAAStructTypeNode ();
359
- return TBAAStructTypeNode (P);
363
+ Ret.emplace_back (P ? TBAAStructTypeNode (P) : TBAAStructTypeNode ());
364
+
365
+ while (TheIdx > FirstFieldOpNo) {
366
+ TheIdx -= NumOpsPerField;
367
+ auto Val = mdconst::extract<ConstantInt>(Operands[TheIdx + 1 ]);
368
+ if (Cur != Val->getZExtValue ())
369
+ break ;
370
+ MDNode *P = dyn_cast_or_null<MDNode>(Operands[TheIdx]);
371
+ P ? Ret.emplace_back (P) : Ret.emplace_back ();
372
+ }
373
+ return Ret;
360
374
}
361
375
};
362
376
@@ -572,6 +586,39 @@ static bool hasField(TBAAStructTypeNode BaseType,
572
586
return false ;
573
587
}
574
588
589
+ static bool rangeOverlap (std::pair<size_t , size_t > Range1,
590
+ std::pair<size_t , size_t > Range2) {
591
+ return Range1.first < Range2.first + Range2.second &&
592
+ Range1.first + Range1.second > Range2.first ;
593
+ }
594
+
595
+ // / Return true if two accessess to given \p BaseType at \p Offset1 and
596
+ // / at \p Offset2 may alias. This check does not account for NewStructType
597
+ // / parameters such as size and may be more conservative.
598
+ static bool mayFieldAccessesAlias (TBAAStructTypeNode BaseType, uint64_t Offset1,
599
+ uint64_t Offset2) {
600
+ if (!BaseType.getNode ())
601
+ return true ;
602
+
603
+ auto PrevDiff = (long long )(Offset1) - (long long )(Offset2);
604
+ auto Fields1 = BaseType.getField (Offset1);
605
+ auto Fields2 = BaseType.getField (Offset2);
606
+ auto CurrentDiff = (long long )(Offset1) - (long long )(Offset2);
607
+
608
+ // If distance between offsets is not same that mean accesses are
609
+ // to different fields.
610
+ if (PrevDiff != CurrentDiff)
611
+ return false ;
612
+
613
+ // Fields that share same offset may have various internal structure. For
614
+ // some of them - same field may be accessed while for others - different
615
+ // ones. To be conservative we report MayAlias if any of fields report
616
+ // MayAlias.
617
+ return llvm::any_of (Fields1, [&](auto &FieldType) {
618
+ return mayFieldAccessesAlias (FieldType, Offset1, Offset2);
619
+ });
620
+ }
621
+
575
622
// / Return true if for two given accesses, one of the accessed objects may be a
576
623
// / subobject of the other. The \p BaseTag and \p SubobjectTag parameters
577
624
// / describe the accesses to the base object and the subobject respectively.
@@ -599,20 +646,38 @@ static bool mayBeAccessToSubobjectOf(TBAAStructTagNode BaseTag,
599
646
// from the base type, follow the edge with the correct offset in the type DAG
600
647
// and adjust the offset until we reach the field type or until we reach the
601
648
// access type.
649
+ // If multiple fields have same offset in some base type, then scan each such
650
+ // field.
602
651
bool NewFormat = BaseTag.isNewFormat ();
603
652
TBAAStructTypeNode BaseType (BaseTag.getBaseType ());
604
653
uint64_t OffsetInBase = BaseTag.getOffset ();
605
654
606
- for (;;) {
607
- // In the old format there is no distinction between fields and parent
608
- // types, so in this case we consider all nodes up to the root.
609
- if (!BaseType.getNode ()) {
610
- assert (!NewFormat && " Did not see access type in access path!" );
611
- break ;
612
- }
655
+ SmallVector<std::pair<TBAAStructTypeNode, uint64_t >, 4 > ToCheck;
656
+ ToCheck.emplace_back (BaseType, OffsetInBase);
657
+ while (!ToCheck.empty ()) {
658
+ std::tie (BaseType, OffsetInBase) = ToCheck.back ();
659
+ ToCheck.pop_back ();
660
+
661
+ // In case if root is reached, still check the remaining candidates.
662
+ // For new format it is always expected for access type to be found.
663
+ // For old format all nodes up to the root are considered from all
664
+ // candidates.
665
+ if (!BaseType.getNode ())
666
+ continue ;
613
667
614
668
if (BaseType.getNode () == SubobjectTag.getBaseType ()) {
615
- bool SameMemberAccess = OffsetInBase == SubobjectTag.getOffset ();
669
+ bool SameMemberAccess;
670
+ uint64_t SubobjectOffset = SubobjectTag.getOffset ();
671
+ if (NewFormat)
672
+ // If size information is available, check if their access locations
673
+ // overlap.
674
+ SameMemberAccess = rangeOverlap (
675
+ std::make_pair (OffsetInBase, BaseTag.getSize ()),
676
+ std::make_pair (SubobjectOffset, SubobjectTag.getSize ()));
677
+ else
678
+ // Else do a more conservative check.
679
+ SameMemberAccess =
680
+ mayFieldAccessesAlias (BaseType, OffsetInBase, SubobjectOffset);
616
681
if (GenericTag) {
617
682
*GenericTag = SameMemberAccess ? SubobjectTag.getNode () :
618
683
createAccessTag (CommonType);
@@ -627,13 +692,15 @@ static bool mayBeAccessToSubobjectOf(TBAAStructTagNode BaseTag,
627
692
628
693
// Follow the edge with the correct offset. Offset will be adjusted to
629
694
// be relative to the field type.
630
- BaseType = BaseType.getField (OffsetInBase);
695
+ for (auto &&F : BaseType.getField (OffsetInBase))
696
+ ToCheck.emplace_back (F, OffsetInBase);
631
697
}
632
698
633
699
// If the base object has a direct or indirect field of the subobject's type,
634
700
// then this may be an access to that field. We need this to check now that
635
701
// we support aggregates as access types.
636
702
if (NewFormat) {
703
+ assert (BaseType.getNode () && " Did not see access type in access path!" );
637
704
// TBAAStructTypeNode BaseAccessType(BaseTag.getAccessType());
638
705
TBAAStructTypeNode FieldType (SubobjectTag.getBaseType ());
639
706
if (hasField (BaseType, FieldType)) {
0 commit comments