[llvm] 8af5ec6 - [AutoUpgrade] Upgrade old-style !tbaa.struct field tags (#225967)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 14:15:35 PDT 2026


Author: Abhay Kanhere
Date: 2026-09-25T14:15:28-07:00
New Revision: 8af5ec67c2001eb379d53cc61ccce0ca521a6c3c

URL: https://github.com/llvm/llvm-project/commit/8af5ec67c2001eb379d53cc61ccce0ca521a6c3c
DIFF: https://github.com/llvm/llvm-project/commit/8af5ec67c2001eb379d53cc61ccce0ca521a6c3c.diff

LOG: [AutoUpgrade] Upgrade old-style !tbaa.struct field tags (#225967)

Extend the TBAA auto-upgrade to rewrite old-style scalar field tags
inside !tbaa.struct
to the struct-path aware format. bitcode (MetadataLoader) upgraded to
match the existing top-level !tbaa upgrade.

Added: 
    llvm/test/Bitcode/upgrade-tbaa-struct.ll
    llvm/test/Bitcode/upgrade-tbaa-struct.ll.bc

Modified: 
    llvm/include/llvm/IR/AutoUpgrade.h
    llvm/lib/Bitcode/Reader/MetadataLoader.cpp
    llvm/lib/IR/AutoUpgrade.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/AutoUpgrade.h b/llvm/include/llvm/IR/AutoUpgrade.h
index 53da20d63a7f1..b129994885b2d 100644
--- a/llvm/include/llvm/IR/AutoUpgrade.h
+++ b/llvm/include/llvm/IR/AutoUpgrade.h
@@ -85,6 +85,11 @@ namespace llvm {
   /// Otherwise return the \p TBAANode itself.
   LLVM_ABI MDNode *UpgradeTBAANode(MDNode &TBAANode);
 
+  /// If the given !tbaa.struct node has old-style scalar field tags, return an
+  /// equivalent node with each field tag upgraded to the struct-path aware
+  /// format. Otherwise return the node itself.
+  LLVM_ABI MDNode *UpgradeTBAAStructNode(MDNode &TBAAStructNode);
+
   /// This is an auto-upgrade for bitcast between pointers with 
diff erent
   /// address spaces: the instruction is replaced by a pair ptrtoint+inttoptr.
   LLVM_ABI Instruction *UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy,

diff  --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 6f1fbd627edbc..80e44634d6f95 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -2647,6 +2647,9 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataAttachment(
         if (I->second == LLVMContext::MD_tbaa) {
           assert(!MD->isTemporary() && "should load MDs before attachments");
           MD = UpgradeTBAANode(*MD);
+        } else if (I->second == LLVMContext::MD_tbaa_struct) {
+          assert(!MD->isTemporary() && "should load MDs before attachments");
+          MD = UpgradeTBAAStructNode(*MD);
         }
         Inst->setMetadata(I->second, MD);
       }

diff  --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index cb0e0690a261f..42f456e82f387 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -6670,6 +6670,28 @@ MDNode *llvm::UpgradeTBAANode(MDNode &MD) {
   return MDNode::get(Context, Elts);
 }
 
+MDNode *llvm::UpgradeTBAAStructNode(MDNode &MD) {
+  // !tbaa.struct is a list of (offset, size, tag) triples. Upgrade any
+  // old-style scalar field tag to struct-path form via UpgradeTBAANode.
+  unsigned NumOperands = MD.getNumOperands();
+  if (NumOperands == 0 || NumOperands % 3 != 0)
+    return &MD; // Malformed; leave it for the verifier to reject.
+
+  SmallVector<Metadata *, 12> Elts(MD.op_begin(), MD.op_end());
+  bool Changed = false;
+  for (unsigned I = 2; I < NumOperands; I += 3) {
+    auto *Tag = dyn_cast_or_null<MDNode>(Elts[I]);
+    if (!Tag)
+      continue;
+    MDNode *Upgraded = UpgradeTBAANode(*Tag);
+    if (Upgraded == Tag)
+      continue;
+    Elts[I] = Upgraded;
+    Changed = true;
+  }
+  return Changed ? MDNode::get(MD.getContext(), Elts) : &MD;
+}
+
 Instruction *llvm::UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy,
                                       Instruction *&Temp) {
   if (Opc != Instruction::BitCast)

diff  --git a/llvm/test/Bitcode/upgrade-tbaa-struct.ll b/llvm/test/Bitcode/upgrade-tbaa-struct.ll
new file mode 100644
index 0000000000000..d3c71ab22a1e4
--- /dev/null
+++ b/llvm/test/Bitcode/upgrade-tbaa-struct.ll
@@ -0,0 +1,68 @@
+; RUN: llvm-dis < %s.bc | FileCheck %s
+; RUN: verify-uselistorder < %s.bc
+; Test that old-style scalar tags used as !tbaa.struct field tags in older
+; bitcode are auto-upgraded to the struct-path aware format on load, whatever
+; instruction carries the !tbaa.struct. Null and already struct-path field
+; tags are left unchanged; an immutability flag is kept.
+;
+
+define void @copy_memcpy(ptr %a, ptr %b) {
+; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 12, i1 false), !tbaa.struct [[TS:![0-9]+]]
+  call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 12, i1 false), !tbaa.struct !0
+  ret void
+}
+
+define void @copy_memmove(ptr %a, ptr %b) {
+; CHECK: call void @llvm.memmove.p0.p0.i64(ptr %a, ptr %b, i64 12, i1 false), !tbaa.struct [[TS]]
+  call void @llvm.memmove.p0.p0.i64(ptr %a, ptr %b, i64 12, i1 false), !tbaa.struct !0
+  ret void
+}
+
+define i32 @access_load_store(ptr %p) {
+; CHECK: %v = load i32, ptr %p, align 4, !tbaa.struct [[TS]]
+; CHECK: store i32 %v, ptr %p, align 4, !tbaa.struct [[TS]]
+  %v = load i32, ptr %p, align 4, !tbaa.struct !0
+  store i32 %v, ptr %p, align 4, !tbaa.struct !0
+  ret i32 %v
+}
+
+define i32 @access_atomicrmw(ptr %p, i32 %v) {
+; CHECK: %r = atomicrmw add ptr %p, i32 %v seq_cst, align 4, !tbaa.struct [[TS]]
+  %r = atomicrmw add ptr %p, i32 %v seq_cst, align 4, !tbaa.struct !0
+  ret i32 %r
+}
+
+define void @copy_flag_and_structpath(ptr %a, ptr %b) {
+; CHECK: call void @llvm.memmove.p0.p0.i64(ptr %a, ptr %b, i64 8, i1 false), !tbaa.struct [[TS2:![0-9]+]]
+  call void @llvm.memmove.p0.p0.i64(ptr %a, ptr %b, i64 8, i1 false), !tbaa.struct !5
+  ret void
+}
+
+declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
+declare void @llvm.memmove.p0.p0.i64(ptr, ptr, i64, i1)
+
+; Old-style 2-operand scalar field tags and a null field tag.
+!0 = !{i64 0, i64 4, !1, i64 4, i64 4, !3, i64 8, i64 4, null}
+!1 = !{!"int", !2}
+!2 = !{!"omnipotent char", !4}
+!3 = !{!"float", !2}
+!4 = !{!"Simple C/C++ TBAA"}
+
+; Old-style 3-operand (immutable) field tag and an already struct-path field tag.
+!5 = !{i64 0, i64 4, !6, i64 4, i64 4, !7}
+!6 = !{!"const int", !2, i64 1}
+!7 = !{!8, !8, i64 0}
+!8 = !{!"double", !2}
+
+; CHECK: [[TS]] = !{i64 0, i64 4, [[TAG_INT:![0-9]+]], i64 4, i64 4, [[TAG_FLOAT:![0-9]+]], i64 8, i64 4, null}
+; CHECK: [[TAG_INT]] = !{[[TYPE_INT:![0-9]+]], [[TYPE_INT]], i64 0}
+; CHECK: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR:![0-9]+]]}
+; CHECK: [[TYPE_CHAR]] = !{!"omnipotent char", !{{[0-9]+}}}
+; CHECK: [[TAG_FLOAT]] = !{[[TYPE_FLOAT:![0-9]+]], [[TYPE_FLOAT]], i64 0}
+; CHECK: [[TYPE_FLOAT]] = !{!"float", [[TYPE_CHAR]]}
+; The immutability flag (i64 1) is preserved; the already struct-path tag is unchanged.
+; CHECK: [[TS2]] = !{i64 0, i64 4, [[TAG_CONST:![0-9]+]], i64 4, i64 4, [[TAG_DOUBLE:![0-9]+]]}
+; CHECK: [[TAG_CONST]] = !{[[TYPE_CONST:![0-9]+]], [[TYPE_CONST]], i64 0, i64 1}
+; CHECK: [[TYPE_CONST]] = !{!"const int", [[TYPE_CHAR]]}
+; CHECK: [[TAG_DOUBLE]] = !{[[TYPE_DOUBLE:![0-9]+]], [[TYPE_DOUBLE]], i64 0}
+; CHECK: [[TYPE_DOUBLE]] = !{!"double", [[TYPE_CHAR]]}

diff  --git a/llvm/test/Bitcode/upgrade-tbaa-struct.ll.bc b/llvm/test/Bitcode/upgrade-tbaa-struct.ll.bc
new file mode 100644
index 0000000000000..0b85cec94aa1b
Binary files /dev/null and b/llvm/test/Bitcode/upgrade-tbaa-struct.ll.bc 
diff er


        


More information about the llvm-commits mailing list