[llvm] [TBAA] Recover !tbaa for a memcpy of struct with same type fields (PR #214116)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 17 13:55:56 PDT 2026


================
@@ -810,16 +823,30 @@ MDNode *AAMDNodes::extendToTBAA(MDNode *MD, ssize_t Len) {
 AAMDNodes AAMDNodes::adjustForAccess(unsigned AccessSize) {
   AAMDNodes New = *this;
   MDNode *M = New.TBAAStruct;
-  if (!New.TBAA && M && M->getNumOperands() >= 3 && M->getOperand(0) &&
-      mdconst::hasa<ConstantInt>(M->getOperand(0)) &&
-      mdconst::extract<ConstantInt>(M->getOperand(0))->isZero() &&
-      M->getOperand(1) && mdconst::hasa<ConstantInt>(M->getOperand(1)) &&
-      mdconst::extract<ConstantInt>(M->getOperand(1))->getValue() ==
-          AccessSize &&
-      M->getOperand(2) && isa<MDNode>(M->getOperand(2)))
-    New.TBAA = cast<MDNode>(M->getOperand(2));
 
+  // The access may cover several !tbaa.struct fields (e.g. a {int, int} copy
+  // widened to an i64 load/store). If those fields share a single tag and tile
+  // [0, AccessSize) with no gaps, that tag still describes the whole access.
   New.TBAAStruct = nullptr;
+  if (New.TBAA || !M)
+    return New;
+  MDNode *CommonTag = nullptr;
+  uint64_t Offset = 0;
+  for (size_t I = 0, E = M->getNumOperands(); I + 2 < E; I += 3) {
+    uint64_t FieldOffset, FieldSize;
+    MDNode *FieldTag = dyn_cast_or_null<MDNode>(M->getOperand(I + 2));
+    if (!getTBAAStructFieldAsInt64(M->getOperand(I), FieldOffset) ||
+        !getTBAAStructFieldAsInt64(M->getOperand(I + 1), FieldSize) ||
+        !FieldTag || !isWellFormedTBAAAccessTagShape(FieldTag) ||
+        FieldOffset != Offset || (CommonTag && FieldTag != CommonTag))
+      break;
+    CommonTag = FieldTag;
+    Offset += FieldSize;
+    if (Offset >= AccessSize)
+      break;
----------------
fhahn wrote:

We may  be able to fold this into the loop condiiton?

https://github.com/llvm/llvm-project/pull/214116


More information about the llvm-commits mailing list