[clang] [TBAA] Emit distinct TBAA tags for pointers with different depths,types. (PR #76612)

Florian Hahn via cfe-commits cfe-commits at lists.llvm.org
Sat Dec 30 02:55:54 PST 2023


https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/76612

This patch extends Clang's TBAA generation code to emit distinct tags for incompatible pointer types.

Pointers with different element types are incompatible if the pointee types are also incompatible (modulo sugar/modifiers).

Express this in TBAA by generating different tags for pointers based on the pointer depth and pointee type. To get the TBAA tag for the pointee type it uses getTypeInfoHelper on the pointee type.

(Moved from https://reviews.llvm.org/D122573)

>From 18f45a0b989d90a0f649dcc7b00f05be58fbe0c9 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sat, 30 Dec 2023 10:39:58 +0000
Subject: [PATCH] [TBAA] Emit distinct TBAA tags for pointers with different
 depths,types.

This patch extends Clang's TBAA generation code to emit distinct tags
for incompatible pointer types.

Pointers with different element types are incompatible if the pointee
types are also incompatible (modulo sugar/modifiers).

Express this in TBAA by generating different tags for pointers based
on the pointer depth and pointee type. To get the TBAA tag for the
pointee type it uses getTypeInfoHelper on the pointee type.

(Moved from https://reviews.llvm.org/D122573)
---
 clang/lib/CodeGen/CodeGenTBAA.cpp  | 29 ++++++++++--
 clang/test/CodeGen/tbaa-pointers.c | 72 +++++++++++++++++-------------
 2 files changed, 67 insertions(+), 34 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index dc288bc3f6157a..b96f9d28c45530 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -184,10 +184,31 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
     return getChar();
 
   // Handle pointers and references.
-  // TODO: Implement C++'s type "similarity" and consider dis-"similar"
-  // pointers distinct.
-  if (Ty->isPointerType() || Ty->isReferenceType())
-    return createScalarTypeNode("any pointer", getChar(), Size);
+  if (Ty->isPointerType() || Ty->isReferenceType()) {
+    llvm::MDNode *AnyPtr = createScalarTypeNode("any pointer", getChar(), Size);
+    // Compute the depth of the pointer and generate a tag of the form "p<depth>
+    // <base type tag>".
+    unsigned PtrDepth = 0;
+    do {
+      PtrDepth++;
+      Ty = Ty->getPointeeType().getTypePtr();
+    } while (Ty->isPointerType() || Ty->isReferenceType());
+    // TODO: Implement C++'s type "similarity" and consider dis-"similar"
+    // pointers distinct for non-builtin types.
+    if (isa<BuiltinType>(Ty)) {
+      llvm::MDNode *ScalarMD = getTypeInfoHelper(Ty);
+      StringRef Name =
+          cast<llvm::MDString>(
+              ScalarMD->getOperand(CodeGenOpts.NewStructPathTBAA ? 2 : 0))
+              ->getString();
+      SmallString<256> OutName("p");
+      OutName += std::to_string(PtrDepth);
+      OutName += " ";
+      OutName += Name;
+      return createScalarTypeNode(OutName, AnyPtr, Size);
+    }
+    return AnyPtr;
+  }
 
   // Accesses to arrays are accesses to objects of their element types.
   if (CodeGenOpts.NewStructPathTBAA && Ty->isArrayType())
diff --git a/clang/test/CodeGen/tbaa-pointers.c b/clang/test/CodeGen/tbaa-pointers.c
index b9ebe879820012..a3a7aa0d66473e 100644
--- a/clang/test/CodeGen/tbaa-pointers.c
+++ b/clang/test/CodeGen/tbaa-pointers.c
@@ -4,9 +4,9 @@ void p2unsigned(unsigned **ptr) {
   // CHECK-LABEL: define void @p2unsigned(ptr noundef %ptr)
   // CHECK-NEXT: entry:
   // CHECK-NEXT:  %ptr.addr = alloca ptr, align 8
-  // CHECK-NEXT:  store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0:!.+]]
-  // CHECK-NEXT:  [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:  store ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
+  // CHECK-NEXT:  store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0:!.+]]
+  // CHECK-NEXT:  [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
+  // CHECK-NEXT:  store ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0:!.+]]
   // CHECK-NEXT:  ret void
   //
   *ptr = 0;
@@ -16,9 +16,9 @@ void p2unsigned_volatile(unsigned *volatile *ptr) {
   // CHECK-LABEL: define void @p2unsigned_volatile(ptr noundef %ptr)
   // CHECK-NEXT: entry:
   // CHECK-NEXT:   %ptr.addr = alloca ptr, align 8
-  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
+  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
+  // CHECK-NEXT:   [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
+  // CHECK-NEXT:   store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0]]
   // CHECK-NEXT:   ret void
   //
   *ptr = 0;
@@ -28,10 +28,10 @@ void p3int(int ***ptr) {
   // CHECK-LABEL: define void @p3int(ptr noundef %ptr)
   // CHECK-NEXT: entry:
   // CHECK-NEXT:   %ptr.addr = alloca ptr, align 8
-  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   store ptr null, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
+  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P3INT_0:!.+]]
+  // CHECK-NEXT:   [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P3INT_0]]
+  // CHECK-NEXT:   [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P2INT_0]]
+  // CHECK-NEXT:   store ptr null, ptr [[BASE_1]], align 8, !tbaa [[P1INT_0]]
   // CHECK-NEXT:   ret void
   //
   **ptr = 0;
@@ -41,11 +41,11 @@ void p4char(char ****ptr) {
   // CHECK-LABEL: define void @p4char(ptr noundef %ptr)
   // CHECK-NEXT: entry:
   // CHECK-NEXT:   %ptr.addr = alloca ptr, align 8
-  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
+  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0:!.+]]
+  // CHECK-NEXT:   [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
+  // CHECK-NEXT:   [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0:!.+]]
+  // CHECK-NEXT:   [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0:!.+]]
+  // CHECK-NEXT:   store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0:!.+]]
   // CHECK-NEXT:   ret void
   //
   ***ptr = 0;
@@ -55,11 +55,11 @@ void p4char_const1(const char ****ptr) {
   // CHECK-LABEL: define void @p4char_const1(ptr noundef %ptr)
   // CHECK-NEXT: entry:
   // CHECK-NEXT:   %ptr.addr = alloca ptr, align 8
-  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
+  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
+  // CHECK-NEXT:   [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
+  // CHECK-NEXT:   [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]]
+  // CHECK-NEXT:   [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]]
+  // CHECK-NEXT:   store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]]
   // CHECK-NEXT:   ret void
   //
   ***ptr = 0;
@@ -69,11 +69,11 @@ void p4char_const2(const char **const **ptr) {
   // CHECK-LABEL: define void @p4char_const2(ptr noundef %ptr)
   // CHECK-NEXT: entry:
   // CHECK-NEXT:   %ptr.addr = alloca ptr, align 8
-  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
+  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
+  // CHECK-NEXT:   [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
+  // CHECK-NEXT:   [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]]
+  // CHECK-NEXT:   [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]]
+  // CHECK-NEXT:   store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]]
   // CHECK-NEXT:   ret void
   //
   ***ptr = 0;
@@ -88,16 +88,28 @@ void p2struct(struct S1 **ptr) {
   // CHECK-LABEL: define void @p2struct(ptr noundef %ptr)
   // CHECK-NEXT: entry:
   // CHECK-NEXT:   %ptr.addr = alloca ptr, align 8
-  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
-  // CHECK-NEXT:   store ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
+  // CHECK-NEXT:   store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2S1_0:!.+]]
+  // CHECK-NEXT:   [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2S1_0]]
+  // CHECK-NEXT:   store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_:!.+]]
   // CHECK-NEXT:   ret void
   //
   *ptr = 0;
 }
 
-// CHECK: [[ANY_POINTER_0]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0}
+// CHECK: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0}
+// CHECK: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0}
 // CHECK: [[ANY_POINTER]] = !{!"any pointer", [[CHAR:!.+]], i64 0}
 // CHECK: [[CHAR]] = !{!"omnipotent char", [[TBAA_ROOT:!.+]], i64 0}
 // CHECK: [[TBAA_ROOT]] = !{!"Simple C/C++ TBAA"}
-//
+// CHECK: [[P1INT_0]] = !{[[P1INT:!.+]], [[P1INT]], i64 0}
+// CHECK: [[P1INT]] = !{!"p1 int", [[ANY_POINTER]], i64 0}
+// CHECK: [[P3INT_0]] = !{[[P3INT:!.+]], [[P3INT]], i64 0}
+// CHECK: [[P3INT]] = !{!"p3 int", [[ANY_POINTER]], i64 0}
+// CHECK: [[P4CHAR_0]] = !{[[P4CHAR:!.+]], [[P4CHAR]], i64 0}
+// CHECK: [[P4CHAR]] = !{!"p4 omnipotent char", [[ANY_POINTER]], i64 0}
+// CHECK: [[P3CHAR_0]] = !{[[P3CHAR:!.+]], [[P3CHAR]], i64 0}
+// CHECK: [[P3CHAR]] = !{!"p3 omnipotent char", [[ANY_POINTER]], i64 0}
+// CHECK: [[P2CHAR_0]] = !{[[P2CHAR:!.+]], [[P2CHAR]], i64 0}
+// CHECK: [[P2CHAR]] = !{!"p2 omnipotent char", [[ANY_POINTER]], i64 0}
+// CHECK: [[P1CHAR_0]] = !{[[P1CHAR:!.+]], [[P1CHAR]], i64 0}
+// CHECK: [[P1CHAR]] = !{!"p1 omnipotent char", [[ANY_POINTER]], i64 0}



More information about the cfe-commits mailing list