121121#include " llvm/Support/ErrorHandling.h"
122122#include < cassert>
123123#include < cstdint>
124+ #include < stack>
124125
125126using namespace llvm ;
126127
@@ -299,21 +300,22 @@ class TBAAStructTypeNode {
299300 return TBAAStructTypeNode (TypeNode);
300301 }
301302
302- // / Get this TBAAStructTypeNode's field in the type DAG with
303+ // / Get this TBAAStructTypeNode's fields in the type DAG with
303304 // / 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 {
305307 bool NewFormat = isNewFormat ();
306308 const ArrayRef<MDOperand> Operands = Node->operands ();
307309 const unsigned NumOperands = Operands.size ();
308310
309311 if (NewFormat) {
310312 // New-format root and scalar type nodes have no fields.
311313 if (NumOperands < 6 )
312- return TBAAStructTypeNode ();
314+ return { TBAAStructTypeNode ()} ;
313315 } else {
314316 // Parent can be omitted for the root node.
315317 if (NumOperands < 2 )
316- return TBAAStructTypeNode ();
318+ return { TBAAStructTypeNode ()} ;
317319
318320 // Fast path for a scalar type node and a struct type node with a single
319321 // field.
@@ -325,8 +327,8 @@ class TBAAStructTypeNode {
325327 Offset -= Cur;
326328 MDNode *P = dyn_cast_or_null<MDNode>(Operands[1 ]);
327329 if (!P)
328- return TBAAStructTypeNode ();
329- return TBAAStructTypeNode (P);
330+ return { TBAAStructTypeNode ()} ;
331+ return { TBAAStructTypeNode (P)} ;
330332 }
331333 }
332334
@@ -336,6 +338,8 @@ class TBAAStructTypeNode {
336338 unsigned NumOpsPerField = NewFormat ? 3 : 2 ;
337339 unsigned TheIdx = 0 ;
338340
341+ std::vector<TBAAStructTypeNode> Ret;
342+
339343 for (unsigned Idx = FirstFieldOpNo; Idx < NumOperands;
340344 Idx += NumOpsPerField) {
341345 uint64_t Cur =
@@ -353,10 +357,20 @@ class TBAAStructTypeNode {
353357 uint64_t Cur =
354358 mdconst::extract<ConstantInt>(Operands[TheIdx + 1 ])->getZExtValue ();
355359 Offset -= Cur;
360+
361+ // Collect all fields that have right offset.
356362 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;
360374 }
361375};
362376
@@ -572,6 +586,39 @@ static bool hasField(TBAAStructTypeNode BaseType,
572586 return false ;
573587}
574588
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+
575622// / Return true if for two given accesses, one of the accessed objects may be a
576623// / subobject of the other. The \p BaseTag and \p SubobjectTag parameters
577624// / describe the accesses to the base object and the subobject respectively.
@@ -599,20 +646,38 @@ static bool mayBeAccessToSubobjectOf(TBAAStructTagNode BaseTag,
599646 // from the base type, follow the edge with the correct offset in the type DAG
600647 // and adjust the offset until we reach the field type or until we reach the
601648 // access type.
649+ // If multiple fields have same offset in some base type, then scan each such
650+ // field.
602651 bool NewFormat = BaseTag.isNewFormat ();
603652 TBAAStructTypeNode BaseType (BaseTag.getBaseType ());
604653 uint64_t OffsetInBase = BaseTag.getOffset ();
605654
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 ;
613667
614668 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);
616681 if (GenericTag) {
617682 *GenericTag = SameMemberAccess ? SubobjectTag.getNode () :
618683 createAccessTag (CommonType);
@@ -627,13 +692,15 @@ static bool mayBeAccessToSubobjectOf(TBAAStructTagNode BaseTag,
627692
628693 // Follow the edge with the correct offset. Offset will be adjusted to
629694 // be relative to the field type.
630- BaseType = BaseType.getField (OffsetInBase);
695+ for (auto &&F : BaseType.getField (OffsetInBase))
696+ ToCheck.emplace_back (F, OffsetInBase);
631697 }
632698
633699 // If the base object has a direct or indirect field of the subobject's type,
634700 // then this may be an access to that field. We need this to check now that
635701 // we support aggregates as access types.
636702 if (NewFormat) {
703+ assert (BaseType.getNode () && " Did not see access type in access path!" );
637704 // TBAAStructTypeNode BaseAccessType(BaseTag.getAccessType());
638705 TBAAStructTypeNode FieldType (SubobjectTag.getBaseType ());
639706 if (hasField (BaseType, FieldType)) {
0 commit comments