Author: Prabhu Rajasekaran
Date: 2026-06-30T18:47:04-07:00
New Revision: c311656883510568fc1ce027916a9534b825f91d

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

LOG: [clang][llvm]Uncorrelate CFI and Callgraph related type metadata 
annotations (#204266)

When -fexperimental-call-graph-section flag is set, it adds type
metadata to all the functions whose addresses are taken and does not
have local linkage. When this flag is set along with CFI, the type
metadata is added to all the vtable functions including destructors.
This changes which functions are to be treated as CFI functions and
includes such vtable entries to become part of the CFI check jumptables.

To disambiguate intentions of CFI and callgraph mechanisms, this patch
renames metadata set by callgraph mechanism to !callgraph
(MD_callgraph). This prevents inflating the list of CFI functions when
callgraph section is enabled along with CFI.

Added: 
    llvm/test/Transforms/MergeFunc/callgraph-function-merging.ll

Modified: 
    clang/lib/CodeGen/CodeGenModule.cpp
    clang/lib/CodeGen/CodeGenModule.h
    clang/test/CodeGen/call-graph-section-callback.cpp
    clang/test/CodeGen/call-graph-section-internal.cpp
    clang/test/CodeGen/call-graph-section-templates.cpp
    clang/test/CodeGen/call-graph-section-virtual-methods.cpp
    clang/test/CodeGen/call-graph-section.c
    clang/test/CodeGen/call-graph-section.cpp
    llvm/docs/LangRef.rst
    llvm/docs/Reference.md
    llvm/docs/ReleaseNotes.md
    llvm/include/llvm/IR/FixedMetadataKinds.def
    llvm/include/llvm/IR/Metadata.h
    llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/lib/CodeGen/MachineFunction.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/lib/Transforms/IPO/MergeFunctions.cpp
    llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
    llvm/test/Assembler/callee-type-metadata.ll
    llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
    llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll
    llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll
    llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll
    llvm/test/CodeGen/ARM/call-graph-section-assembly.ll
    llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll
    llvm/test/CodeGen/ARM/call-graph-section.ll
    llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
    llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll
    llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll
    llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir
    llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
    llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll
    llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
    llvm/test/CodeGen/Mips/callsite-emit-calleetypeid-tailcall.ll
    llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll
    llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
    llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll
    llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll
    llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll
    llvm/test/CodeGen/X86/call-graph-section-assembly.ll
    llvm/test/CodeGen/X86/call-graph-section-tailcall.ll
    llvm/test/CodeGen/X86/call-graph-section.ll
    llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
    llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll
    llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll
    llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
    llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
    llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
    llvm/test/Verifier/callee-type-metadata.ll

Removed: 
    llvm/docs/CalleeTypeMetadata.rst


################################################################################
diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 292706d3c5088..813cd67e4dd51 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3402,24 +3402,19 @@ static void setLinkageForGV(llvm::GlobalValue *GV, 
const NamedDecl *ND) {
     GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
 }
 
-static bool hasExistingGeneralizedTypeMD(llvm::Function *F) {
-  llvm::MDNode *MD = F->getMetadata(llvm::LLVMContext::MD_type);
-  return MD && MD->hasGeneralizedMDString();
-}
-
 void CodeGenModule::createIndirectFunctionTypeMD(const FunctionDecl *FD,
                                                  llvm::Function *F) {
-  // Return if generalized type metadata is already attached.
-  if (hasExistingGeneralizedTypeMD(F))
-    return;
-
   // All functions which are not internal linkage could be indirect targets.
   // Address taken functions with internal linkage could be indirect targets.
   if (!F->hasLocalLinkage() ||
       F->getFunction().hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true,
                                        /*IgnoreAssumeLikeCalls=*/true,
-                                       /*IgnoreLLVMUsed=*/false))
-    F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
+                                       /*IgnoreLLVMUsed=*/false)) {
+    F->addMetadata(llvm::LLVMContext::MD_callgraph,
+                   *llvm::MDTuple::get(
+                       getLLVMContext(),
+                       {CreateMetadataIdentifierGeneralized(FD->getType())}));
+  }
 }
 
 void CodeGenModule::createFunctionTypeMetadataForIcall(const FunctionDecl *FD,
@@ -3437,12 +3432,10 @@ void 
CodeGenModule::createFunctionTypeMetadataForIcall(const FunctionDecl *FD,
                                            /*GeneralizePointers=*/false);
   llvm::Metadata *MD = CreateMetadataIdentifierForType(FnType);
   F->addTypeMetadata(0, MD);
-  // Add the generalized identifier if not added already.
-  if (!hasExistingGeneralizedTypeMD(F)) {
-    QualType GenPtrFnType = GeneralizeFunctionType(getContext(), FD->getType(),
-                                                   
/*GeneralizePointers=*/true);
-    F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(GenPtrFnType));
-  }
+
+  QualType GenPtrFnType = GeneralizeFunctionType(getContext(), FD->getType(),
+                                                 /*GeneralizePointers=*/true);
+  F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(GenPtrFnType));
 
   // Emit a hash-based bit set entry for cross-DSO calls.
   if (CodeGenOpts.SanitizeCfiCrossDso)
@@ -3461,10 +3454,7 @@ void 
CodeGenModule::createCalleeTypeMetadataForIcall(const QualType &QT,
     return;
 
   llvm::Metadata *TypeIdMD = CreateMetadataIdentifierGeneralized(QT);
-  llvm::MDTuple *TypeTuple = llvm::MDTuple::get(
-      getLLVMContext(), {llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
-                             llvm::Type::getInt64Ty(getLLVMContext()), 0)),
-                         TypeIdMD});
+  llvm::MDTuple *TypeTuple = llvm::MDTuple::get(getLLVMContext(), {TypeIdMD});
   llvm::MDTuple *MDN = llvm::MDNode::get(getLLVMContext(), {TypeTuple});
   CB->setMetadata(llvm::LLVMContext::MD_callee_type, MDN);
 }

diff  --git a/clang/lib/CodeGen/CodeGenModule.h 
b/clang/lib/CodeGen/CodeGenModule.h
index 4283b6a3dc869..b1e70a7c347db 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1739,11 +1739,11 @@ class CodeGenModule : public CodeGenTypeCache {
   void createFunctionTypeMetadataForIcall(const FunctionDecl *FD,
                                           llvm::Function *F);
 
-  /// Create and attach type metadata if the function is a potential indirect
-  /// call target to support call graph section.
+  /// Create and attach callgraph metadata if the function is a potential
+  /// indirect call target to support call graph section.
   void createIndirectFunctionTypeMD(const FunctionDecl *FD, llvm::Function *F);
 
-  /// Create and attach type metadata to the given call.
+  /// Create and attach callee_type metadata to the given call.
   void createCalleeTypeMetadataForIcall(const QualType &QT, llvm::CallBase 
*CB);
 
   /// Set type metadata to the given function.

diff  --git a/clang/test/CodeGen/call-graph-section-callback.cpp 
b/clang/test/CodeGen/call-graph-section-callback.cpp
index e9b0a1818e3a4..c943050d6d59f 100644
--- a/clang/test/CodeGen/call-graph-section-callback.cpp
+++ b/clang/test/CodeGen/call-graph-section-callback.cpp
@@ -10,7 +10,7 @@ typedef void (*CallbackFn)(int);
 
 // Callback function with "internal" linkage.
 // CHECK-LABEL: define internal void @_ZL10myCallbacki(
-// CHECK-SAME: {{.*}} !type [[F_CALLBACK:![0-9]+]]
+// CHECK-SAME: {{.*}} !callgraph [[F_CALLBACK:![0-9]+]]
 static void myCallback(int value) 
 {
     volatile int sink = value;
@@ -27,4 +27,4 @@ int takeCallbackAddress() {
     return 0;
 }
 
-// CHECK: [[F_CALLBACK]]   = !{i64 0, !"_ZTSFviE.generalized"}
+// CHECK: [[F_CALLBACK]]   = !{!"_ZTSFviE.generalized"}

diff  --git a/clang/test/CodeGen/call-graph-section-internal.cpp 
b/clang/test/CodeGen/call-graph-section-internal.cpp
index aea48675dfa27..923cb4ed053b0 100644
--- a/clang/test/CodeGen/call-graph-section-internal.cpp
+++ b/clang/test/CodeGen/call-graph-section-internal.cpp
@@ -2,7 +2,7 @@
 
 // Check that we do not generate callee_type metadata for indirect calls
 // to functions with internal linkage (e.g., types in anonymous namespaces),
-// as their type metadata identifiers are distinct MDNodes instead of 
+// as their callgraph metadata identifiers are distinct MDNodes instead of 
 // generalized strings, which would fail the LLVM Verifier.
 
 namespace {

diff  --git a/clang/test/CodeGen/call-graph-section-templates.cpp 
b/clang/test/CodeGen/call-graph-section-templates.cpp
index 39030d27a4ea9..c26170585e8fd 100644
--- a/clang/test/CodeGen/call-graph-section-templates.cpp
+++ b/clang/test/CodeGen/call-graph-section-templates.cpp
@@ -17,39 +17,39 @@ template <class T>
 class Cls2 {
 public:
   // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f1Ev(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F1:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F1:![0-9]+]]
   void f1() {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f2ES0_(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F2:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F2:![0-9]+]]
   void f2(T a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f3EPS0_(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F3:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F3:![0-9]+]]
   void f3(T *a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f4EPKS0_(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F4:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F4:![0-9]+]]
   void f4(const T *a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f5ERS0_(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F5:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F5:![0-9]+]]
   void f5(T &a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f6ERKS0_(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F6:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F6:![0-9]+]]
   void f6(const T &a) {}
 
   // Mixed type function pointer member
   T *(*fp)(T a, T *b, const T *c, T &d, const T &e);
 };
 
-// FT: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFvvE.generalized"}
-// FT: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
-// FT: [[F_TCLS2F3]] = !{i64 0, !"_ZTSFvP4Cls1E.generalized"}
-// FT: [[F_TCLS2F4]] = !{i64 0, !"_ZTSFvPK4Cls1E.generalized"}
-// FT: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
-// FT: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
+// FT: [[F_TCLS2F1]] = !{!"_ZTSFvvE.generalized"}
+// FT: [[F_TCLS2F2]] = !{!"_ZTSFv4Cls1E.generalized"}
+// FT: [[F_TCLS2F3]] = !{!"_ZTSFvP4Cls1E.generalized"}
+// FT: [[F_TCLS2F4]] = !{!"_ZTSFvPK4Cls1E.generalized"}
+// FT: [[F_TCLS2F5]] = !{!"_ZTSFvR4Cls1E.generalized"}
+// FT: [[F_TCLS2F6]] = !{!"_ZTSFvRK4Cls1E.generalized"}
 
 
////////////////////////////////////////////////////////////////////////////////
 // Callsites (check for indirect callsite operand bundles)
@@ -58,7 +58,7 @@ template <class T>
 T *T_func(T a, T *b, const T *c, T &d, const T &e) { return b; }
 
 // CST-LABEL: define {{.*}} @_Z3foov
-// CST-SAME: {{.*}} !type [[F_TCLS2F1:![0-9]+]]
+// CST-SAME: {{.*}} !callgraph [[F_TCLS2F1:![0-9]+]]
 void foo() {
   // Methods for Cls2<Cls1> is checked above within the template description.
   Cls2<Cls1> Obj;
@@ -99,19 +99,19 @@ void foo() {
 }
 
 // CST-LABEL: define {{.*}} @_Z6T_funcI4Cls1EPT_S1_S2_PKS1_RS1_RS3_(
-// CST-SAME: {{.*}} !type [[F_TFUNC_CLS1:![0-9]+]]
+// CST-SAME: {{.*}} !callgraph [[F_TFUNC_CLS1:![0-9]+]]
 
-// CST: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFvvE.generalized"}
+// CST: [[F_TCLS2F1]] = !{!"_ZTSFvvE.generalized"}
 // CST: [[F_TFUNC_CLS1_CT]] = !{[[F_TFUNC_CLS1:![0-9]+]]}
-// CST: [[F_TFUNC_CLS1]] = !{i64 0, 
!"_ZTSFP4Cls1S_S0_PKS_RS_RS1_E.generalized"}
+// CST: [[F_TFUNC_CLS1]] = !{!"_ZTSFP4Cls1S_S0_PKS_RS_RS1_E.generalized"}
 // CST: [[F_TCLS2F1_CT]] = !{[[F_TCLS2F1:![0-9]+]]}
 // CST: [[F_TCLS2F2_CT]] = !{[[F_TCLS2F2:![0-9]+]]}
-// CST: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
+// CST: [[F_TCLS2F2]] = !{!"_ZTSFv4Cls1E.generalized"}
 // CST: [[F_TCLS2F3_CT]] = !{[[F_TCLS2F3:![0-9]+]]}
-// CST: [[F_TCLS2F3]] = !{i64 0, !"_ZTSFvP4Cls1E.generalized"}
+// CST: [[F_TCLS2F3]] = !{!"_ZTSFvP4Cls1E.generalized"}
 // CST: [[F_TCLS2F4_CT]] = !{[[F_TCLS2F4:![0-9]+]]}
-// CST: [[F_TCLS2F4]] = !{i64 0, !"_ZTSFvPK4Cls1E.generalized"}
+// CST: [[F_TCLS2F4]] = !{!"_ZTSFvPK4Cls1E.generalized"}
 // CST: [[F_TCLS2F5_CT]] = !{[[F_TCLS2F5:![0-9]+]]}
-// CST: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
+// CST: [[F_TCLS2F5]] = !{!"_ZTSFvR4Cls1E.generalized"}
 // CST: [[F_TCLS2F6_CT]] = !{[[F_TCLS2F6:![0-9]+]]}
-// CST: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
+// CST: [[F_TCLS2F6]] = !{!"_ZTSFvRK4Cls1E.generalized"}

diff  --git a/clang/test/CodeGen/call-graph-section-virtual-methods.cpp 
b/clang/test/CodeGen/call-graph-section-virtual-methods.cpp
index afeeae146ec41..34c22c467080b 100644
--- a/clang/test/CodeGen/call-graph-section-virtual-methods.cpp
+++ b/clang/test/CodeGen/call-graph-section-virtual-methods.cpp
@@ -12,17 +12,17 @@
 class Base {
   public:
     // FT-LABEL: define {{.*}} @_ZN4Base2vfEPc(
-    // FT-SAME: {{.*}} !type [[F_TVF:![0-9]+]]
+    // FT-SAME: {{.*}} !callgraph [[F_TVF:![0-9]+]]
     virtual int vf(char *a) { return 0; };
   };
   
   class Derived : public Base {
   public:
-    // FT: define {{.*}} @_ZN7Derived2vfEPc({{.*}} !type [[F_TVF]]
+    // FT: define {{.*}} @_ZN7Derived2vfEPc({{.*}} !callgraph [[F_TVF]]
     int vf(char *a) override { return 1; };
   };
   
-  // FT: [[F_TVF]] = !{i64 0, !"_ZTSFiPcE.generalized"}
+  // FT: [[F_TVF]] = !{!"_ZTSFiPcE.generalized"}
   
   
////////////////////////////////////////////////////////////////////////////////
   // Callsites (check for indirect callsite operand bundles)
@@ -53,4 +53,4 @@ class Base {
   }
 
   // CST: [[F_TVF_CT]] = !{[[F_TVF:![0-9]+]]}
-  // CST: [[F_TVF]] = !{i64 0, !"_ZTSFiPcE.generalized"}
+  // CST: [[F_TVF]] = !{!"_ZTSFiPcE.generalized"}

diff  --git a/clang/test/CodeGen/call-graph-section.c 
b/clang/test/CodeGen/call-graph-section.c
index 69cdd59549190..94581674dc5e3 100644
--- a/clang/test/CodeGen/call-graph-section.c
+++ b/clang/test/CodeGen/call-graph-section.c
@@ -7,12 +7,12 @@
 // RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s
 
 // CHECK-LABEL: define {{(dso_local)?}} void @foo(
-// CHECK-SAME: {{.*}} !type [[F_TVOID:![0-9]+]]
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID:![0-9]+]]
 void foo() {
 }
 
 // CHECK-LABEL: define {{(dso_local)?}} void @bar(
-// CHECK-SAME: {{.*}} !type [[F_TVOID]]
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
 void bar() {
   void (*fp)() = foo;
   // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
@@ -21,19 +21,19 @@ void bar() {
 }
 
 // CHECK-LABEL: define {{(dso_local)?}} i32 @baz(
-// CHECK-SAME: {{.*}} !type [[F_TPRIMITIVE:![0-9]+]]
+// CHECK-SAME: {{.*}} !callgraph [[F_TPRIMITIVE:![0-9]+]]
 int baz(char a, float b, double c) {
   return 1;
 }
 
 // CHECK-LABEL: define {{(dso_local)?}} ptr @qux(
-// CHECK-SAME: {{.*}} !type [[F_TPTR:![0-9]+]]
+// CHECK-SAME: {{.*}} !callgraph [[F_TPTR:![0-9]+]]
 int *qux(char *a, float *b, double *c) {
   return 0;
 }
 
 // CHECK-LABEL: define {{(dso_local)?}} void @corge(
-// CHECK-SAME: {{.*}} !type [[F_TVOID]]
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
 void corge() {
   int (*fp_baz)(char, float, double) = baz;  
   // CHECK: call i32 {{.*}}, !callee_type [[F_TPRIMITIVE_CT:![0-9]+]]
@@ -53,11 +53,11 @@ struct st2 {
 };
 
 // CHECK-LABEL: define {{(dso_local)?}} void @stparam(
-// CHECK-SAME: {{.*}} !type [[F_TSTRUCT:![0-9]+]]
+// CHECK-SAME: {{.*}} !callgraph [[F_TSTRUCT:![0-9]+]]
 void stparam(struct st2 a, struct st2 *b) {}
 
 // CHECK-LABEL: define {{(dso_local)?}} void @stf(
-// CHECK-SAME: {{.*}} !type [[F_TVOID]]
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
 void stf() {
   struct st1 St1;
   St1.fp = qux;  
@@ -74,20 +74,20 @@ void stf() {
   fp_stparam(St2, &St2);
 }
 
-// ITANIUM: [[F_TVOID]] = !{i64 0, !"_ZTSFvE.generalized"}
+// ITANIUM: [[F_TVOID]] = !{!"_ZTSFvE.generalized"}
 // ITANIUM: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
-// ITANIUM: [[F_TPRIMITIVE]] = !{i64 0, !"_ZTSFicfdE.generalized"}
-// ITANIUM: [[F_TPTR]] = !{i64 0, !"_ZTSFPiPcPfPdE.generalized"}
+// ITANIUM: [[F_TPRIMITIVE]] = !{!"_ZTSFicfdE.generalized"}
+// ITANIUM: [[F_TPTR]] = !{!"_ZTSFPiPcPfPdE.generalized"}
 // ITANIUM: [[F_TPRIMITIVE_CT]] = !{[[F_TPRIMITIVE:![0-9]+]]}
 // ITANIUM: [[F_TPTR_CT]] = !{[[F_TPTR:![0-9]+]]}
-// ITANIUM: [[F_TSTRUCT]] = !{i64 0, !"_ZTSFv3st2PS_E.generalized"}
+// ITANIUM: [[F_TSTRUCT]] = !{!"_ZTSFv3st2PS_E.generalized"}
 // ITANIUM: [[F_TSTRUCT_CT]] = !{[[F_TSTRUCT:![0-9]+]]}
 
-// MS: [[F_TVOID]] = !{i64 0, !"[email protected]"}
+// MS: [[F_TVOID]] = !{!"[email protected]"}
 // MS: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
-// MS: [[F_TPRIMITIVE]] = !{i64 0, !"[email protected]"}
-// MS: [[F_TPTR]] = !{i64 0, !"[email protected]"}
+// MS: [[F_TPRIMITIVE]] = !{!"[email protected]"}
+// MS: [[F_TPTR]] = !{!"[email protected]"}
 // MS: [[F_TPRIMITIVE_CT]] = !{[[F_TPRIMITIVE:![0-9]+]]}
 // MS: [[F_TPTR_CT]] = !{[[F_TPTR:![0-9]+]]}
-// MS: [[F_TSTRUCT]] = !{i64 0, !"?6AXUst2@@PEAU0@@Z.generalized"}
+// MS: [[F_TSTRUCT]] = !{!"?6AXUst2@@PEAU0@@Z.generalized"}
 // MS: [[F_TSTRUCT_CT]] = !{[[F_TSTRUCT:![0-9]+]]}

diff  --git a/clang/test/CodeGen/call-graph-section.cpp 
b/clang/test/CodeGen/call-graph-section.cpp
index 86ed3ee2337a7..a358ff9d2d551 100644
--- a/clang/test/CodeGen/call-graph-section.cpp
+++ b/clang/test/CodeGen/call-graph-section.cpp
@@ -12,7 +12,7 @@
 class Cls1 {
 public:
   // FT-LABEL: define {{.*}} ptr @_ZN4Cls18receiverEPcPf(
-  // FT-SAME: {{.*}} !type [[F_TCLS1RECEIVER:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS1RECEIVER:![0-9]+]]
   static int *receiver(char *a, float *b) { return 0; }
 };
 
@@ -21,51 +21,51 @@ class Cls2 {
   int *(*fp)(char *, float *);
 
   // FT-LABEL: define {{.*}} i32 @_ZN4Cls22f1Ecfd(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F1:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F1:![0-9]+]]
   int f1(char a, float b, double c) { return 0; }
 
   // FT-LABEL: define {{.*}} ptr @_ZN4Cls22f2EPcPfPd(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F2:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F2:![0-9]+]]
   int *f2(char *a, float *b, double *c) { return 0; }
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls22f3E4Cls1(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F3F4:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F3F4:![0-9]+]]
   void f3(Cls1 a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls22f4E4Cls1(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F3F4]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F3F4]]
   void f4(const Cls1 a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls22f5EP4Cls1(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F5:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F5:![0-9]+]]
   void f5(Cls1 *a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls22f6EPK4Cls1(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F6:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F6:![0-9]+]]
   void f6(const Cls1 *a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls22f7ER4Cls1(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F7:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F7:![0-9]+]]
   void f7(Cls1 &a) {}
 
   // FT-LABEL: define {{.*}} void @_ZN4Cls22f8ERK4Cls1(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F8:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F8:![0-9]+]]
   void f8(const Cls1 &a) {}
 
   // FT-LABEL: define {{.*}} void @_ZNK4Cls22f9Ev(
-  // FT-SAME: {{.*}} !type [[F_TCLS2F9:![0-9]+]]
+  // FT-SAME: {{.*}} !callgraph [[F_TCLS2F9:![0-9]+]]
   void f9() const {}
 };
 
-// FT: [[F_TCLS1RECEIVER]] = !{i64 0, !"_ZTSFPiPcPfE.generalized"}
-// FT: [[F_TCLS2F1]]   = !{i64 0, !"_ZTSFicfdE.generalized"}
-// FT: [[F_TCLS2F2]]   = !{i64 0, !"_ZTSFPiPcPfPdE.generalized"}
-// FT: [[F_TCLS2F3F4]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
-// FT: [[F_TCLS2F5]]   = !{i64 0, !"_ZTSFvP4Cls1E.generalized"}
-// FT: [[F_TCLS2F6]]   = !{i64 0, !"_ZTSFvPK4Cls1E.generalized"}
-// FT: [[F_TCLS2F7]]   = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
-// FT: [[F_TCLS2F8]]   = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
-// FT: [[F_TCLS2F9]]   = !{i64 0, !"_ZTSKFvvE.generalized"}
+// FT: [[F_TCLS1RECEIVER]] = !{!"_ZTSFPiPcPfE.generalized"}
+// FT: [[F_TCLS2F1]]   = !{!"_ZTSFicfdE.generalized"}
+// FT: [[F_TCLS2F2]]   = !{!"_ZTSFPiPcPfPdE.generalized"}
+// FT: [[F_TCLS2F3F4]] = !{!"_ZTSFv4Cls1E.generalized"}
+// FT: [[F_TCLS2F5]]   = !{!"_ZTSFvP4Cls1E.generalized"}
+// FT: [[F_TCLS2F6]]   = !{!"_ZTSFvPK4Cls1E.generalized"}
+// FT: [[F_TCLS2F7]]   = !{!"_ZTSFvR4Cls1E.generalized"}
+// FT: [[F_TCLS2F8]]   = !{!"_ZTSFvRK4Cls1E.generalized"}
+// FT: [[F_TCLS2F9]]   = !{!"_ZTSKFvvE.generalized"}
 
 
////////////////////////////////////////////////////////////////////////////////
 // Callsites (check for indirect callsites' callee_type metadata )
@@ -120,28 +120,28 @@ void foo() {
 }
 
 // CST: [[F_TCLS1RECEIVER_CT]] = !{[[F_TCLS1RECEIVER:![0-9]+]]}
-// CST: [[F_TCLS1RECEIVER]] = !{i64 0, !"_ZTSFPiPcPfE.generalized"}
+// CST: [[F_TCLS1RECEIVER]] = !{!"_ZTSFPiPcPfE.generalized"}
 
 // CST: [[F_TCLS2F1_CT]] = !{[[F_TCLS2F1:![0-9]+]]}
-// CST: [[F_TCLS2F1]]   = !{i64 0, !"_ZTSFicfdE.generalized"}
+// CST: [[F_TCLS2F1]]   = !{!"_ZTSFicfdE.generalized"}
 
 // CST: [[F_TCLS2F2_CT]] = !{[[F_TCLS2F2:![0-9]+]]}
-// CST: [[F_TCLS2F2]]   = !{i64 0, !"_ZTSFPiPcPfPdE.generalized"}
+// CST: [[F_TCLS2F2]]   = !{!"_ZTSFPiPcPfPdE.generalized"}
 
 // CST: [[F_TCLS2F3F4_CT]] = !{[[F_TCLS2F3F4:![0-9]+]]}
-// CST: [[F_TCLS2F3F4]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
+// CST: [[F_TCLS2F3F4]] = !{!"_ZTSFv4Cls1E.generalized"}
 
 // CST: [[F_TCLS2F5_CT]] = !{[[F_TCLS2F5:![0-9]+]]}
-// CST: [[F_TCLS2F5]]   = !{i64 0, !"_ZTSFvP4Cls1E.generalized"}
+// CST: [[F_TCLS2F5]]   = !{!"_ZTSFvP4Cls1E.generalized"}
 
 // CST: [[F_TCLS2F6_CT]] = !{[[F_TCLS2F6:![0-9]+]]}
-// CST: [[F_TCLS2F6]]   = !{i64 0, !"_ZTSFvPK4Cls1E.generalized"}
+// CST: [[F_TCLS2F6]]   = !{!"_ZTSFvPK4Cls1E.generalized"}
 
 // CST: [[F_TCLS2F7_CT]] = !{[[F_TCLS2F7:![0-9]+]]}
-// CST: [[F_TCLS2F7]]   = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
+// CST: [[F_TCLS2F7]]   = !{!"_ZTSFvR4Cls1E.generalized"}
 
 // CST: [[F_TCLS2F8_CT]] = !{[[F_TCLS2F8:![0-9]+]]}
-// CST: [[F_TCLS2F8]]   = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
+// CST: [[F_TCLS2F8]]   = !{!"_ZTSFvRK4Cls1E.generalized"}
 
 // CST: [[F_TCLS2F9_CT]] = !{[[F_TCLS2F9:![0-9]+]]}
-// CST: [[F_TCLS2F9]]   = !{i64 0, !"_ZTSKFvvE.generalized"}
+// CST: [[F_TCLS2F9]]   = !{!"_ZTSKFvvE.generalized"}

diff  --git a/llvm/docs/CalleeTypeMetadata.rst 
b/llvm/docs/CalleeTypeMetadata.rst
deleted file mode 100644
index 45d0657966a8c..0000000000000
--- a/llvm/docs/CalleeTypeMetadata.rst
+++ /dev/null
@@ -1,33 +0,0 @@
-====================
-Callee Type Metadata
-====================
-
-Introduction
-============
-This ``!callee_type`` metadata is introduced to support the generation of a 
call graph
-section in the object file.  The ``!callee_type`` metadata is used
-to identify the types of the intended callees of indirect call instructions. 
The ``!callee_type`` metadata is a
-list of one or more generalized ``!type`` metadata objects (See 
:doc:`TypeMetadata`) with each ``!type``
-metadata pointing to a callee's :ref:`type identifier 
<calleetype-type-identifier>`.
-LLVM's `Control Flow Integrity (CFI)`_ also uses the ``!type`` metadata in its 
implementation.
-
-.. _Control Flow Integrity (CFI): 
https://clang.llvm.org/docs/ControlFlowIntegrity.html
-
-.. _calleetype-type-identifier:
-
-Type identifier
-================
-
-The type for an indirect call target is the callee's function signature.
-Mapping from a type to an identifier is an ABI detail.
-In the current implementation, an identifier of type T is
-computed as follows:
-
-  -  Obtain the generalized mangled name for “typeinfo name for T”.
-  -  Compute MD5 hash of the name as a string.
-  -  Reinterpret the first 8 bytes of the hash as a little-endian 64-bit 
integer.
-
-To avoid mismatched pointer types, generalizations are applied.
-Pointers in return and argument types are treated as equivalent as long as the 
qualifiers for the 
-type they point to match. For example, ``char*``, ``char**``, and ``int*`` are 
considered equivalent
-types. However, ``char*`` and ``const char*`` are considered distinct types.

diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 5640eec987133..4d880494eb449 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8700,10 +8700,81 @@ change in the future.
 
 See :doc:`TypeMetadata`.
 
+.. _metadata_callee_type:
+
 '``callee_type``' Metadata
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-See :doc:`CalleeTypeMetadata`.
+The ``!callee_type`` metadata is introduced to support the generation of a 
call graph
+section in the object file. The ``!callee_type`` metadata is used
+to identify the types of the intended callees of indirect call instructions. 
The ``!callee_type`` metadata is a
+list of one or more generalized ``!callgraph`` metadata objects (See the 
:ref:`metadata_callgraph` section) with each ``!callgraph``
+metadata pointing to a callee's :ref:`type identifier 
<calleetype-type-identifier>`.
+
+While ``!callee_type`` and ``!callgraph`` are private to the Call Graph 
Section pipeline and contain no offsets,
+LLVM's `Control Flow Integrity (CFI)
+<https://clang.org/docs/ControlFlowIntegrity.html>`_ uses a structurally 
similar ``!type`` metadata in its implementation (See :doc:`TypeMetadata`),
+which shares the same type identifier format but includes a leading offset for 
vtable compatibility.
+
+.. _calleetype-type-identifier:
+
+Type identifier
+"""""""""""""""
+
+The type for an indirect call target is the callee's function signature.
+Mapping from a type to an identifier is an ABI detail.
+In the current implementation, an identifier of type T is
+computed as follows:
+
+  -  Obtain the generalized mangled name for “typeinfo name for T”.
+  -  Compute MD5 hash of the name as a string.
+  -  Reinterpret the first 8 bytes of the hash as a little-endian 64-bit 
integer.
+
+To avoid mismatched pointer types, generalizations are applied.
+Pointers in return and argument types are treated as equivalent as long as the 
qualifiers for the 
+type they point to match. For example, ``char*``, ``char**``, and ``int*`` are 
considered equivalent
+types. However, ``char*`` and ``const char*`` are considered distinct types.
+
+.. _metadata_callgraph:
+
+'``callgraph``' Metadata
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``!callgraph`` metadata associates a function definition with its type
+identifier. It uses the same generalized type encoding as the ``!type`` 
metadata
+used for CFI and WPD, and allows us to emit a call graph section in the object
+file that can be used to compute a conservative and precise static call graph
+in a linked binary.
+
+Syntax:
+"""""""
+
+A ``!callgraph`` metadata node is attached to a function definition as follows:
+
+.. code-block:: llvm
+
+  define void @foo() !callgraph !0
+  !0 = !{!"_ZTSFvvE.generalized"}
+
+The metadata node is a 1-element tuple containing only the generalized type
+identifier as ``MDString``.
+
+Relation to Control Flow Integrity (CFI)
+""""""""""""""""""""""""""""""""""""""""
+
+While ``!callgraph`` metadata is structurally similar to LLVM's ``!type``
+metadata (which is used by `Control Flow Integrity (CFI)
+<https://clang.org/docs/ControlFlowIntegrity.html>`_ and Whole Program
+Devirtualization), they serve 
diff erent purposes:
+
+* ``!type`` (CFI): Contains an offset (e.g., ``!{i64 0, 
!"_ZTSFvvE.generalized"}``)
+  to support virtual table offset calculations and devirtualization.
+* ``!callgraph`` (Call Graph Section): Does not contain an offset. This is
+  private to the Call Graph Section pipeline.
+
+The generalized type identifier format used by both is identical. For more
+details on the generalized type identifier format and CFI's metadata, see
+:doc:`TypeMetadata` and :ref:`metadata_callee_type`.
 
 '``associated``' Metadata
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/llvm/docs/Reference.md b/llvm/docs/Reference.md
index 1bbdc8f4582dd..24a3fe88106d4 100644
--- a/llvm/docs/Reference.md
+++ b/llvm/docs/Reference.md
@@ -53,7 +53,6 @@ MLGO
 ContentAddressableStorage
 CIBestPractices
 AIToolPolicy
-CalleeTypeMetadata
 CallGraphSection
 InterfaceExportAnnotations
 PCSectionsMetadata

diff  --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index fdf3fddd1fef9..fd4156032bfc1 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -102,6 +102,11 @@ Makes programs 10x faster by doing Special New Thing.
   outlining. Add the `noinline` and `nooutline` attributes as well in cases
   where inlining and outlining should additionally be disabled.
 
+* Added support for ``callgraph`` metadata. The `!callgraph` metadata
+  associates a function definition with its type identifier and is used for 
call
+  graph section generation. See the [callgraph 
Metadata](https://llvm.org/docs/LangRef.html#callgraph-metadata)
+  section of the LangRef for details.
+
 ### Changes to LLVM infrastructure
 
 * Removed ``Constant::isZeroValue``. It was functionally identical to

diff  --git a/llvm/include/llvm/IR/FixedMetadataKinds.def 
b/llvm/include/llvm/IR/FixedMetadataKinds.def
index 6271633ca6d66..cb6ebfb5c0fb5 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -65,3 +65,5 @@ LLVM_FIXED_MD_KIND(MD_elf_section_properties, 
"elf_section_properties", 50)
 LLVM_FIXED_MD_KIND(MD_unique_id, "guid", 51)
 LLVM_FIXED_MD_KIND(MD_mem_cache_hint, "mem.cache_hint", 52)
 LLVM_FIXED_MD_KIND(MD_block_uniformity_profile, "block.uniformity.profile", 53)
+LLVM_FIXED_MD_KIND(MD_callgraph, "callgraph", 54)
+

diff  --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index b9288740a7145..73adeb3416ab1 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -1255,13 +1255,6 @@ class MDNode : public Metadata {
   bool isReplaceable() const { return isTemporary() || isAlwaysReplaceable(); }
   bool isAlwaysReplaceable() const { return getMetadataID() == DIAssignIDKind; 
}
 
-  /// Check if this is a valid generalized type metadata node.
-  bool hasGeneralizedMDString() {
-    if (getNumOperands() < 2 || !isa<MDString>(getOperand(1)))
-      return false;
-    return 
cast<MDString>(getOperand(1))->getString().ends_with(".generalized");
-  }
-
   unsigned getNumTemporaryUses() const {
     assert(isTemporary() && "Only for temporaries");
     return Context.getReplaceableUses()->getNumUses();

diff  --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp 
b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index aedc4956f1bd8..abb20a7919fa1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1752,16 +1752,18 @@ void AsmPrinter::emitStackUsage(const MachineFunction 
&MF) {
 }
 
 /// Extracts a generalized numeric type identifier of a Function's type from
-/// type metadata. Returns null if metadata cannot be found.
+/// callgraph metadata. Returns null if metadata cannot be found.
 static ConstantInt *extractNumericCGTypeId(const Function &F) {
   SmallVector<MDNode *, 2> Types;
-  F.getMetadata(LLVMContext::MD_type, Types);
+  F.getMetadata(LLVMContext::MD_callgraph, Types);
   for (const auto &Type : Types) {
-    if (Type->hasGeneralizedMDString()) {
-      MDString *MDGeneralizedTypeId = cast<MDString>(Type->getOperand(1));
-      uint64_t TypeIdVal = llvm::MD5Hash(MDGeneralizedTypeId->getString());
-      IntegerType *Int64Ty = Type::getInt64Ty(F.getContext());
-      return ConstantInt::get(Int64Ty, TypeIdVal);
+    if (Type->getNumOperands() == 1 && isa<MDString>(Type->getOperand(0))) {
+      MDString *MDGeneralizedTypeId = cast<MDString>(Type->getOperand(0));
+      if (MDGeneralizedTypeId->getString().ends_with(".generalized")) {
+        uint64_t TypeIdVal = llvm::MD5Hash(MDGeneralizedTypeId->getString());
+        IntegerType *Int64Ty = Type::getInt64Ty(F.getContext());
+        return ConstantInt::get(Int64Ty, TypeIdVal);
+      }
     }
   }
   return nullptr;

diff  --git a/llvm/lib/CodeGen/MachineFunction.cpp 
b/llvm/lib/CodeGen/MachineFunction.cpp
index b0ffdb36f21be..bbc5041a9166d 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -758,7 +758,7 @@ MachineFunction::CallSiteInfo::CallSiteInfo(const CallBase 
&CB) {
 
   for (const MDOperand &Op : CalleeTypeList->operands()) {
     MDNode *TypeMD = cast<MDNode>(Op);
-    MDString *TypeIdStr = cast<MDString>(TypeMD->getOperand(1));
+    MDString *TypeIdStr = cast<MDString>(TypeMD->getOperand(0));
     // Compute numeric type id from generalized type id string
     uint64_t TypeIdVal = MD5Hash(TypeIdStr->getString());
     IntegerType *Int64Ty = Type::getInt64Ty(CB.getContext());

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index a4e0f531ab1ef..88d99750048d5 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5428,28 +5428,25 @@ void Verifier::visitCallsiteMetadata(Instruction &I, 
MDNode *MD) {
   visitCallStackMetadata(MD);
 }
 
-static inline bool isConstantIntMetadataOperand(const Metadata *MD) {
-  if (auto *VAL = dyn_cast<ValueAsMetadata>(MD))
-    return isa<ConstantInt>(VAL->getValue());
-  return false;
-}
-
 void Verifier::visitCalleeTypeMetadata(Instruction &I, MDNode *MD) {
   Check(isa<CallBase>(I), "!callee_type metadata should only exist on calls",
         &I);
   for (Metadata *Op : MD->operands()) {
     Check(isa<MDNode>(Op),
-          "The callee_type metadata must be a list of type metadata nodes", 
Op);
-    auto *TypeMD = cast<MDNode>(Op);
-    Check(TypeMD->getNumOperands() == 2,
-          "Well-formed generalized type metadata must contain exactly two "
-          "operands",
+          "The callee_type metadata must be a list of callgraph metadata 
nodes",
+          Op);
+    auto *CallgraphMD = cast<MDNode>(Op);
+    Check(CallgraphMD->getNumOperands() == 1,
+          "Well-formed generalized callgraph metadata must contain exactly one 
"
+          "operand",
+          Op);
+    Check(isa<MDString>(CallgraphMD->getOperand(0)),
+          "The operand of callgraph metadata for functions must be an 
MDString",
           Op);
-    Check(isConstantIntMetadataOperand(TypeMD->getOperand(0)) &&
-              mdconst::extract<ConstantInt>(TypeMD->getOperand(0))->isZero(),
-          "The first operand of type metadata for functions must be zero", Op);
-    Check(TypeMD->hasGeneralizedMDString(),
-          "Only generalized type metadata can be part of the callee_type "
+    Check(cast<MDString>(CallgraphMD->getOperand(0))
+              ->getString()
+              .ends_with(".generalized"),
+          "Only generalized callgraph metadata can be part of the callee_type "
           "metadata list",
           Op);
   }

diff  --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp 
b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index 5c8624ba56a27..0b2315faaeb94 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -805,6 +805,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
     // Ensure CFI type metadata is propagated to the new function.
     copyMetadataIfPresent(G, NewG, "type");
     copyMetadataIfPresent(G, NewG, "kcfi_type");
+    copyMetadataIfPresent(G, NewG, "callgraph");
     removeUsers(G);
     G->replaceAllUsesWith(NewG);
     G->eraseFromParent();
@@ -902,6 +903,7 @@ void MergeFunctions::mergeTwoFunctions(Function *F, 
Function *G) {
     // Ensure CFI type metadata is propagated to the new function.
     copyMetadataIfPresent(F, NewF, "type");
     copyMetadataIfPresent(F, NewF, "kcfi_type");
+    copyMetadataIfPresent(F, NewF, "callgraph");
     removeUsers(F);
     F->replaceAllUsesWith(NewF);
 

diff  --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp 
b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
index c14c9b869525d..a486979a58c2d 100644
--- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
+++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
@@ -169,6 +169,22 @@ void promoteTypeIds(Module &M, StringRef ModuleId) {
           LLVMContext::MD_type,
           *MDNode::get(M.getContext(), {MD->getOperand(0), I->second}));
     }
+
+    SmallVector<MDNode *, 1> CGMDs;
+    GO.getMetadata(LLVMContext::MD_callgraph, CGMDs);
+
+    GO.eraseMetadata(LLVMContext::MD_callgraph);
+    for (auto *MD : CGMDs) {
+      if (MD->getNumOperands() == 1) {
+        auto I = LocalToGlobal.find(MD->getOperand(0));
+        if (I == LocalToGlobal.end()) {
+          GO.addMetadata(LLVMContext::MD_callgraph, *MD);
+          continue;
+        }
+        GO.addMetadata(LLVMContext::MD_callgraph,
+                       *MDNode::get(M.getContext(), {I->second}));
+      }
+    }
   }
 }
 

diff  --git a/llvm/test/Assembler/callee-type-metadata.ll 
b/llvm/test/Assembler/callee-type-metadata.ll
index 9c3cfbe82fc13..305aedd0b2895 100644
--- a/llvm/test/Assembler/callee-type-metadata.ll
+++ b/llvm/test/Assembler/callee-type-metadata.ll
@@ -16,6 +16,6 @@ entry:
 
 declare !type !2 i32 @_Z3barc(i8 signext)
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll 
b/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
index c4c54175ecd9f..7aae1783de2cb 100644
--- a/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
@@ -7,7 +7,7 @@
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
-define i32 @foo(i32 %x, i32 %y) !type !0 {
+define i32 @foo(i32 %x, i32 %y) !callgraph !0 {
 entry:
   ;; Call instruction with accurate callee_type.
   ;; callee_type should be dropped seemlessly.
@@ -23,10 +23,10 @@ entry:
   ret i32 %sub
 }
 
-declare !type !2 i32 @fizz(i32, i32)
+declare !callgraph !2 i32 @fizz(i32, i32)
 
-!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!0 = !{!"_ZTSFiiiiE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
+!2 = !{!"_ZTSFiiiE.generalized"}
 !3 = !{!4}
-!4 = !{i64 0, !"_ZTSFicE.generalized"}
+!4 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll 
b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll
index b47607ec135ae..780a67695a170 100644
--- a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll
+++ b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll
@@ -5,7 +5,7 @@
 ;; computed as the type id from the callee_type metadata.
 ; RUN: llc --call-graph-section -mtriple aarch64-linux-gnu < %s 
-stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
 
-define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
+define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 {
 entry:
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
@@ -14,6 +14,6 @@ entry:
   ret i32 %call
 }
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll 
b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll
index 94b657c6ea908..c918558d8bd82 100644
--- a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll
+++ b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll
@@ -17,4 +17,4 @@ entry:
 }
 
 !0 = !{!1}
-!1 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{!"_ZTSFvcE.generalized"}

diff  --git a/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll 
b/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll
index 9e243aec1128d..3ffdb65aed8dc 100644
--- a/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll
+++ b/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll
@@ -5,16 +5,16 @@
 
 ; RUN: llc -mtriple=arm-unknown-linux --call-graph-section -o - < %s | 
FileCheck %s
 
-declare !type !0 void @_Z6doWorkPFviE(ptr)
+declare !callgraph !0 void @_Z6doWorkPFviE(ptr)
 
-define i32 @_Z4testv() !type !1 {
+define i32 @_Z4testv() !callgraph !1 {
 entry:
   call void @_Z6doWorkPFviE(ptr nonnull @_ZL10myCallbacki)
   ret i32 0
 }
 
 ; CHECK: _ZL10myCallbacki:
-define internal void @_ZL10myCallbacki(i32 %value) !type !2 {
+define internal void @_ZL10myCallbacki(i32 %value) !callgraph !2 {
 entry:
   %sink = alloca i32, align 4
   store volatile i32 %value, ptr %sink, align 4
@@ -22,9 +22,9 @@ entry:
   ret void
 }
 
-!0 = !{i64 0, !"_ZTSFvPFviEE.generalized"}
-!1 = !{i64 0, !"_ZTSFivE.generalized"}
-!2 = !{i64 0, !"_ZTSFviE.generalized"}
+!0 = !{!"_ZTSFvPFviEE.generalized"}
+!1 = !{!"_ZTSFivE.generalized"}
+!2 = !{!"_ZTSFviE.generalized"}
 
 ; CHECK: .section .llvm.callgraph,"o",%llvm_call_graph,.text
 ;; Version

diff  --git a/llvm/test/CodeGen/ARM/call-graph-section-assembly.ll 
b/llvm/test/CodeGen/ARM/call-graph-section-assembly.ll
index 8e8881ee722fb..74000dc4337bc 100644
--- a/llvm/test/CodeGen/ARM/call-graph-section-assembly.ll
+++ b/llvm/test/CodeGen/ARM/call-graph-section-assembly.ll
@@ -6,9 +6,9 @@
 
 ; RUN: llc -mtriple=arm-unknown-linux --call-graph-section -o - < %s | 
FileCheck %s
 
-declare !type !0 void @direct_foo()
-declare !type !1 i32 @direct_bar(i8)
-declare !type !2 ptr @direct_baz(ptr)
+declare !callgraph !0 void @direct_foo()
+declare !callgraph !1 i32 @direct_bar(i8)
+declare !callgraph !2 ptr @direct_baz(ptr)
 
 ; CHECK: ball:
 define ptr @ball() {
@@ -29,11 +29,11 @@ entry:
 }
 
 !0 = !{!1}
-!1 = !{i64 0, !"_ZTSFvE.generalized"}
+!1 = !{!"_ZTSFvE.generalized"}
 !2 = !{!3}
-!3 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{!"_ZTSFicE.generalized"}
 !4 = !{!5}
-!5 = !{i64 0, !"_ZTSFPvS_E.generalized"}
+!5 = !{!"_ZTSFPvS_E.generalized"}
 
 ; CHECK: .section .llvm.callgraph,"o",%llvm_call_graph,.text
 ;; Version

diff  --git a/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll 
b/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll
index 35e570bdde405..eeceea7bc73ab 100644
--- a/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll
+++ b/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll
@@ -3,13 +3,13 @@
 ; RUN: llc -mtriple=arm-unknown-linux --call-graph-section -filetype=obj -o - 
< %s | \
 ; RUN: llvm-readelf -x .llvm.callgraph - | FileCheck %s
 
-define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
+define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 {
 entry:
   %call = tail call i32 %func(i8 signext %x), !callee_type !1
   ret i32 %call
 }
 
-define i32 @main(i32 %argc) !type !3 {
+define i32 @main(i32 %argc) !callgraph !3 {
 entry:
   %andop = and i32 %argc, 1
   %cmp = icmp eq i32 %andop, 0
@@ -18,14 +18,14 @@ entry:
   ret i32 %call.i
 }
 
-declare !type !2 i32 @foo(i8 signext)
+declare !callgraph !2 i32 @foo(i8 signext)
 
-declare !type !2 i32 @bar(i8 signext)
+declare !callgraph !2 i32 @bar(i8 signext)
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
-!3 = !{i64 0, !"_ZTSFiiE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}
+!3 = !{!"_ZTSFiiE.generalized"}
 
 ; CHECK:      Hex dump of section '.llvm.callgraph':
 ; CHECK-NEXT: 0x00000000 00050000 00008e19 0b7f3326 e3000154

diff  --git a/llvm/test/CodeGen/ARM/call-graph-section.ll 
b/llvm/test/CodeGen/ARM/call-graph-section.ll
index 167cc6f3c73bd..4d7b3f44b9353 100644
--- a/llvm/test/CodeGen/ARM/call-graph-section.ll
+++ b/llvm/test/CodeGen/ARM/call-graph-section.ll
@@ -3,11 +3,11 @@
 ; RUN: llc -mtriple=arm-unknown-linux --call-graph-section -filetype=obj -o - 
< %s | \
 ; RUN: llvm-readelf -x .llvm.callgraph - | FileCheck %s
 
-declare !type !0 void @foo()
+declare !callgraph !0 void @foo()
 
-declare !type !1 i32 @bar(i8)
+declare !callgraph !1 i32 @bar(i8)
 
-declare !type !2 ptr @baz(ptr)
+declare !callgraph !2 ptr @baz(ptr)
 
 define void @main() {
 entry:
@@ -22,12 +22,12 @@ entry:
 
 ;; Check that the numeric type id (md5 hash) for the below type ids are emitted
 ;; to the callgraph section.
-!0 = !{i64 0, !"_ZTSFvE.generalized"}
+!0 = !{!"_ZTSFvE.generalized"}
 !1 = !{!0}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}
 !3 = !{!2}
 !4 = !{!5}
-!5 = !{i64 0, !"_ZTSFPvS_E.generalized"}
+!5 = !{!"_ZTSFPvS_E.generalized"}
 
 ;; Make sure following type IDs are in call graph section
 ;; 0x5eecb3e2444f731f, 0x814b8e305486bc59, 0xf897fd777ade6814

diff  --git a/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll 
b/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
index 8f7b0506a5e39..6a474227e2b42 100644
--- a/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
@@ -7,7 +7,7 @@
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
-define i32 @foo(i32 %x, i32 %y) !type !0 {
+define i32 @foo(i32 %x, i32 %y) !callgraph !0 {
 entry:
   ;; Call instruction with accurate callee_type.
   ;; callee_type should be dropped seemlessly.
@@ -23,10 +23,10 @@ entry:
   ret i32 %sub
 }
 
-declare !type !2 i32 @fizz(i32, i32)
+declare !callgraph !2 i32 @fizz(i32, i32)
 
-!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!0 = !{!"_ZTSFiiiiE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
+!2 = !{!"_ZTSFiiiE.generalized"}
 !3 = !{!4}
-!4 = !{i64 0, !"_ZTSFicE.generalized"}
+!4 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll 
b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll
index 05e1e8bf0502b..5233da75435ab 100644
--- a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll
+++ b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll
@@ -5,7 +5,7 @@
 ;; computed as the type id from the callee_type metadata.
 ; RUN: llc --call-graph-section -mtriple arm-linux-gnu < %s 
-stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
 
-define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
+define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 {
 entry:
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
@@ -14,6 +14,6 @@ entry:
   ret i32 %call
 }
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll 
b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll
index a65e5c5f8c015..7e1ab0068ff07 100644
--- a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll
+++ b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll
@@ -17,4 +17,4 @@ entry:
 }
 
 !0 = !{!1}
-!1 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{!"_ZTSFvcE.generalized"}

diff  --git 
a/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir 
b/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir
index cb78898f3a0d4..5573be87fbb2d 100644
--- 
a/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir
+++ 
b/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir
@@ -16,8 +16,8 @@
   }
   
   !0 = !{!1, !2}
-  !1 = !{i64 0, !"callee_type0.generalized"}
-  !2 = !{i64 0, !"callee_type2.generalized"}
+  !1 = !{!"callee_type0.generalized"}
+  !2 = !{!"callee_type2.generalized"}
 ...
 ---
 name:            ambiguous_caller

diff  --git a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir 
b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
index 303b8fac22a9c..dd835abab5256 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -16,7 +16,7 @@
   }
 
   !0 = !{!1}
-  !1 = !{i64 0, !"_ZTSFvcE.generalized"}
+  !1 = !{!"_ZTSFvcE.generalized"}
 ...
 ---
 name:            call_foo

diff  --git a/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll 
b/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll
index fe1980e3f5605..c49d8152a7751 100644
--- a/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll
+++ b/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll
@@ -86,4 +86,4 @@ entry:
 }
 
 !0 = !{!1}
-!1 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{!"_ZTSFvcE.generalized"}

diff  --git a/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll 
b/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
index a66a884dc844e..1a1bc63b24a97 100644
--- a/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
@@ -7,7 +7,7 @@
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
-define i32 @foo(i32 %x, i32 %y) !type !0 {
+define i32 @foo(i32 %x, i32 %y) !callgraph !0 {
 entry:
   ;; Call instruction with accurate callee_type.
   ;; callee_type should be dropped seemlessly.
@@ -23,10 +23,10 @@ entry:
   ret i32 %sub
 }
 
-declare !type !2 i32 @fizz(i32, i32)
+declare !callgraph !2 i32 @fizz(i32, i32)
 
-!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!0 = !{!"_ZTSFiiiiE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
+!2 = !{!"_ZTSFiiiE.generalized"}
 !3 = !{!4}
-!4 = !{i64 0, !"_ZTSFicE.generalized"}
+!4 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid-tailcall.ll 
b/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid-tailcall.ll
index e7f162c6daa77..efe2fb91a85fa 100644
--- a/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid-tailcall.ll
+++ b/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid-tailcall.ll
@@ -5,7 +5,7 @@
 ;; computed as the type id from the callee_type metadata.
 ; RUN: llc --call-graph-section -mtriple=mips-linux-gnu < %s 
-stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
 
-define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
+define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 {
 entry:
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
@@ -14,6 +14,6 @@ entry:
   ret i32 %call
 }
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll 
b/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll
index 9f5e858412ed6..1b0c885bb8e44 100644
--- a/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll
+++ b/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll
@@ -17,4 +17,4 @@ entry:
 }
 
 !0 = !{!1}
-!1 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{!"_ZTSFvcE.generalized"}

diff  --git a/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll 
b/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
index 34493cec0eab0..9bdb6cef6714f 100644
--- a/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
@@ -8,7 +8,7 @@
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
-define i32 @foo(i32 %x, i32 %y) !type !0 {
+define i32 @foo(i32 %x, i32 %y) !callgraph !0 {
 entry:
   ;; Call instruction with accurate callee_type.
   ;; callee_type should be dropped seemlessly.
@@ -24,10 +24,10 @@ entry:
   ret i32 %sub
 }
 
-declare !type !2 i32 @fizz(i32, i32)
+declare !callgraph !2 i32 @fizz(i32, i32)
 
-!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!0 = !{!"_ZTSFiiiiE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
+!2 = !{!"_ZTSFiiiE.generalized"}
 !3 = !{!4}
-!4 = !{i64 0, !"_ZTSFicE.generalized"}
+!4 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll 
b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll
index 6e1fe92dac8f7..5b17a8a56664c 100644
--- a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll
+++ b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll
@@ -6,7 +6,7 @@
 ; RUN: llc --call-graph-section -mtriple riscv64 < %s 
-stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
 ; RUN: llc --call-graph-section -mtriple riscv32 < %s 
-stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
 
-define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
+define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 {
 entry:
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
@@ -15,6 +15,6 @@ entry:
   ret i32 %call
 }
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll 
b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll
index 1f91f4103abbb..ec7f4abc0bc2d 100644
--- a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll
+++ b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll
@@ -18,4 +18,4 @@ entry:
 }
 
 !0 = !{!1}
-!1 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{!"_ZTSFvcE.generalized"}

diff  --git a/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll 
b/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll
index ab8498d8d3451..06daa8fa38810 100644
--- a/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll
+++ b/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll
@@ -5,16 +5,16 @@
 
 ; RUN: llc -mtriple=x86_64-unknown-linux --call-graph-section -o - < %s | 
FileCheck %s
 
-declare !type !0 void @_Z6doWorkPFviE(ptr)
+declare !callgraph !0 void @_Z6doWorkPFviE(ptr)
 
-define i32 @_Z4testv() !type !1 {
+define i32 @_Z4testv() !callgraph !1 {
 entry:
   call void @_Z6doWorkPFviE(ptr nonnull @_ZL10myCallbacki)
   ret i32 0
 }
 
 ; CHECK: _ZL10myCallbacki:
-define internal void @_ZL10myCallbacki(i32 %value) !type !2 {
+define internal void @_ZL10myCallbacki(i32 %value) !callgraph !2 {
 entry:
   %sink = alloca i32, align 4
   store volatile i32 %value, ptr %sink, align 4
@@ -22,9 +22,9 @@ entry:
   ret void
 }
 
-!0 = !{i64 0, !"_ZTSFvPFviEE.generalized"}
-!1 = !{i64 0, !"_ZTSFivE.generalized"}
-!2 = !{i64 0, !"_ZTSFviE.generalized"}
+!0 = !{!"_ZTSFvPFviEE.generalized"}
+!1 = !{!"_ZTSFivE.generalized"}
+!2 = !{!"_ZTSFviE.generalized"}
 
 ; CHECK: .section .llvm.callgraph,"o",@llvm_call_graph,.text
 ;; Version

diff  --git a/llvm/test/CodeGen/X86/call-graph-section-assembly.ll 
b/llvm/test/CodeGen/X86/call-graph-section-assembly.ll
index 02d71073b65c5..38e2c9cbc3b47 100644
--- a/llvm/test/CodeGen/X86/call-graph-section-assembly.ll
+++ b/llvm/test/CodeGen/X86/call-graph-section-assembly.ll
@@ -6,9 +6,9 @@
 
 ; RUN: llc -mtriple=x86_64-unknown-linux --call-graph-section -o - < %s | 
FileCheck %s
 
-declare !type !0 void @direct_foo()
-declare !type !1 i32 @direct_bar(i8)
-declare !type !2 ptr @direct_baz(ptr)
+declare !callgraph !0 void @direct_foo()
+declare !callgraph !1 i32 @direct_bar(i8)
+declare !callgraph !2 ptr @direct_baz(ptr)
 
 ; CHECK: ball:
 define ptr @ball() {
@@ -29,11 +29,11 @@ entry:
 }
 
 !0 = !{!1}
-!1 = !{i64 0, !"_ZTSFvE.generalized"}
+!1 = !{!"_ZTSFvE.generalized"}
 !2 = !{!3}
-!3 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{!"_ZTSFicE.generalized"}
 !4 = !{!5}
-!5 = !{i64 0, !"_ZTSFPvS_E.generalized"}
+!5 = !{!"_ZTSFPvS_E.generalized"}
 
 ; CHECK: .section .llvm.callgraph,"o",@llvm_call_graph,.text
 ;; Version

diff  --git a/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll 
b/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll
index 49cc335bf7379..753995a9733bf 100644
--- a/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll
+++ b/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll
@@ -6,13 +6,13 @@
 ; RUN: llc -mtriple=x86_64-unknown-linux --call-graph-section -filetype=obj -o 
- < %s | \
 ; RUN: llvm-readelf -x .llvm.callgraph - | FileCheck %s
 
-define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
+define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 {
 entry:
   %call = tail call i32 %func(i8 signext %x), !callee_type !1
   ret i32 %call
 }
 
-define i32 @main(i32 %argc) !type !3 {
+define i32 @main(i32 %argc) !callgraph !3 {
 entry:
   %andop = and i32 %argc, 1
   %cmp = icmp eq i32 %andop, 0
@@ -21,14 +21,14 @@ entry:
   ret i32 %call.i
 }
 
-declare !type !2 i32 @foo(i8 signext)
+declare !callgraph !2 i32 @foo(i8 signext)
 
-declare !type !2 i32 @bar(i8 signext)
+declare !callgraph !2 i32 @bar(i8 signext)
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
-!3 = !{i64 0, !"_ZTSFiiE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}
+!3 = !{!"_ZTSFiiE.generalized"}
 
 ; CHECK: Hex dump of section '.llvm.callgraph':
 ; CHECK-NEXT: 0x00000000 00050000 00000000 00008e19 0b7f3326

diff  --git a/llvm/test/CodeGen/X86/call-graph-section.ll 
b/llvm/test/CodeGen/X86/call-graph-section.ll
index 8a1c6ca627cb5..2f08b0edc9ebf 100644
--- a/llvm/test/CodeGen/X86/call-graph-section.ll
+++ b/llvm/test/CodeGen/X86/call-graph-section.ll
@@ -6,11 +6,11 @@
 ; RUN: llc -mtriple=x86_64-unknown-linux --call-graph-section -filetype=obj -o 
- < %s | \
 ; RUN: llvm-readelf -x .llvm.callgraph - | FileCheck %s
 
-declare !type !0 void @foo()
+declare !callgraph !0 void @foo()
 
-declare !type !1 i32 @bar(i8)
+declare !callgraph !1 i32 @bar(i8)
 
-declare !type !2 ptr @baz(ptr)
+declare !callgraph !2 ptr @baz(ptr)
 
 define void @main() {
 entry:
@@ -25,12 +25,12 @@ entry:
 
 ;; Check that the numeric type id (md5 hash) for the below type ids are emitted
 ;; to the callgraph section.
-!0 = !{i64 0, !"_ZTSFvE.generalized"}
+!0 = !{!"_ZTSFvE.generalized"}
 !1 = !{!0}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}
 !3 = !{!2}
 !4 = !{!5}
-!5 = !{i64 0, !"_ZTSFPvS_E.generalized"}
+!5 = !{!"_ZTSFPvS_E.generalized"}
 
 ;; Make sure following type IDs are in call graph section
 ;; 0x5eecb3e2444f731f, 0x814b8e305486bc59, 0xf897fd777ade6814

diff  --git a/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll 
b/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
index 7881ea7d59314..92d783055d3ba 100644
--- a/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
@@ -7,7 +7,7 @@
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
 ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
-define i32 @foo(i32 %x, i32 %y) !type !0 {
+define i32 @foo(i32 %x, i32 %y) !callgraph !0 {
 entry:
   ;; Call instruction with accurate callee_type.
   ;; callee_type should be dropped seemlessly.
@@ -23,10 +23,10 @@ entry:
   ret i32 %sub
 }
 
-declare !type !2 i32 @fizz(i32, i32)
+declare !callgraph !2 i32 @fizz(i32, i32)
 
-!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!0 = !{!"_ZTSFiiiiE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
+!2 = !{!"_ZTSFiiiE.generalized"}
 !3 = !{!4}
-!4 = !{i64 0, !"_ZTSFicE.generalized"}
+!4 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll 
b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll
index 8f6b7a6d7f240..91fc652c8b05e 100644
--- a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll
+++ b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll
@@ -5,7 +5,7 @@
 ;; computed as the type id from the callee_type metadata.
 ; RUN: llc --call-graph-section -mtriple=x86_64-unknown-linux < %s 
-stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
 
-define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
+define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 {
 entry:
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
@@ -14,6 +14,6 @@ entry:
   ret i32 %call
 }
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}

diff  --git a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll 
b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll
index e97a6ac75e111..5981b58bdf7e9 100644
--- a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll
+++ b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll
@@ -17,4 +17,4 @@ entry:
 }
 
 !0 = !{!1}
-!1 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{!"_ZTSFvcE.generalized"}

diff  --git a/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll 
b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
index 547588089c5b0..5495441a45738 100644
--- a/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
+++ b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
@@ -29,13 +29,13 @@ entry:
 }
 declare !type !2 i32 @_Z3fooc(i8 signext)
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{!"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
-!3 = !{i64 0, !"_ZTSFivE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}
+!3 = !{!"_ZTSFivE.generalized"}
 ;.
-; CHECK: [[META0]] = !{i64 0, !"_ZTSFiPvcE.generalized"}
+; CHECK: [[META0]] = !{!"_ZTSFiPvcE.generalized"}
 ; CHECK: [[META1]] = !{[[META2:![0-9]+]]}
-; CHECK: [[META2]] = !{i64 0, !"_ZTSFicE.generalized"}
-; CHECK: [[META3]] = !{i64 0, !"_ZTSFivE.generalized"}
+; CHECK: [[META2]] = !{!"_ZTSFicE.generalized"}
+; CHECK: [[META3]] = !{!"_ZTSFivE.generalized"}
 ;.

diff  --git a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll 
b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
index 83215f78be1b0..e5296f96690f5 100644
--- a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
+++ b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
@@ -17,9 +17,9 @@ entry:
 
 declare !type !2 i32 @_Z3fooc(i8 signext)
 
-!0 = !{i64 0, !"_ZTSFivE.generalized"}
+!0 = !{!"_ZTSFivE.generalized"}
 !1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!2 = !{!"_ZTSFicE.generalized"}
 ;.
-; CHECK: [[META0]] = !{i64 0, !"_ZTSFivE.generalized"}
+; CHECK: [[META0]] = !{!"_ZTSFivE.generalized"}
 ;.

diff  --git a/llvm/test/Transforms/MergeFunc/callgraph-function-merging.ll 
b/llvm/test/Transforms/MergeFunc/callgraph-function-merging.ll
new file mode 100644
index 0000000000000..0202412f62fa3
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/callgraph-function-merging.ll
@@ -0,0 +1,25 @@
+; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
+
+; Verify that !callgraph metadata is correctly preserved and copied to the new
+; thunk/backing functions when two identical functions are merged, and that
+; the metadata nodes are correctly uniqued.
+
+declare void @dummy()
+
+; CHECK: define void @func1(ptr {{.*}}) {{.*}} !callgraph [[MD:![0-9]+]] {
+; CHECK: define void @func2(ptr {{.*}}) {{.*}} !callgraph [[MD]] {
+
+define void @func1(ptr %a) unnamed_addr !callgraph !0 {
+  call void @dummy()
+  ret void
+}
+
+define void @func2(ptr %a) unnamed_addr !callgraph !1 {
+  call void @dummy()
+  ret void
+}
+
+!0 = !{!"_ZTSFvPvE.generalized"}
+!1 = !{!"_ZTSFvPvE.generalized"}
+
+; CHECK: [[MD]] = !{!"_ZTSFvPvE.generalized"}

diff  --git a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll 
b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
index 3e56939b1642f..03bfb8e31d0b9 100644
--- a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
+++ b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
@@ -150,18 +150,18 @@ if.end:                                           ; preds 
= %if.else, %if.then
 
 declare ptr @_Znwm(i64)
 
-!0 = !{i64 0, !"callee_type0.generalized"}
-!1 = !{i64 0, !"callee_type1.generalized"}
-!2 = !{i64 0, !"callee_type2.generalized"}
+!0 = !{!"callee_type0.generalized"}
+!1 = !{!"callee_type1.generalized"}
+!2 = !{!"callee_type2.generalized"}
 !3 = !{!0}
 !4 = !{!2}
 !5 = !{!1, !2}
 !6 = !{!0, !2}
 ;.
 ; CHECK: [[META0]] = !{[[META1:![0-9]+]], [[META2:![0-9]+]]}
-; CHECK: [[META1]] = !{i64 0, !"callee_type2.generalized"}
-; CHECK: [[META2]] = !{i64 0, !"callee_type0.generalized"}
+; CHECK: [[META1]] = !{!"callee_type2.generalized"}
+; CHECK: [[META2]] = !{!"callee_type0.generalized"}
 ; CHECK: [[META3]] = !{[[META2]]}
 ; CHECK: [[META4]] = !{[[META2]], [[META1]], [[META5:![0-9]+]]}
-; CHECK: [[META5]] = !{i64 0, !"callee_type1.generalized"}
+; CHECK: [[META5]] = !{!"callee_type1.generalized"}
 ;.

diff  --git a/llvm/test/Verifier/callee-type-metadata.ll 
b/llvm/test/Verifier/callee-type-metadata.ll
index 50cf37b941fe9..e40d36ae0f234 100644
--- a/llvm/test/Verifier/callee-type-metadata.ll
+++ b/llvm/test/Verifier/callee-type-metadata.ll
@@ -9,16 +9,14 @@ entry:
   store i8 %x, ptr %x.addr, align 1
   %fptr = load ptr, ptr %func.addr, align 8
   %x_val = load i8, ptr %x.addr, align 1  
-  ; CHECK: The callee_type metadata must be a list of type metadata nodes
+  ; CHECK: The callee_type metadata must be a list of callgraph metadata nodes
   %call = call i32 %fptr(i8 signext %x_val), !callee_type !0
-  ; CHECK: Well-formed generalized type metadata must contain exactly two 
operands
+  ; CHECK: The operand of callgraph metadata for functions must be an MDString
   %call1 = call i32 %fptr(i8 signext %x_val), !callee_type !2
-  ; CHECK: The first operand of type metadata for functions must be zero
+  ; CHECK: Well-formed generalized callgraph metadata must contain exactly one 
operand
   %call2 = call i32 %fptr(i8 signext %x_val), !callee_type !4
-  ; CHECK: The first operand of type metadata for functions must be zero
+  ; CHECK: Only generalized callgraph metadata can be part of the callee_type 
metadata list
   %call3 = call i32 %fptr(i8 signext %x_val), !callee_type !6
-  ; CHECK: Only generalized type metadata can be part of the callee_type 
metadata list
-  %call4 = call i32 %fptr(i8 signext %x_val), !callee_type !8
   ret i32 %call
 }
 
@@ -27,7 +25,5 @@ entry:
 !2 = !{!2}
 !3 = !{i64 1, !"_ZTSFicE"}
 !4 = !{!3}
-!5 = !{!"expected_int", !"_ZTSFicE"}
+!5 = !{!"_ZTSFicE"}
 !6 = !{!5}
-!7 = !{i64 0, !"_ZTSFicE"}
-!8 = !{!7}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to