[clang] [llvm] [llvm] Add CalleeTypeIds field to CallSiteInfo (PR #87574)

Prabhu Rajasekaran via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 22 19:51:40 PDT 2025


https://github.com/Prabhuk updated https://github.com/llvm/llvm-project/pull/87574

>From 00ac51b3053257575de9bc167be2822db2c87e1e Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Wed, 3 Apr 2024 15:47:56 -0700
Subject: [PATCH 01/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 clang/docs/CallGraphSection.rst               | 251 ++++++++++++++++++
 clang/include/clang/Basic/CodeGenOptions.def  |   2 +
 clang/include/clang/Driver/Options.td         |   4 +
 clang/lib/CodeGen/BackendUtil.cpp             |   1 +
 clang/lib/CodeGen/CGCall.cpp                  |  22 ++
 clang/lib/CodeGen/CGClass.cpp                 |   9 +-
 clang/lib/CodeGen/CGExpr.cpp                  |   5 +
 clang/lib/CodeGen/CGExprCXX.cpp               |  34 ++-
 clang/lib/CodeGen/CGObjCMac.cpp               |   8 +
 clang/lib/CodeGen/CodeGenModule.cpp           |  34 ++-
 clang/lib/CodeGen/CodeGenModule.h             |   4 +
 clang/lib/Driver/ToolChains/Clang.cpp         |   4 +
 clang/test/CodeGen/call-graph-section-1.cpp   | 110 ++++++++
 clang/test/CodeGen/call-graph-section-2.cpp   |  95 +++++++
 clang/test/CodeGen/call-graph-section-3.cpp   |  52 ++++
 clang/test/CodeGen/call-graph-section.c       |  85 ++++++
 clang/test/Driver/call-graph-section.c        |   5 +
 llvm/include/llvm/CodeGen/CommandFlags.h      |   2 +
 llvm/include/llvm/IR/LLVMContext.h            |   1 +
 llvm/include/llvm/Target/TargetOptions.h      |   5 +-
 llvm/lib/AsmParser/LLParser.cpp               |  16 +-
 llvm/lib/CodeGen/CommandFlags.cpp             |   7 +
 .../SelectionDAG/SelectionDAGBuilder.cpp      |  10 +-
 llvm/lib/IR/LLVMContext.cpp                   |   5 +
 llvm/lib/IR/Verifier.cpp                      |   7 +-
 ...21-07-22-Parse-Metadata-Operand-Bundles.ll |   9 +
 llvm/test/Verifier/operand-bundles.ll         |  13 +
 27 files changed, 780 insertions(+), 20 deletions(-)
 create mode 100644 clang/docs/CallGraphSection.rst
 create mode 100644 clang/test/CodeGen/call-graph-section-1.cpp
 create mode 100644 clang/test/CodeGen/call-graph-section-2.cpp
 create mode 100644 clang/test/CodeGen/call-graph-section-3.cpp
 create mode 100644 clang/test/CodeGen/call-graph-section.c
 create mode 100644 clang/test/Driver/call-graph-section.c
 create mode 100644 llvm/test/Bitcode/2021-07-22-Parse-Metadata-Operand-Bundles.ll

diff --git a/clang/docs/CallGraphSection.rst b/clang/docs/CallGraphSection.rst
new file mode 100644
index 0000000000000..d5db507f9ca9a
--- /dev/null
+++ b/clang/docs/CallGraphSection.rst
@@ -0,0 +1,251 @@
+==================
+Call Graph Section
+==================
+
+Introduction
+============
+
+With ``-fcall-graph-section``, the compiler will create a call graph section 
+in the object file. It will include type identifiers for indirect calls and 
+targets. This information can be used to map indirect calls to their receivers 
+with matching types. A complete and high-precision call graph can be 
+reconstructed by complementing this information with disassembly 
+(see ``llvm-objdump --call-graph-info``).
+
+Semantics
+=========
+
+A coarse-grained, type-agnostic call graph may allow indirect calls to target
+any function in the program. This approach ensures completeness since no
+indirect call edge is missing. However, it is generally poor in precision
+due to having unneeded edges.
+
+A call graph section provides type identifiers for indirect calls and targets.
+This information can be used to restrict the receivers of an indirect target to
+indirect calls with matching type. Consequently, the precision for indirect
+call edges are improved while maintaining the completeness.
+
+The ``llvm-objdump`` utility provides a ``--call-graph-info`` option to extract
+full call graph information by parsing the content of the call graph section
+and disassembling the program for complementary information, e.g., direct
+calls.
+
+Section layout
+==============
+
+A call graph section consists of zero or more call graph entries.
+Each entry contains information on a function and its indirect calls.
+
+An entry of a call graph section has the following layout in the binary:
+
++---------------------+-----------------------------------------------------------------------+
+| Element             | Content                                                               |
++=====================+=======================================================================+
+| FormatVersionNumber | Format version number.                                                |
++---------------------+-----------------------------------------------------------------------+
+| FunctionEntryPc     | Function entry address.                                               |
++---------------------+-----------------------------------+-----------------------------------+
+|                     | A flag whether the function is an | - 0: not an indirect target       |
+| FunctionKind        | indirect target, and if so,       | - 1: indirect target, unknown id  |
+|                     | whether its type id is known.     | - 2: indirect target, known id    |
++---------------------+-----------------------------------+-----------------------------------+
+| FunctionTypeId      | Type id for the indirect target. Present only when FunctionKind is 2. |
++---------------------+-----------------------------------------------------------------------+
+| CallSiteCount       | Number of type id to indirect call site mappings that follow.         |
++---------------------+-----------------------------------------------------------------------+
+| CallSiteList        | List of type id and indirect call site pc pairs.                      |
++---------------------+-----------------------------------------------------------------------+
+
+Each element in an entry (including each element of the contained lists and
+pairs) occupies 64-bit space.
+
+The format version number is repeated per entry to support concatenation of
+call graph sections with different format versions by the linker.
+
+As of now, the only supported format version is described above and has version
+number 0.
+
+Type identifiers
+================
+
+The type for an indirect call or target is the function signature.
+The mapping from a type to an identifier is an ABI detail.
+In the current experimental 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 separate types.
+
+Missing type identifiers
+========================
+
+For functions, two cases need to be considered. First, if the compiler cannot
+deduce a type id for an indirect target, it will be listed as an indirect target
+without a type id. Second, if an object without a call graph section gets
+linked, the final call graph section will lack information on functions from
+the object. For completeness, these functions need to be taken as receiver to
+any indirect call regardless of their type id.
+``llvm-objdump --call-graph-info`` lists these functions as indirect targets
+with `UNKNOWN` type id.
+
+For indirect calls, current implementation guarantees a type id for each
+compiled call. However, if an object without a call graph section gets linked,
+no type id will be present for its indirect calls. For completeness, these calls
+need to be taken to target any indirect target regardless of their type id. For
+indirect calls, ``llvm-objdump --call-graph-info`` prints 1) a complete list of
+indirect calls, 2) type id to indirect call mappings. The difference of these
+lists allow to deduce the indirect calls with missing type ids.
+
+TODO: measure and report the ratio of missed type ids
+
+Performance
+===========
+
+A call graph section does not affect the executable code and does not occupy
+memory during process execution. Therefore, there is no performance overhead.
+
+The scheme has not yet been optimized for binary size.
+
+TODO: measure and report the increase in the binary size
+
+Example
+=======
+
+For example, consider the following C++ code:
+
+.. code-block:: cpp
+
+    namespace {
+      // Not an indirect target
+      void foo() {}
+    }
+
+    // Indirect target 1
+    void bar() {}
+
+    // Indirect target 2
+    int baz(char a, float *b) {
+      return 0;
+    }
+
+    // Indirect target 3
+    int main() {
+      char a;
+      float b;
+      void (*fp_bar)() = bar;
+      int (*fp_baz1)(char, float*) = baz;
+      int (*fp_baz2)(char, float*) = baz;
+
+      // Indirect call site 1
+      fp_bar();
+
+      // Indirect call site 2
+      fp_baz1(a, &b);
+
+      // Indirect call site 3: shares the type id with indirect call site 2
+      fp_baz2(a, &b);
+
+      // Direct call sites
+      foo();
+      bar();
+      baz(a, &b);
+
+      return 0;
+    }
+
+Following will compile it with a call graph section created in the binary:
+
+.. code-block:: bash
+
+  $ clang -fcall-graph-section example.cpp
+
+During the construction of the call graph section, the type identifiers are 
+computed as follows:
+
++---------------+-----------------------+----------------------------+----------------------------+
+| Function name | Generalized signature | Mangled name (itanium ABI) | Numeric type id (md5 hash) |
++===============+=======================+============================+============================+
+|  bar          | void ()               | _ZTSFvvE.generalized       | f85c699bb8ef20a2           |
++---------------+-----------------------+----------------------------+----------------------------+
+|  baz          | int (char, void*)     | _ZTSFicPvE.generalized     | e3804d2a7f2b03fe           |
++---------------+-----------------------+----------------------------+----------------------------+
+|  main         | int ()                | _ZTSFivE.generalized       | a9494def81a01dc            |
++---------------+-----------------------+----------------------------+----------------------------+
+
+The call graph section will have the following content:
+
++---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
+| FormatVersion | FunctionEntryPc | FunctionKind | FunctionTypeId | CallSiteCount | CallSiteList                         |
++===============+=================+==============+================+===============+======================================+
+| 0             | EntryPc(foo)    | 0            | (empty)        | 0             | (empty)                              |
++---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
+| 0             | EntryPc(bar)    | 2            | TypeId(bar)    | 0             | (empty)                              |
++---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
+| 0             | EntryPc(baz)    | 2            | TypeId(baz)    | 0             | (empty)                              |
++---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
+| 0             | EntryPc(main)   | 2            | TypeId(main)   | 3             | * TypeId(bar), CallSitePc(fp_bar())  |
+|               |                 |              |                |               | * TypeId(baz), CallSitePc(fp_baz1()) |
+|               |                 |              |                |               | * TypeId(baz), CallSitePc(fp_baz2()) |
++---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
+
+
+The ``llvm-objdump`` utility can parse the call graph section and disassemble
+the program to provide complete call graph information. This includes any
+additional call sites from the binary:
+
+.. code-block:: bash
+
+    $ llvm-objdump --call-graph-info a.out
+
+    # Comments are not a part of the llvm-objdump's output but inserted for clarifications.
+
+    a.out:  file format elf64-x86-64
+    # These warnings are due to the functions and the indirect calls coming from linked objects.
+    llvm-objdump: warning: 'a.out': callgraph section does not have type ids for 3 indirect calls
+    llvm-objdump: warning: 'a.out': callgraph section does not have information for 10 functions
+
+    # Unknown targets are the 10 functions the warnings mention.
+    INDIRECT TARGET TYPES (TYPEID [FUNC_ADDR,])
+    UNKNOWN 401000 401100 401234 401050 401090 4010d0 4011d0 401020 401060 401230
+    a9494def81a01dc 401150            # main()
+    f85c699bb8ef20a2 401120           # bar()
+    e3804d2a7f2b03fe 401130           # baz()
+
+    # Notice that the call sites share the same type id as target functions
+    INDIRECT CALL TYPES (TYPEID [CALL_SITE_ADDR,])
+    f85c699bb8ef20a2 401181           # Indirect call site 1 (fp_bar())
+    e3804d2a7f2b03fe 401191 4011a1    # Indirect call site 2 and 3 (fp_baz1() and fp_baz2())
+
+    INDIRECT CALL SITES (CALLER_ADDR [CALL_SITE_ADDR,])
+    401000 401012                     # _init
+    401150 401181 401191 4011a1       # main calls fp_bar(), fp_baz1(), fp_baz2()
+    4011d0 401215                     # __libc_csu_init
+    401020 40104a                     # _start
+
+    DIRECT CALL SITES (CALLER_ADDR [(CALL_SITE_ADDR, TARGET_ADDR),])
+    4010d0 4010e2 401060              # __do_global_dtors_aux
+    401150 4011a6 401110 4011ab 401120 4011ba 401130   # main calls foo(), bar(), baz()
+    4011d0 4011fd 401000              # __libc_csu_init
+
+    FUNCTIONS (FUNC_ENTRY_ADDR, SYM_NAME)
+    401000 _init
+    401100 frame_dummy
+    401234 _fini
+    401050 _dl_relocate_static_pie
+    401090 register_tm_clones
+    4010d0 __do_global_dtors_aux
+    401110 _ZN12_GLOBAL__N_13fooEv    # (anonymous namespace)::foo()
+    401150 main                       # main
+    4011d0 __libc_csu_init
+    401020 _start
+    401060 deregister_tm_clones
+    401120 _Z3barv                    # bar()
+    401130 _Z3bazcPf                  # baz(char, float*)
+    401230 __libc_csu_fini
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 340b08dd7e2a3..9a8d62918a73d 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -76,6 +76,8 @@ CODEGENOPT(EnableNoundefAttrs, 1, 0) ///< Enable emitting `noundef` attributes o
 CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
                                    ///< pass manager.
 CODEGENOPT(DisableRedZone    , 1, 0) ///< Set when -mno-red-zone is enabled.
+CODEGENOPT(CallGraphSection, 1, 0) ///< Emit a call graph section into the
+                                   ///< object file.
 CODEGENOPT(EmitCallSiteInfo, 1, 0) ///< Emit call site info only in the case of
                                    ///< '-g' + 'O>0' level.
 CODEGENOPT(IndirectTlsSegRefs, 1, 0) ///< Set when -mno-tls-direct-seg-refs
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index c3e90a70925b7..3023ae91c1a8d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4081,6 +4081,10 @@ defm data_sections : BoolFOption<"data-sections",
   PosFlag<SetTrue, [], [ClangOption, CC1Option],
           "Place each data in its own section">,
   NegFlag<SetFalse>>;
+defm call_graph_section : BoolFOption<"call-graph-section",
+  CodeGenOpts<"CallGraphSection">, DefaultFalse,
+  PosFlag<SetTrue, [], [CC1Option], "Emit a call graph section">,
+  NegFlag<SetFalse>>;
 defm stack_size_section : BoolFOption<"stack-size-section",
   CodeGenOpts<"StackSizeSection">, DefaultFalse,
   PosFlag<SetTrue, [], [ClangOption, CC1Option],
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index c8b2a93ae47ad..cba4064bbb5c6 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -420,6 +420,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
   Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;
   Options.EmitAddrsig = CodeGenOpts.Addrsig;
   Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
+  Options.EmitCallGraphSection = CodeGenOpts.CallGraphSection;
   Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;
   Options.EnableAIXExtendedAltivecABI = LangOpts.EnableAIXExtendedAltivecABI;
   Options.XRayFunctionIndex = CodeGenOpts.XRayFunctionIndex;
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index f12765b826935..51133b0a9d47c 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5681,6 +5681,28 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
   AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs);
   Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs);
 
+  if (CGM.getCodeGenOpts().CallGraphSection) {
+    // FIXME: create operand bundle only for indirect calls, not for all
+
+    assert((TargetDecl && TargetDecl->getFunctionType() ||
+            Callee.getAbstractInfo().getCalleeFunctionProtoType()) &&
+           "cannot find callsite type");
+
+    QualType CST;
+    if (TargetDecl && TargetDecl->getFunctionType())
+      CST = QualType(TargetDecl->getFunctionType(), 0);
+    else if (const auto *FPT =
+                 Callee.getAbstractInfo().getCalleeFunctionProtoType())
+      CST = QualType(FPT, 0);
+
+    if (!CST.isNull()) {
+      auto *TypeIdMD = CGM.CreateMetadataIdentifierGeneralized(CST);
+      auto *TypeIdMDVal =
+          llvm::MetadataAsValue::get(getLLVMContext(), TypeIdMD);
+      BundleList.emplace_back("type", TypeIdMDVal);
+    }
+  }
+
   // Emit the actual call/invoke instruction.
   llvm::CallBase *CI;
   if (!InvokeDest) {
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 8c1c8ee455d2e..2c347bd435926 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -2247,7 +2247,14 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
   const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(
       Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs);
   CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type));
-  EmitCall(Info, Callee, ReturnValueSlot(), Args, nullptr, false, Loc);
+  llvm::CallBase *CallOrInvoke = nullptr;
+  EmitCall(Info, Callee, ReturnValueSlot(), Args, &CallOrInvoke, false, Loc);
+
+  // Set type identifier metadata of indirect calls for call graph section.
+  if (CGM.getCodeGenOpts().CallGraphSection && CallOrInvoke &&
+      CallOrInvoke->isIndirectCall())
+    CGM.CreateFunctionTypeMetadataForIcall(D->getType(), CallOrInvoke);
+
 
   // Generate vtable assumptions if we're constructing a complete object
   // with a vtable.  We don't do this for base subobjects for two reasons:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 54432353e7420..467a7cfe50e79 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5953,6 +5953,11 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
     }
   }
 
+  // Set type identifier metadata of indirect calls for call graph section.
+  if (CGM.getCodeGenOpts().CallGraphSection && CallOrInvoke &&
+      CallOrInvoke->isIndirectCall())
+    CGM.CreateFunctionTypeMetadataForIcall(QualType(FnType, 0), CallOrInvoke);
+
   return Call;
 }
 
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index a4fb673284cec..4cbffd7073867 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -93,9 +93,17 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
       *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
   auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(
       Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize);
-  return EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr,
+  llvm::CallBase *CallOrInvoke = nullptr;        
+  auto Call = EmitCall(FnInfo, Callee, ReturnValue, Args, &CallOrInvoke,
                   CE && CE == MustTailCall,
                   CE ? CE->getExprLoc() : SourceLocation());
+  
+  // Set type identifier metadata of indirect calls for call graph section.
+  if (CGM.getCodeGenOpts().CallGraphSection && CallOrInvoke &&
+      CallOrInvoke->isIndirectCall())
+    CGM.CreateFunctionTypeMetadataForIcall(MD->getType(), CallOrInvoke);
+
+  return Call;                    
 }
 
 RValue CodeGenFunction::EmitCXXDestructorCall(
@@ -119,9 +127,17 @@ RValue CodeGenFunction::EmitCXXDestructorCall(
   CallArgList Args;
   commonEmitCXXMemberOrOperatorCall(*this, Dtor, This, ImplicitParam,
                                     ImplicitParamTy, CE, Args, nullptr);
-  return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee,
-                  ReturnValueSlot(), Args, nullptr, CE && CE == MustTailCall,
+  llvm::CallBase *CallOrInvoke = nullptr;
+  auto Call = EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee,
+                  ReturnValueSlot(), Args, &CallOrInvoke, CE && CE == MustTailCall,
                   CE ? CE->getExprLoc() : SourceLocation{});
+
+  // Set type identifier metadata of indirect calls for call graph section.
+  if (CGM.getCodeGenOpts().CallGraphSection && CallOrInvoke &&
+      CallOrInvoke->isIndirectCall())
+    CGM.CreateFunctionTypeMetadataForIcall(DtorDecl->getType(), CallOrInvoke);
+
+  return Call;
 }
 
 RValue CodeGenFunction::EmitCXXPseudoDestructorExpr(
@@ -482,10 +498,18 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
 
   // And the rest of the call args
   EmitCallArgs(Args, FPT, E->arguments());
-  return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required,
+  llvm::CallBase *CallOrInvoke = nullptr;
+  auto Call = EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required,
                                                       /*PrefixSize=*/0),
-                  Callee, ReturnValue, Args, nullptr, E == MustTailCall,
+                  Callee, ReturnValue, Args, &CallOrInvoke, E == MustTailCall,
                   E->getExprLoc());
+
+  // Set type identifier metadata of indirect calls for call graph section.
+  if (CGM.getCodeGenOpts().CallGraphSection && CallOrInvoke &&
+      CallOrInvoke->isIndirectCall())
+    CGM.CreateFunctionTypeMetadataForIcall(QualType(FPT, 0), CallOrInvoke);
+
+  return Call;                  
 }
 
 RValue
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 8a599c10e1caf..291f5aff89ec2 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -2220,6 +2220,14 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
   RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
                                &CallSite);
 
+  // Set type identifier metadata of indirect calls for call graph section.
+  if (CGM.getCodeGenOpts().CallGraphSection && Method && CallSite &&
+      CallSite->isIndirectCall()) {
+    if (const auto *FnType = Method->getFunctionType()) {
+      CGM.CreateFunctionTypeMetadataForIcall(QualType(FnType, 0), CallSite);
+    }
+  }
+
   // Mark the call as noreturn if the method is marked noreturn and the
   // receiver cannot be null.
   if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 00b3bfcaa0bc2..e19bbee996f58 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2486,8 +2486,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
 
   // In the cross-dso CFI mode with canonical jump tables, we want !type
   // attributes on definitions only.
-  if (CodeGenOpts.SanitizeCfiCrossDso &&
-      CodeGenOpts.SanitizeCfiCanonicalJumpTables) {
+  if ((CodeGenOpts.SanitizeCfiCrossDso &&
+      CodeGenOpts.SanitizeCfiCanonicalJumpTables) || CodeGenOpts.CallGraphSection) {
     if (auto *FD = dyn_cast<FunctionDecl>(D)) {
       // Skip available_externally functions. They won't be codegen'ed in the
       // current module anyway.
@@ -2677,7 +2677,17 @@ static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) {
 
 void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
                                                        llvm::Function *F) {
-  // Only if we are checking indirect calls.
+  bool EmittedMDIdGeneralized = false;
+  if (CodeGenOpts.CallGraphSection &&
+      (!F->hasLocalLinkage() ||
+       F->getFunction().hasAddressTaken(nullptr, /* IgnoreCallbackUses */ true,
+                                        /* IgnoreAssumeLikeCalls */ true,
+                                        /* IgnoreLLVMUsed */ false))) {
+    F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
+    EmittedMDIdGeneralized = true;
+  }
+
+  // Add additional metadata only if we are checking indirect calls with CFI.
   if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall))
     return;
 
@@ -2688,7 +2698,9 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
 
   llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
   F->addTypeMetadata(0, MD);
-  F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
+  // Add the generalized identifier if not added already.
+  if (!EmittedMDIdGeneralized)
+    F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
 
   // Emit a hash-based bit set entry for cross-DSO calls.
   if (CodeGenOpts.SanitizeCfiCrossDso)
@@ -2696,6 +2708,17 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
       F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId));
 }
 
+void CodeGenModule::CreateFunctionTypeMetadataForIcall(const QualType &QT,
+                                                       llvm::CallBase *CB) {
+  // Only if needed for call graph section and only for indirect calls.
+  if (!(CodeGenOpts.CallGraphSection && CB && CB->isIndirectCall()))
+    return;
+
+  auto *MD = CreateMetadataIdentifierGeneralized(QT);
+  auto *MDN = llvm::MDNode::get(getLLVMContext(), MD);
+  CB->setMetadata(llvm::LLVMContext::MD_type, MDN);
+}
+
 void CodeGenModule::setKCFIType(const FunctionDecl *FD, llvm::Function *F) {
   llvm::LLVMContext &Ctx = F->getContext();
   llvm::MDBuilder MDB(Ctx);
@@ -2823,7 +2846,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
   // are non-canonical then we need type metadata in order to produce the local
   // jump table.
   if (!CodeGenOpts.SanitizeCfiCrossDso ||
-      !CodeGenOpts.SanitizeCfiCanonicalJumpTables)
+      !CodeGenOpts.SanitizeCfiCanonicalJumpTables ||
+      CodeGenOpts.CallGraphSection)
     CreateFunctionTypeMetadataForIcall(FD, F);
 
   if (LangOpts.Sanitize.has(SanitizerKind::KCFI))
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 1cc447765e2c9..12ac8d0f57eec 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1473,6 +1473,10 @@ class CodeGenModule : public CodeGenTypeCache {
   void CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
                                           llvm::Function *F);
 
+  /// Create and attach type metadata to the given call.
+  void CreateFunctionTypeMetadataForIcall(const QualType &QT,
+                                          llvm::CallBase *CB);
+
   /// Set type metadata to the given function.
   void setKCFIType(const FunctionDecl *FD, llvm::Function *F);
 
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index b7ec7e0a60977..7cc2d9a521e6b 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6407,6 +6407,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back(A->getValue());
   }
 
+  if (Args.hasFlag(options::OPT_fcall_graph_section,
+                   options::OPT_fno_call_graph_section, false))
+    CmdArgs.push_back("-fcall-graph-section");
+
   Args.addOptInFlag(CmdArgs, options::OPT_fstack_size_section,
                     options::OPT_fno_stack_size_section);
 
diff --git a/clang/test/CodeGen/call-graph-section-1.cpp b/clang/test/CodeGen/call-graph-section-1.cpp
new file mode 100644
index 0000000000000..25397e94422b7
--- /dev/null
+++ b/clang/test/CodeGen/call-graph-section-1.cpp
@@ -0,0 +1,110 @@
+// Tests that we assign appropriate identifiers to indirect calls and targets
+// specifically for C++ class and instance methods.
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \
+// RUN: -emit-llvm -o %t %s
+// RUN: FileCheck --check-prefix=FT %s < %t
+// RUN: FileCheck --check-prefix=CST %s < %t
+
+////////////////////////////////////////////////////////////////////////////////
+// Class definitions (check for indirect target metadata)
+
+class Cls1 {
+public:
+  // FT-DAG: define {{.*}} ptr @_ZN4Cls18receiverEPcPf({{.*}} !type [[F_TCLS1RECEIVER:![0-9]+]]
+  static int *receiver(char *a, float *b) { return 0; }
+};
+
+class Cls2 {
+public:
+  int *(*fp)(char *, float *);
+
+  // FT-DAG: define {{.*}} i32 @_ZN4Cls22f1Ecfd({{.*}} !type [[F_TCLS2F1:![0-9]+]]
+  int f1(char a, float b, double c) { return 0; }
+
+  // FT-DAG: define {{.*}} ptr @_ZN4Cls22f2EPcPfPd({{.*}} !type [[F_TCLS2F2:![0-9]+]]
+  int *f2(char *a, float *b, double *c) { return 0; }
+
+  // FT-DAG: define {{.*}} void @_ZN4Cls22f3E4Cls1({{.*}} !type [[F_TCLS2F3F4:![0-9]+]]
+  void f3(Cls1 a) {}
+
+  // FT-DAG: define {{.*}} void @_ZN4Cls22f4E4Cls1({{.*}} !type [[F_TCLS2F3F4]]
+  void f4(const Cls1 a) {}
+
+  // FT-DAG: define {{.*}} void @_ZN4Cls22f5EP4Cls1({{.*}} !type [[F_TCLS2F5:![0-9]+]]
+  void f5(Cls1 *a) {}
+
+  // FT-DAG: define {{.*}} void @_ZN4Cls22f6EPK4Cls1({{.*}} !type [[F_TCLS2F6:![0-9]+]]
+  void f6(const Cls1 *a) {}
+
+  // FT-DAG: define {{.*}} void @_ZN4Cls22f7ER4Cls1({{.*}} !type [[F_TCLS2F7:![0-9]+]]
+  void f7(Cls1 &a) {}
+
+  // FT-DAG: define {{.*}} void @_ZN4Cls22f8ERK4Cls1({{.*}} !type [[F_TCLS2F8:![0-9]+]]
+  void f8(const Cls1 &a) {}
+
+  // FT-DAG: define {{.*}} void @_ZNK4Cls22f9Ev({{.*}} !type [[F_TCLS2F9:![0-9]+]]
+  void f9() const {}
+};
+
+// FT-DAG: [[F_TCLS1RECEIVER]] = !{i64 0, !"_ZTSFPvS_S_E.generalized"}
+// FT-DAG: [[F_TCLS2F2]]   = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"}
+// FT-DAG: [[F_TCLS2F1]]   = !{i64 0, !"_ZTSFicfdE.generalized"}
+// FT-DAG: [[F_TCLS2F3F4]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
+// FT-DAG: [[F_TCLS2F5]]   = !{i64 0, !"_ZTSFvPvE.generalized"}
+// FT-DAG: [[F_TCLS2F6]]   = !{i64 0, !"_ZTSFvPKvE.generalized"}
+// FT-DAG: [[F_TCLS2F7]]   = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
+// FT-DAG: [[F_TCLS2F8]]   = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
+// FT-DAG: [[F_TCLS2F9]]   = !{i64 0, !"_ZTSKFvvE.generalized"}
+
+////////////////////////////////////////////////////////////////////////////////
+// Callsites (check for indirect callsite operand bundles)
+
+// CST-LABEL: define {{.*}} @_Z3foov
+void foo() {
+  Cls2 ObjCls2;
+  ObjCls2.fp = &Cls1::receiver;
+
+  // CST: call noundef ptr %{{.*}} [ "type"(metadata !"_ZTSFPvS_S_E.generalized") ]
+  ObjCls2.fp(0, 0);
+
+  auto fp_f1 = &Cls2::f1;
+  auto fp_f2 = &Cls2::f2;
+  auto fp_f3 = &Cls2::f3;
+  auto fp_f4 = &Cls2::f4;
+  auto fp_f5 = &Cls2::f5;
+  auto fp_f6 = &Cls2::f6;
+  auto fp_f7 = &Cls2::f7;
+  auto fp_f8 = &Cls2::f8;
+  auto fp_f9 = &Cls2::f9;
+
+  Cls2 *ObjCls2Ptr = &ObjCls2;
+  Cls1 Cls1Param;
+
+  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFicfdE.generalized") ]
+  (ObjCls2Ptr->*fp_f1)(0, 0, 0);
+
+  // CST: call noundef ptr %{{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
+  (ObjCls2Ptr->*fp_f2)(0, 0, 0);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ]
+  (ObjCls2Ptr->*fp_f3)(Cls1Param);
+
+  // CST: call void  %{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ]
+  (ObjCls2Ptr->*fp_f4)(Cls1Param);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPvE.generalized") ]
+  (ObjCls2Ptr->*fp_f5)(&Cls1Param);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPKvE.generalized") ]
+  (ObjCls2Ptr->*fp_f6)(&Cls1Param);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvR4Cls1E.generalized") ]
+  (ObjCls2Ptr->*fp_f7)(Cls1Param);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvRK4Cls1E.generalized") ]
+  (ObjCls2Ptr->*fp_f8)(Cls1Param);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSKFvvE.generalized") ]
+  (ObjCls2Ptr->*fp_f9)();
+}
diff --git a/clang/test/CodeGen/call-graph-section-2.cpp b/clang/test/CodeGen/call-graph-section-2.cpp
new file mode 100644
index 0000000000000..4187faea495be
--- /dev/null
+++ b/clang/test/CodeGen/call-graph-section-2.cpp
@@ -0,0 +1,95 @@
+// Tests that we assign appropriate identifiers to indirect calls and targets
+// specifically for C++ templates.
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \
+// RUN: -emit-llvm -o %t %s
+// RUN: FileCheck --check-prefix=FT    %s < %t
+// RUN: FileCheck --check-prefix=CST   %s < %t
+// RUN: FileCheck --check-prefix=CHECK %s < %t
+
+////////////////////////////////////////////////////////////////////////////////
+// Class definitions and template classes (check for indirect target metadata)
+
+class Cls1 {};
+
+// Cls2 is instantiated with T=Cls1 in foo(). Following checks are for this
+// instantiation.
+template <class T>
+class Cls2 {
+public:
+  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f1Ev({{.*}} !type [[F_TCLS2F1:![0-9]+]]
+  void f1() {}
+
+  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f2ES0_({{.*}} !type [[F_TCLS2F2:![0-9]+]]
+  void f2(T a) {}
+
+  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f3EPS0_({{.*}} !type [[F_TCLS2F3:![0-9]+]]
+  void f3(T *a) {}
+
+  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f4EPKS0_({{.*}} !type [[F_TCLS2F4:![0-9]+]]
+  void f4(const T *a) {}
+
+  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f5ERS0_({{.*}} !type [[F_TCLS2F5:![0-9]+]]
+  void f5(T &a) {}
+
+  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f6ERKS0_({{.*}} !type [[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-DAG: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFvvE.generalized"}
+// FT-DAG: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
+// FT-DAG: [[F_TCLS2F3]] = !{i64 0, !"_ZTSFvPvE.generalized"}
+// FT-DAG: [[F_TCLS2F4]] = !{i64 0, !"_ZTSFvPKvE.generalized"}
+// FT-DAG: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
+// FT-DAG: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
+
+////////////////////////////////////////////////////////////////////////////////
+// Callsites (check for indirect callsite operand bundles)
+
+template <class T>
+T *T_func(T a, T *b, const T *c, T &d, const T &e) { return b; }
+
+// CST-LABEL: define {{.*}} @_Z3foov
+void foo() {
+  // Methods for Cls2<Cls1> is checked above within the template description.
+  Cls2<Cls1> Obj;
+
+  // CHECK-DAG: define {{.*}} @_Z6T_funcI4Cls1EPT_S1_S2_PKS1_RS1_RS3_({{.*}} !type [[F_TFUNC_CLS1:![0-9]+]]
+  // CHECK-DAG: [[F_TFUNC_CLS1]] = !{i64 0, !"_ZTSFPv4Cls1S_PKvRS0_RKS0_E.generalized"}
+  Obj.fp = T_func<Cls1>;
+  Cls1 Cls1Obj;
+
+  // CST: call noundef ptr %{{.*}} [ "type"(metadata !"_ZTSFPv4Cls1S_PKvRS0_RKS0_E.generalized") ]
+  Obj.fp(Cls1Obj, &Cls1Obj, &Cls1Obj, Cls1Obj, Cls1Obj);
+
+  // Make indirect calls to Cls2's member methods
+  auto fp_f1 = &Cls2<Cls1>::f1;
+  auto fp_f2 = &Cls2<Cls1>::f2;
+  auto fp_f3 = &Cls2<Cls1>::f3;
+  auto fp_f4 = &Cls2<Cls1>::f4;
+  auto fp_f5 = &Cls2<Cls1>::f5;
+  auto fp_f6 = &Cls2<Cls1>::f6;
+
+  auto *Obj2Ptr = &Obj;
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvvE.generalized") ]
+  (Obj2Ptr->*fp_f1)();
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ]
+  (Obj2Ptr->*fp_f2)(Cls1Obj);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPvE.generalized") ]
+  (Obj2Ptr->*fp_f3)(&Cls1Obj);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPKvE.generalized") ]
+  (Obj2Ptr->*fp_f4)(&Cls1Obj);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvR4Cls1E.generalized") ]
+  (Obj2Ptr->*fp_f5)(Cls1Obj);
+
+  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvRK4Cls1E.generalized") ]
+  (Obj2Ptr->*fp_f6)(Cls1Obj);
+}
diff --git a/clang/test/CodeGen/call-graph-section-3.cpp b/clang/test/CodeGen/call-graph-section-3.cpp
new file mode 100644
index 0000000000000..77bb110c664ef
--- /dev/null
+++ b/clang/test/CodeGen/call-graph-section-3.cpp
@@ -0,0 +1,52 @@
+// Tests that we assign appropriate identifiers to indirect calls and targets
+// specifically for virtual methods.
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \
+// RUN: -emit-llvm -o %t %s
+// RUN: FileCheck --check-prefix=FT %s < %t
+// RUN: FileCheck --check-prefix=CST %s < %t
+
+////////////////////////////////////////////////////////////////////////////////
+// Class definitions (check for indirect target metadata)
+
+class Base {
+public:
+  // FT-DAG: define {{.*}} @_ZN4Base2vfEPc({{.*}} !type [[F_TVF:![0-9]+]]
+  virtual int vf(char *a) { return 0; };
+};
+
+class Derived : public Base {
+public:
+  // FT-DAG: define {{.*}} @_ZN7Derived2vfEPc({{.*}} !type [[F_TVF]]
+  int vf(char *a) override { return 1; };
+};
+
+// FT-DAG: [[F_TVF]] = !{i64 0, !"_ZTSFiPvE.generalized"}
+
+////////////////////////////////////////////////////////////////////////////////
+// Callsites (check for indirect callsite operand bundles)
+
+// CST-LABEL: define {{.*}} @_Z3foov
+void foo() {
+  auto B = Base();
+  auto D = Derived();
+
+  Base *Bptr = &B;
+  Base *BptrToD = &D;
+  Derived *Dptr = &D;
+
+  auto FpBaseVf = &Base::vf;
+  auto FpDerivedVf = &Derived::vf;
+
+  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ]
+  (Bptr->*FpBaseVf)(0);
+
+  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ]
+  (BptrToD->*FpBaseVf)(0);
+
+  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ]
+  (Dptr->*FpBaseVf)(0);
+
+  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ]
+  (Dptr->*FpDerivedVf)(0);
+}
diff --git a/clang/test/CodeGen/call-graph-section.c b/clang/test/CodeGen/call-graph-section.c
new file mode 100644
index 0000000000000..ed1bdb876152a
--- /dev/null
+++ b/clang/test/CodeGen/call-graph-section.c
@@ -0,0 +1,85 @@
+// Tests that we assign appropriate identifiers to indirect calls and targets.
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \
+// RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,ITANIUM %s
+
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fcall-graph-section -S \
+// RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s
+
+// CHECK-DAG: define {{(dso_local)?}} void @foo({{.*}} !type [[F_TVOID:![0-9]+]]
+void foo() {
+}
+
+// CHECK-DAG: define {{(dso_local)?}} void @bar({{.*}} !type [[F_TVOID]]
+void bar() {
+  void (*fp)() = foo;
+  // ITANIUM: call {{.*}} [ "type"(metadata !"_ZTSFvE.generalized") ]
+  // MS:      call {{.*}} [ "type"(metadata !"?6AX at Z.generalized") ]
+  fp();
+}
+
+// CHECK-DAG: define {{(dso_local)?}} i32 @baz({{.*}} !type [[F_TPRIMITIVE:![0-9]+]]
+int baz(char a, float b, double c) {
+  return 1;
+}
+
+// CHECK-DAG: define {{(dso_local)?}} ptr @qux({{.*}} !type [[F_TPTR:![0-9]+]]
+int *qux(char *a, float *b, double *c) {
+  return 0;
+}
+
+// CHECK-DAG: define {{(dso_local)?}} void @corge({{.*}} !type [[F_TVOID]]
+void corge() {
+  int (*fp_baz)(char, float, double) = baz;
+  // ITANIUM: call i32 {{.*}} [ "type"(metadata !"_ZTSFicfdE.generalized") ]
+  // MS:      call i32 {{.*}} [ "type"(metadata !"?6AHDMN at Z.generalized") ]
+  fp_baz('a', .0f, .0);
+
+  int *(*fp_qux)(char *, float *, double *) = qux;
+  // ITANIUM: call ptr {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
+  // MS:      call ptr {{.*}} [ "type"(metadata !"?6APEAXPEAX00 at Z.generalized") ]
+  fp_qux(0, 0, 0);
+}
+
+struct st1 {
+  int *(*fp)(char *, float *, double *);
+};
+
+struct st2 {
+  struct st1 m;
+};
+
+// CHECK-DAG: define {{(dso_local)?}} void @stparam({{.*}} !type [[F_TSTRUCT:![0-9]+]]
+void stparam(struct st2 a, struct st2 *b) {}
+
+// CHECK-DAG: define {{(dso_local)?}} void @stf({{.*}} !type [[F_TVOID]]
+void stf() {
+  struct st1 St1;
+  St1.fp = qux;
+  // ITANIUM: call ptr {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
+  // MS:      call ptr {{.*}} [ "type"(metadata !"?6APEAXPEAX00 at Z.generalized") ]
+  St1.fp(0, 0, 0);
+
+  struct st2 St2;
+  St2.m.fp = qux;
+  // ITANIUM: call ptr {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
+  // MS:      call ptr {{.*}} [ "type"(metadata !"?6APEAXPEAX00 at Z.generalized") ]
+  St2.m.fp(0, 0, 0);
+
+  // ITANIUM: call void {{.*}} [ "type"(metadata !"_ZTSFv3st2PvE.generalized") ]
+  // MS:      call void {{.*}} [ "type"(metadata !"?6AXUst2@@PEAX at Z.generalized") ]
+  void (*fp_stparam)(struct st2, struct st2 *) = stparam;
+  fp_stparam(St2, &St2);
+}
+
+// ITANIUM-DAG: [[F_TVOID]] = !{i64 0, !"_ZTSFvE.generalized"}
+// MS-DAG:      [[F_TVOID]] = !{i64 0, !"?6AX at Z.generalized"}
+
+// ITANIUM-DAG: [[F_TPRIMITIVE]] = !{i64 0, !"_ZTSFicfdE.generalized"}
+// MS-DAG:      [[F_TPRIMITIVE]] = !{i64 0, !"?6AHDMN at Z.generalized"}
+
+// ITANIUM-DAG: [[F_TPTR]] = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"}
+// MS-DAG:      [[F_TPTR]] = !{i64 0, !"?6APEAXPEAX00 at Z.generalized"}
+
+// ITANIUM-DAG: [[F_TSTRUCT]] = !{i64 0, !"_ZTSFv3st2PvE.generalized"}
+// MS-DAG:      [[F_TSTRUCT]] = !{i64 0, !"?6AXUst2@@PEAX at Z.generalized"}
diff --git a/clang/test/Driver/call-graph-section.c b/clang/test/Driver/call-graph-section.c
new file mode 100644
index 0000000000000..5832aa6754137
--- /dev/null
+++ b/clang/test/Driver/call-graph-section.c
@@ -0,0 +1,5 @@
+// RUN: %clang -### -S -fcall-graph-section %s 2>&1 | FileCheck --check-prefix=CALL-GRAPH-SECTION %s
+// RUN: %clang -### -S -fcall-graph-section -fno-call-graph-section %s 2>&1 | FileCheck --check-prefix=NO-CALL-GRAPH-SECTION %s
+
+// CALL-GRAPH-SECTION: "-fcall-graph-section"
+// NO-CALL-GRAPH-SECTION-NOT: "-fcall-graph-section"
diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h
index 244dabd38cf65..1f216b2853b07 100644
--- a/llvm/include/llvm/CodeGen/CommandFlags.h
+++ b/llvm/include/llvm/CodeGen/CommandFlags.h
@@ -130,6 +130,8 @@ bool getEnableStackSizeSection();
 
 bool getEnableAddrsig();
 
+bool getEnableCallGraphSection();
+
 bool getEmitCallSiteInfo();
 
 bool getEnableMachineFunctionSplitter();
diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h
index e5786afd72214..20a0bf70edecd 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -96,6 +96,7 @@ class LLVMContext {
     OB_ptrauth = 7,                // "ptrauth"
     OB_kcfi = 8,                   // "kcfi"
     OB_convergencectrl = 9,        // "convergencectrl"
+    OB_type = 10,                  // "type"
   };
 
   /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index d37e9d9576ba7..09bb0082c6ef8 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -149,7 +149,7 @@ namespace llvm {
           EnableTLSDESC(false), EnableIPRA(false), EmitStackSizeSection(false),
           EnableMachineOutliner(false), EnableMachineFunctionSplitter(false),
           SupportsDefaultOutlining(false), EmitAddrsig(false), BBAddrMap(false),
-          EmitCallSiteInfo(false), SupportsDebugEntryValues(false),
+          EmitCallGraphSection(false), EmitCallSiteInfo(false), SupportsDebugEntryValues(false),
           EnableDebugEntryValues(false), ValueTrackingVariableLocations(false),
           ForceDwarfFrameSection(false), XRayFunctionIndex(true),
           DebugStrictDwarf(false), Hotpatch(false),
@@ -323,6 +323,9 @@ namespace llvm {
     /// to selectively generate basic block sections.
     std::shared_ptr<MemoryBuffer> BBSectionsFuncListBuf;
 
+    /// Emit section containing call graph metadata.
+    unsigned EmitCallGraphSection : 1;
+
     /// The flag enables call site info production. It is used only for debug
     /// info, and it is restricted only to optimized code. This can be used for
     /// something else, so that should be controlled in the frontend.
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index fe49e52ae4283..abd8a586ba2b5 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -3091,9 +3091,21 @@ bool LLParser::parseOptionalOperandBundles(
         return true;
 
       Type *Ty = nullptr;
-      Value *Input = nullptr;
-      if (parseType(Ty) || parseValue(Ty, Input, PFS))
+      if (parseType(Ty))
         return true;
+
+      Value *Input = nullptr;
+      // FIXME: Metadata operand bundle value is garbage when LLVM IR is
+      // compiled to bitcode, then disassembled back to LLVM IR. See D107039
+      // for the reproducers, and https://bugs.llvm.org/show_bug.cgi?id=51264
+      // for the bug report.
+      if (Ty->isMetadataTy()) {
+        if (parseMetadataAsValue(Input, PFS))
+          return true;
+      } else {
+        if (parseValue(Ty, Input, PFS))
+          return true;
+      }
       Inputs.push_back(Input);
     }
 
diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp
index 14ac4b2102c2f..6d31681bb6c01 100644
--- a/llvm/lib/CodeGen/CommandFlags.cpp
+++ b/llvm/lib/CodeGen/CommandFlags.cpp
@@ -100,6 +100,7 @@ CGOPT(EABI, EABIVersion)
 CGOPT(DebuggerKind, DebuggerTuningOpt)
 CGOPT(bool, EnableStackSizeSection)
 CGOPT(bool, EnableAddrsig)
+CGOPT(bool, EnableCallGraphSection)
 CGOPT(bool, EmitCallSiteInfo)
 CGOPT(bool, EnableMachineFunctionSplitter)
 CGOPT(bool, EnableDebugEntryValues)
@@ -450,6 +451,11 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
       cl::init(false));
   CGBINDOPT(EnableAddrsig);
 
+  static cl::opt<bool> EnableCallGraphSection(
+      "call-graph-section", cl::desc("Emit a call graph section"),
+      cl::init(false));
+  CGBINDOPT(EnableCallGraphSection);
+
   static cl::opt<bool> EmitCallSiteInfo(
       "emit-call-site-info",
       cl::desc(
@@ -578,6 +584,7 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
   Options.EmitStackSizeSection = getEnableStackSizeSection();
   Options.EnableMachineFunctionSplitter = getEnableMachineFunctionSplitter();
   Options.EmitAddrsig = getEnableAddrsig();
+  Options.EmitCallGraphSection = getEnableCallGraphSection();
   Options.EmitCallSiteInfo = getEmitCallSiteInfo();
   Options.EnableDebugEntryValues = getEnableDebugEntryValues();
   Options.ForceDwarfFrameSection = getForceDwarfFrameSection();
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 618bdee7f4053..1a3970e4e25c6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3308,7 +3308,7 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
              {LLVMContext::OB_deopt, LLVMContext::OB_gc_transition,
               LLVMContext::OB_gc_live, LLVMContext::OB_funclet,
               LLVMContext::OB_cfguardtarget,
-              LLVMContext::OB_clang_arc_attachedcall}) &&
+              LLVMContext::OB_clang_arc_attachedcall, LLVMContext::OB_type}) &&
          "Cannot lower invokes with arbitrary operand bundles yet!");
 
   const Value *Callee(I.getCalledOperand());
@@ -3395,8 +3395,9 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
 
   // Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't
   // have to do anything here to lower funclet bundles.
-  assert(!I.hasOperandBundlesOtherThan(
-             {LLVMContext::OB_deopt, LLVMContext::OB_funclet}) &&
+  assert(!I.hasOperandBundlesOtherThan({LLVMContext::OB_deopt,
+                                        LLVMContext::OB_funclet,
+                                        LLVMContext::OB_type}) &&
          "Cannot lower callbrs with arbitrary operand bundles yet!");
 
   assert(I.isInlineAsm() && "Only know how to handle inlineasm callbr");
@@ -9176,7 +9177,8 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
              {LLVMContext::OB_deopt, LLVMContext::OB_funclet,
               LLVMContext::OB_cfguardtarget, LLVMContext::OB_preallocated,
               LLVMContext::OB_clang_arc_attachedcall, LLVMContext::OB_kcfi,
-              LLVMContext::OB_convergencectrl}) &&
+              LLVMContext::OB_convergencectrl,
+              LLVMContext::OB_type}) &&
          "Cannot lower calls with arbitrary operand bundles!");
 
   SDValue Callee = getValue(I.getCalledOperand());
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 57077e786efc2..d987acf309ea3 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -97,6 +97,11 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
          "convergencectrl operand bundle id drifted!");
   (void)ConvergenceCtrlEntry;
 
+  auto *TypeEntry = pImpl->getOrInsertBundleTag("type");
+  assert(TypeEntry->second == LLVMContext::OB_type &&
+         "type operand bundle id drifted!");
+  (void)TypeEntry;
+
   SyncScope::ID SingleThreadSSID =
       pImpl->getOrInsertSyncScopeID("singlethread");
   assert(SingleThreadSSID == SyncScope::SingleThread &&
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 33f358440a312..4f6d8599b6812 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3608,13 +3608,13 @@ void Verifier::visitCallBase(CallBase &Call) {
       visitIntrinsicCall(ID, Call);
 
   // Verify that a callsite has at most one "deopt", at most one "funclet", at
-  // most one "gc-transition", at most one "cfguardtarget", at most one
+  // most one "gc-transition", at most one "cfguardtarget", at most one "type", at most one
   // "preallocated" operand bundle, and at most one "ptrauth" operand bundle.
   bool FoundDeoptBundle = false, FoundFuncletBundle = false,
        FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false,
        FoundPreallocatedBundle = false, FoundGCLiveBundle = false,
        FoundPtrauthBundle = false, FoundKCFIBundle = false,
-       FoundAttachedCallBundle = false;
+       FoundAttachedCallBundle = false, FoundTypeBundle = false;
   for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) {
     OperandBundleUse BU = Call.getOperandBundleAt(i);
     uint32_t Tag = BU.getTagID();
@@ -3677,6 +3677,9 @@ void Verifier::visitCallBase(CallBase &Call) {
             "Multiple \"clang.arc.attachedcall\" operand bundles", Call);
       FoundAttachedCallBundle = true;
       verifyAttachedCallBundle(Call, BU);
+    } else if (Tag == LLVMContext::OB_type) {
+      Check(!FoundTypeBundle, "Multiple \"type\" operand bundles", Call);
+      FoundTypeBundle = true;
     }
   }
 
diff --git a/llvm/test/Bitcode/2021-07-22-Parse-Metadata-Operand-Bundles.ll b/llvm/test/Bitcode/2021-07-22-Parse-Metadata-Operand-Bundles.ll
new file mode 100644
index 0000000000000..35c6131bbad60
--- /dev/null
+++ b/llvm/test/Bitcode/2021-07-22-Parse-Metadata-Operand-Bundles.ll
@@ -0,0 +1,9 @@
+; This test ensures that we parse metadata operand bundle values.
+; RUN: llvm-as < %s
+
+declare void @callee()
+
+define void @call_with_operand_bundle() {
+  call void @callee() [ "op_type"(metadata !"metadata_string") ]
+  ret void
+}
diff --git a/llvm/test/Verifier/operand-bundles.ll b/llvm/test/Verifier/operand-bundles.ll
index db85b6ae6ef5f..788006494edce 100644
--- a/llvm/test/Verifier/operand-bundles.ll
+++ b/llvm/test/Verifier/operand-bundles.ll
@@ -105,4 +105,17 @@ declare ptr @objc_retainAutoreleasedReturnValue(ptr)
 declare ptr @objc_unsafeClaimAutoreleasedReturnValue(ptr)
 declare void @llvm.assume(i1)
 
+define void @f_type(i32* %ptr) {
+; CHECK: Multiple "type" operand bundles
+; CHECK-NEXT: call void @g() [ "type"(metadata !"_ZTSFvE.generalized"), "type"(metadata !"_ZTSFvE.generalized") ]
+; CHECK-NOT: call void @g() [ "type"(metadata !"_ZTSFvE.generalized") ]
+
+ entry:
+  %l = load i32, i32* %ptr
+  call void @g() [ "type"(metadata !"_ZTSFvE.generalized"), "type"(metadata !"_ZTSFvE.generalized") ]
+  call void @g() [ "type"(metadata !"_ZTSFvE.generalized") ]
+  %x = add i32 42, 1
+  ret void
+}
+
 attributes #0 = { noreturn }

>From 86ba0b1b54792b848728ce0a616ca32d82b824a4 Mon Sep 17 00:00:00 2001
From: Prabhuk <prabhukr at google.com>
Date: Mon, 29 Apr 2024 11:53:44 -0700
Subject: [PATCH 02/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 clang/lib/CodeGen/CGCall.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 526a63b24ff83..45033ced1d834 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5713,8 +5713,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
     if (callOrInvoke && *callOrInvoke && (*callOrInvoke)->isIndirectCall()) {
       if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
         // Type id metadata is set only for C/C++ contexts.
-        if (dyn_cast<CXXConstructorDecl>(FD) || dyn_cast<CXXMethodDecl>(FD) ||
-            dyn_cast<CXXDestructorDecl>(FD)) {
+        if (isa<CXXConstructorDecl>(FD) || isa<CXXMethodDecl>(FD) ||
+            isa<CXXDestructorDecl>(FD)) {
           CGM.CreateFunctionTypeMetadataForIcall(FD->getType(), *callOrInvoke);
         }
       }

>From 120cb5408f024b27b12c89c0a17669f10ef79fbe Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Wed, 13 Nov 2024 17:20:09 -0800
Subject: [PATCH 03/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/lib/AsmParser/LLParser.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index fa8c008a7f870..bfd25c98a9446 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -3206,9 +3206,10 @@ bool LLParser::parseOptionalOperandBundles(
 
       Value *Input = nullptr;
       // FIXME: Metadata operand bundle value is garbage when LLVM IR is
-      // compiled to bitcode, then disassembled back to LLVM IR. See D107039
-      // for the reproducers, and https://bugs.llvm.org/show_bug.cgi?id=51264
-      // for the bug report.
+      // compiled to bitcode, then disassembled back to LLVM IR.
+      // See [PR#89649](https://github.com/llvm/llvm-project/pull/89649)
+      // for the reproducers, and
+      // https://github.com/llvm/llvm-project/issues/50608 for the bug report.
       if (Ty->isMetadataTy()) {
         if (parseMetadataAsValue(Input, PFS))
           return true;

>From cf96ec260f487f329e57115e3f0874d076d7fe42 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 20 Nov 2024 11:52:51 -0800
Subject: [PATCH 04/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 clang/docs/CallGraphSection.rst              | 251 -------------------
 clang/include/clang/Basic/CodeGenOptions.def |   2 -
 clang/include/clang/Driver/Options.td        |   4 -
 clang/lib/CodeGen/BackendUtil.cpp            |   1 -
 clang/lib/Driver/ToolChains/Clang.cpp        |   4 -
 clang/test/Driver/call-graph-section.c       |   5 -
 llvm/include/llvm/CodeGen/CommandFlags.h     |   2 -
 llvm/include/llvm/Target/TargetOptions.h     |   5 +-
 llvm/lib/CodeGen/CommandFlags.cpp            |   7 -
 9 files changed, 1 insertion(+), 280 deletions(-)
 delete mode 100644 clang/docs/CallGraphSection.rst
 delete mode 100644 clang/test/Driver/call-graph-section.c

diff --git a/clang/docs/CallGraphSection.rst b/clang/docs/CallGraphSection.rst
deleted file mode 100644
index d5db507f9ca9a..0000000000000
--- a/clang/docs/CallGraphSection.rst
+++ /dev/null
@@ -1,251 +0,0 @@
-==================
-Call Graph Section
-==================
-
-Introduction
-============
-
-With ``-fcall-graph-section``, the compiler will create a call graph section 
-in the object file. It will include type identifiers for indirect calls and 
-targets. This information can be used to map indirect calls to their receivers 
-with matching types. A complete and high-precision call graph can be 
-reconstructed by complementing this information with disassembly 
-(see ``llvm-objdump --call-graph-info``).
-
-Semantics
-=========
-
-A coarse-grained, type-agnostic call graph may allow indirect calls to target
-any function in the program. This approach ensures completeness since no
-indirect call edge is missing. However, it is generally poor in precision
-due to having unneeded edges.
-
-A call graph section provides type identifiers for indirect calls and targets.
-This information can be used to restrict the receivers of an indirect target to
-indirect calls with matching type. Consequently, the precision for indirect
-call edges are improved while maintaining the completeness.
-
-The ``llvm-objdump`` utility provides a ``--call-graph-info`` option to extract
-full call graph information by parsing the content of the call graph section
-and disassembling the program for complementary information, e.g., direct
-calls.
-
-Section layout
-==============
-
-A call graph section consists of zero or more call graph entries.
-Each entry contains information on a function and its indirect calls.
-
-An entry of a call graph section has the following layout in the binary:
-
-+---------------------+-----------------------------------------------------------------------+
-| Element             | Content                                                               |
-+=====================+=======================================================================+
-| FormatVersionNumber | Format version number.                                                |
-+---------------------+-----------------------------------------------------------------------+
-| FunctionEntryPc     | Function entry address.                                               |
-+---------------------+-----------------------------------+-----------------------------------+
-|                     | A flag whether the function is an | - 0: not an indirect target       |
-| FunctionKind        | indirect target, and if so,       | - 1: indirect target, unknown id  |
-|                     | whether its type id is known.     | - 2: indirect target, known id    |
-+---------------------+-----------------------------------+-----------------------------------+
-| FunctionTypeId      | Type id for the indirect target. Present only when FunctionKind is 2. |
-+---------------------+-----------------------------------------------------------------------+
-| CallSiteCount       | Number of type id to indirect call site mappings that follow.         |
-+---------------------+-----------------------------------------------------------------------+
-| CallSiteList        | List of type id and indirect call site pc pairs.                      |
-+---------------------+-----------------------------------------------------------------------+
-
-Each element in an entry (including each element of the contained lists and
-pairs) occupies 64-bit space.
-
-The format version number is repeated per entry to support concatenation of
-call graph sections with different format versions by the linker.
-
-As of now, the only supported format version is described above and has version
-number 0.
-
-Type identifiers
-================
-
-The type for an indirect call or target is the function signature.
-The mapping from a type to an identifier is an ABI detail.
-In the current experimental 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 separate types.
-
-Missing type identifiers
-========================
-
-For functions, two cases need to be considered. First, if the compiler cannot
-deduce a type id for an indirect target, it will be listed as an indirect target
-without a type id. Second, if an object without a call graph section gets
-linked, the final call graph section will lack information on functions from
-the object. For completeness, these functions need to be taken as receiver to
-any indirect call regardless of their type id.
-``llvm-objdump --call-graph-info`` lists these functions as indirect targets
-with `UNKNOWN` type id.
-
-For indirect calls, current implementation guarantees a type id for each
-compiled call. However, if an object without a call graph section gets linked,
-no type id will be present for its indirect calls. For completeness, these calls
-need to be taken to target any indirect target regardless of their type id. For
-indirect calls, ``llvm-objdump --call-graph-info`` prints 1) a complete list of
-indirect calls, 2) type id to indirect call mappings. The difference of these
-lists allow to deduce the indirect calls with missing type ids.
-
-TODO: measure and report the ratio of missed type ids
-
-Performance
-===========
-
-A call graph section does not affect the executable code and does not occupy
-memory during process execution. Therefore, there is no performance overhead.
-
-The scheme has not yet been optimized for binary size.
-
-TODO: measure and report the increase in the binary size
-
-Example
-=======
-
-For example, consider the following C++ code:
-
-.. code-block:: cpp
-
-    namespace {
-      // Not an indirect target
-      void foo() {}
-    }
-
-    // Indirect target 1
-    void bar() {}
-
-    // Indirect target 2
-    int baz(char a, float *b) {
-      return 0;
-    }
-
-    // Indirect target 3
-    int main() {
-      char a;
-      float b;
-      void (*fp_bar)() = bar;
-      int (*fp_baz1)(char, float*) = baz;
-      int (*fp_baz2)(char, float*) = baz;
-
-      // Indirect call site 1
-      fp_bar();
-
-      // Indirect call site 2
-      fp_baz1(a, &b);
-
-      // Indirect call site 3: shares the type id with indirect call site 2
-      fp_baz2(a, &b);
-
-      // Direct call sites
-      foo();
-      bar();
-      baz(a, &b);
-
-      return 0;
-    }
-
-Following will compile it with a call graph section created in the binary:
-
-.. code-block:: bash
-
-  $ clang -fcall-graph-section example.cpp
-
-During the construction of the call graph section, the type identifiers are 
-computed as follows:
-
-+---------------+-----------------------+----------------------------+----------------------------+
-| Function name | Generalized signature | Mangled name (itanium ABI) | Numeric type id (md5 hash) |
-+===============+=======================+============================+============================+
-|  bar          | void ()               | _ZTSFvvE.generalized       | f85c699bb8ef20a2           |
-+---------------+-----------------------+----------------------------+----------------------------+
-|  baz          | int (char, void*)     | _ZTSFicPvE.generalized     | e3804d2a7f2b03fe           |
-+---------------+-----------------------+----------------------------+----------------------------+
-|  main         | int ()                | _ZTSFivE.generalized       | a9494def81a01dc            |
-+---------------+-----------------------+----------------------------+----------------------------+
-
-The call graph section will have the following content:
-
-+---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
-| FormatVersion | FunctionEntryPc | FunctionKind | FunctionTypeId | CallSiteCount | CallSiteList                         |
-+===============+=================+==============+================+===============+======================================+
-| 0             | EntryPc(foo)    | 0            | (empty)        | 0             | (empty)                              |
-+---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
-| 0             | EntryPc(bar)    | 2            | TypeId(bar)    | 0             | (empty)                              |
-+---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
-| 0             | EntryPc(baz)    | 2            | TypeId(baz)    | 0             | (empty)                              |
-+---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
-| 0             | EntryPc(main)   | 2            | TypeId(main)   | 3             | * TypeId(bar), CallSitePc(fp_bar())  |
-|               |                 |              |                |               | * TypeId(baz), CallSitePc(fp_baz1()) |
-|               |                 |              |                |               | * TypeId(baz), CallSitePc(fp_baz2()) |
-+---------------+-----------------+--------------+----------------+---------------+--------------------------------------+
-
-
-The ``llvm-objdump`` utility can parse the call graph section and disassemble
-the program to provide complete call graph information. This includes any
-additional call sites from the binary:
-
-.. code-block:: bash
-
-    $ llvm-objdump --call-graph-info a.out
-
-    # Comments are not a part of the llvm-objdump's output but inserted for clarifications.
-
-    a.out:  file format elf64-x86-64
-    # These warnings are due to the functions and the indirect calls coming from linked objects.
-    llvm-objdump: warning: 'a.out': callgraph section does not have type ids for 3 indirect calls
-    llvm-objdump: warning: 'a.out': callgraph section does not have information for 10 functions
-
-    # Unknown targets are the 10 functions the warnings mention.
-    INDIRECT TARGET TYPES (TYPEID [FUNC_ADDR,])
-    UNKNOWN 401000 401100 401234 401050 401090 4010d0 4011d0 401020 401060 401230
-    a9494def81a01dc 401150            # main()
-    f85c699bb8ef20a2 401120           # bar()
-    e3804d2a7f2b03fe 401130           # baz()
-
-    # Notice that the call sites share the same type id as target functions
-    INDIRECT CALL TYPES (TYPEID [CALL_SITE_ADDR,])
-    f85c699bb8ef20a2 401181           # Indirect call site 1 (fp_bar())
-    e3804d2a7f2b03fe 401191 4011a1    # Indirect call site 2 and 3 (fp_baz1() and fp_baz2())
-
-    INDIRECT CALL SITES (CALLER_ADDR [CALL_SITE_ADDR,])
-    401000 401012                     # _init
-    401150 401181 401191 4011a1       # main calls fp_bar(), fp_baz1(), fp_baz2()
-    4011d0 401215                     # __libc_csu_init
-    401020 40104a                     # _start
-
-    DIRECT CALL SITES (CALLER_ADDR [(CALL_SITE_ADDR, TARGET_ADDR),])
-    4010d0 4010e2 401060              # __do_global_dtors_aux
-    401150 4011a6 401110 4011ab 401120 4011ba 401130   # main calls foo(), bar(), baz()
-    4011d0 4011fd 401000              # __libc_csu_init
-
-    FUNCTIONS (FUNC_ENTRY_ADDR, SYM_NAME)
-    401000 _init
-    401100 frame_dummy
-    401234 _fini
-    401050 _dl_relocate_static_pie
-    401090 register_tm_clones
-    4010d0 __do_global_dtors_aux
-    401110 _ZN12_GLOBAL__N_13fooEv    # (anonymous namespace)::foo()
-    401150 main                       # main
-    4011d0 __libc_csu_init
-    401020 _start
-    401060 deregister_tm_clones
-    401120 _Z3barv                    # bar()
-    401130 _Z3bazcPf                  # baz(char, float*)
-    401230 __libc_csu_fini
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index a3ee5acef4217..4cf22c4ee08ce 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -78,8 +78,6 @@ CODEGENOPT(EnableNoundefAttrs, 1, 0) ///< Enable emitting `noundef` attributes o
 CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
                                    ///< pass manager.
 CODEGENOPT(DisableRedZone    , 1, 0) ///< Set when -mno-red-zone is enabled.
-CODEGENOPT(CallGraphSection, 1, 0) ///< Emit a call graph section into the
-                                   ///< object file.
 CODEGENOPT(EmitCallSiteInfo, 1, 0) ///< Emit call site info only in the case of
                                    ///< '-g' + 'O>0' level.
 CODEGENOPT(IndirectTlsSegRefs, 1, 0) ///< Set when -mno-tls-direct-seg-refs
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 77c78ea0724da..f2f9c20c9bc26 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4291,10 +4291,6 @@ defm data_sections : BoolFOption<"data-sections",
   PosFlag<SetTrue, [], [ClangOption, CC1Option],
           "Place each data in its own section">,
   NegFlag<SetFalse>>;
-defm call_graph_section : BoolFOption<"call-graph-section",
-  CodeGenOpts<"CallGraphSection">, DefaultFalse,
-  PosFlag<SetTrue, [], [CC1Option], "Emit a call graph section">,
-  NegFlag<SetFalse>>;
 defm stack_size_section : BoolFOption<"stack-size-section",
   CodeGenOpts<"StackSizeSection">, DefaultFalse,
   PosFlag<SetTrue, [], [ClangOption, CC1Option],
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 4b81d229cda3c..bf9b04f02e9f4 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -455,7 +455,6 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
   Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;
   Options.EmitAddrsig = CodeGenOpts.Addrsig;
   Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
-  Options.EmitCallGraphSection = CodeGenOpts.CallGraphSection;
   Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;
   Options.EnableAIXExtendedAltivecABI = LangOpts.EnableAIXExtendedAltivecABI;
   Options.XRayFunctionIndex = CodeGenOpts.XRayFunctionIndex;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index d749f0fc5375a..d3eec9fea0d49 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6609,10 +6609,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back(A->getValue());
   }
 
-  if (Args.hasFlag(options::OPT_fcall_graph_section,
-                   options::OPT_fno_call_graph_section, false))
-    CmdArgs.push_back("-fcall-graph-section");
-
   Args.addOptInFlag(CmdArgs, options::OPT_fstack_size_section,
                     options::OPT_fno_stack_size_section);
 
diff --git a/clang/test/Driver/call-graph-section.c b/clang/test/Driver/call-graph-section.c
deleted file mode 100644
index 5832aa6754137..0000000000000
--- a/clang/test/Driver/call-graph-section.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %clang -### -S -fcall-graph-section %s 2>&1 | FileCheck --check-prefix=CALL-GRAPH-SECTION %s
-// RUN: %clang -### -S -fcall-graph-section -fno-call-graph-section %s 2>&1 | FileCheck --check-prefix=NO-CALL-GRAPH-SECTION %s
-
-// CALL-GRAPH-SECTION: "-fcall-graph-section"
-// NO-CALL-GRAPH-SECTION-NOT: "-fcall-graph-section"
diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h
index eb93192700a83..d5448d781363d 100644
--- a/llvm/include/llvm/CodeGen/CommandFlags.h
+++ b/llvm/include/llvm/CodeGen/CommandFlags.h
@@ -132,8 +132,6 @@ bool getEnableStackSizeSection();
 
 bool getEnableAddrsig();
 
-bool getEnableCallGraphSection();
-
 bool getEmitCallSiteInfo();
 
 bool getEnableMachineFunctionSplitter();
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index eb17922798a82..88f253805ca99 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -146,7 +146,7 @@ namespace llvm {
           EmulatedTLS(false), EnableTLSDESC(false), EnableIPRA(false),
           EmitStackSizeSection(false), EnableMachineOutliner(false),
           EnableMachineFunctionSplitter(false), SupportsDefaultOutlining(false),
-          EmitAddrsig(false), BBAddrMap(false), EmitCallGraphSection(false), EmitCallSiteInfo(false),
+          EmitAddrsig(false), BBAddrMap(false), EmitCallSiteInfo(false),
           SupportsDebugEntryValues(false), EnableDebugEntryValues(false),
           ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
           XRayFunctionIndex(true), DebugStrictDwarf(false), Hotpatch(false),
@@ -329,9 +329,6 @@ namespace llvm {
     /// to selectively generate basic block sections.
     std::shared_ptr<MemoryBuffer> BBSectionsFuncListBuf;
 
-    /// Emit section containing call graph metadata.
-    unsigned EmitCallGraphSection : 1;
-
     /// The flag enables call site info production. It is used only for debug
     /// info, and it is restricted only to optimized code. This can be used for
     /// something else, so that should be controlled in the frontend.
diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp
index c2a7a0d7ea663..d180cfcea658c 100644
--- a/llvm/lib/CodeGen/CommandFlags.cpp
+++ b/llvm/lib/CodeGen/CommandFlags.cpp
@@ -101,7 +101,6 @@ CGOPT(EABI, EABIVersion)
 CGOPT(DebuggerKind, DebuggerTuningOpt)
 CGOPT(bool, EnableStackSizeSection)
 CGOPT(bool, EnableAddrsig)
-CGOPT(bool, EnableCallGraphSection)
 CGOPT(bool, EmitCallSiteInfo)
 CGOPT(bool, EnableMachineFunctionSplitter)
 CGOPT(bool, EnableDebugEntryValues)
@@ -461,11 +460,6 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
       cl::init(false));
   CGBINDOPT(EnableAddrsig);
 
-  static cl::opt<bool> EnableCallGraphSection(
-      "call-graph-section", cl::desc("Emit a call graph section"),
-      cl::init(false));
-  CGBINDOPT(EnableCallGraphSection);
-
   static cl::opt<bool> EmitCallSiteInfo(
       "emit-call-site-info",
       cl::desc(
@@ -593,7 +587,6 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
   Options.EmitStackSizeSection = getEnableStackSizeSection();
   Options.EnableMachineFunctionSplitter = getEnableMachineFunctionSplitter();
   Options.EmitAddrsig = getEnableAddrsig();
-  Options.EmitCallGraphSection = getEnableCallGraphSection();
   Options.EmitCallSiteInfo = getEmitCallSiteInfo();
   Options.EnableDebugEntryValues = getEnableDebugEntryValues();
   Options.ForceDwarfFrameSection = getForceDwarfFrameSection();

>From 5455d3b68da583fd4e85e0f283a7782559805d44 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 10 Dec 2024 14:54:44 -0800
Subject: [PATCH 05/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 clang/lib/CodeGen/CGCall.cpp                |  38 -------
 clang/lib/CodeGen/CGExpr.cpp                |   6 --
 clang/lib/CodeGen/CGObjCMac.cpp             |   5 +-
 clang/lib/CodeGen/CodeGenModule.cpp         |  35 +------
 clang/lib/CodeGen/CodeGenModule.h           |   4 -
 clang/test/CodeGen/call-graph-section-1.cpp | 110 --------------------
 clang/test/CodeGen/call-graph-section-2.cpp |  95 -----------------
 clang/test/CodeGen/call-graph-section-3.cpp |  52 ---------
 clang/test/CodeGen/call-graph-section.c     |  85 ---------------
 llvm/include/llvm/CodeGen/CommandFlags.h    |   2 +
 llvm/include/llvm/Target/TargetOptions.h    |  12 ++-
 llvm/lib/CodeGen/CommandFlags.cpp           |   7 ++
 llvm/lib/IR/Verifier.cpp                    |   7 +-
 llvm/test/Verifier/operand-bundles.ll       |   4 +-
 14 files changed, 30 insertions(+), 432 deletions(-)
 delete mode 100644 clang/test/CodeGen/call-graph-section-1.cpp
 delete mode 100644 clang/test/CodeGen/call-graph-section-2.cpp
 delete mode 100644 clang/test/CodeGen/call-graph-section-3.cpp
 delete mode 100644 clang/test/CodeGen/call-graph-section.c

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d5240db0fceb8..35d495d4dfab8 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -25,7 +25,6 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
-#include "clang/AST/Type.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
@@ -5078,11 +5077,6 @@ static unsigned getMaxVectorWidth(const llvm::Type *Ty) {
   return MaxVectorWidth;
 }
 
-static bool isCXXDeclType(const FunctionDecl *FD) {
-  return isa<CXXConstructorDecl>(FD) || isa<CXXMethodDecl>(FD) ||
-         isa<CXXDestructorDecl>(FD);
-}
-
 RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
                                  const CGCallee &Callee,
                                  ReturnValueSlot ReturnValue,
@@ -5771,38 +5765,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
   AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs);
   Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs);
 
-  if (CGM.getCodeGenOpts().CallGraphSection) {
-    // Create operand bundle only for indirect calls, not for all
-    if (callOrInvoke && *callOrInvoke && (*callOrInvoke)->isIndirectCall()) {
-
-      assert((TargetDecl && TargetDecl->getFunctionType() ||
-              Callee.getAbstractInfo().getCalleeFunctionProtoType()) &&
-             "cannot find callsite type");
-
-      QualType CST;
-      if (TargetDecl && TargetDecl->getFunctionType())
-        CST = QualType(TargetDecl->getFunctionType(), 0);
-      else if (const auto *FPT =
-                   Callee.getAbstractInfo().getCalleeFunctionProtoType())
-        CST = QualType(FPT, 0);
-
-      if (!CST.isNull()) {
-        auto *TypeIdMD = CGM.CreateMetadataIdentifierGeneralized(CST);
-        auto *TypeIdMDVal =
-            llvm::MetadataAsValue::get(getLLVMContext(), TypeIdMD);
-        BundleList.emplace_back("type", TypeIdMDVal);
-      }
-
-      // Set type identifier metadata of indirect calls for call graph section.
-      if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
-        // Type id metadata is set only for C/C++ contexts.
-        if (isCXXDeclType(FD)) {
-          CGM.CreateFunctionTypeMetadataForIcall(FD->getType(), *callOrInvoke);
-        }
-      }
-    }
-  }
-
   // Emit the actual call/invoke instruction.
   llvm::CallBase *CI;
   if (!InvokeDest) {
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 97f2cfe35ec59..232cac22d1bfc 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -6173,12 +6173,6 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
   if (CallOrInvoke)
     *CallOrInvoke = LocalCallOrInvoke;
 
-  // Set type identifier metadata of indirect calls for call graph section.
-  if (CGM.getCodeGenOpts().CallGraphSection && LocalCallOrInvoke &&
-      LocalCallOrInvoke->isIndirectCall())
-    CGM.CreateFunctionTypeMetadataForIcall(QualType(FnType, 0),
-                                           LocalCallOrInvoke);
-
   return Call;
 }
 
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 248fb2ef68c43..7b85dcc2c7984 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -2214,8 +2214,9 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
 
   llvm::CallBase *CallSite;
   CGCallee Callee = CGCallee::forDirect(BitcastFn);
-  RValue rvalue =
-      CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, &CallSite);
+  RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
+                               &CallSite);
+
   // Mark the call as noreturn if the method is marked noreturn and the
   // receiver cannot be null.
   if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 56a831b13bd08..b854eeb62a80c 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2622,9 +2622,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
 
   // In the cross-dso CFI mode with canonical jump tables, we want !type
   // attributes on definitions only.
-  if ((CodeGenOpts.SanitizeCfiCrossDso &&
-       CodeGenOpts.SanitizeCfiCanonicalJumpTables) ||
-      CodeGenOpts.CallGraphSection) {
+  if (CodeGenOpts.SanitizeCfiCrossDso &&
+      CodeGenOpts.SanitizeCfiCanonicalJumpTables) {
     if (auto *FD = dyn_cast<FunctionDecl>(D)) {
       // Skip available_externally functions. They won't be codegen'ed in the
       // current module anyway.
@@ -2814,17 +2813,7 @@ static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) {
 
 void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
                                                        llvm::Function *F) {
-  bool EmittedMDIdGeneralized = false;
-  if (CodeGenOpts.CallGraphSection &&
-      (!F->hasLocalLinkage() ||
-       F->getFunction().hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true,
-                                        /*IgnoreAssumeLikeCalls=*/true,
-                                        /*IgnoreLLVMUsed=*/false))) {
-    F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
-    EmittedMDIdGeneralized = true;
-  }
-
-  // Add additional metadata only if we are checking indirect calls with CFI.
+  // Only if we are checking indirect calls.
   if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall))
     return;
 
@@ -2835,9 +2824,7 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
 
   llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
   F->addTypeMetadata(0, MD);
-  // Add the generalized identifier if not added already.
-  if (!EmittedMDIdGeneralized)
-    F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
+  F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
 
   // Emit a hash-based bit set entry for cross-DSO calls.
   if (CodeGenOpts.SanitizeCfiCrossDso)
@@ -2845,17 +2832,6 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
       F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId));
 }
 
-void CodeGenModule::CreateFunctionTypeMetadataForIcall(const QualType &QT,
-                                                       llvm::CallBase *CB) {
-  // Only if needed for call graph section and only for indirect calls.
-  if (!CodeGenOpts.CallGraphSection || !CB || !CB->isIndirectCall())
-    return;
-
-  auto *MD = CreateMetadataIdentifierGeneralized(QT);
-  auto *MDN = llvm::MDNode::get(getLLVMContext(), MD);
-  CB->setMetadata(llvm::LLVMContext::MD_type, MDN);
-}
-
 void CodeGenModule::setKCFIType(const FunctionDecl *FD, llvm::Function *F) {
   llvm::LLVMContext &Ctx = F->getContext();
   llvm::MDBuilder MDB(Ctx);
@@ -2983,8 +2959,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
   // are non-canonical then we need type metadata in order to produce the local
   // jump table.
   if (!CodeGenOpts.SanitizeCfiCrossDso ||
-      !CodeGenOpts.SanitizeCfiCanonicalJumpTables ||
-      CodeGenOpts.CallGraphSection)
+      !CodeGenOpts.SanitizeCfiCanonicalJumpTables)
     CreateFunctionTypeMetadataForIcall(FD, F);
 
   if (LangOpts.Sanitize.has(SanitizerKind::KCFI))
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index bbaf5b150f176..741b0f17da658 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1572,10 +1572,6 @@ class CodeGenModule : public CodeGenTypeCache {
   void CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
                                           llvm::Function *F);
 
-  /// Create and attach type metadata to the given call.
-  void CreateFunctionTypeMetadataForIcall(const QualType &QT,
-                                          llvm::CallBase *CB);
-
   /// Set type metadata to the given function.
   void setKCFIType(const FunctionDecl *FD, llvm::Function *F);
 
diff --git a/clang/test/CodeGen/call-graph-section-1.cpp b/clang/test/CodeGen/call-graph-section-1.cpp
deleted file mode 100644
index 25397e94422b7..0000000000000
--- a/clang/test/CodeGen/call-graph-section-1.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-// Tests that we assign appropriate identifiers to indirect calls and targets
-// specifically for C++ class and instance methods.
-
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \
-// RUN: -emit-llvm -o %t %s
-// RUN: FileCheck --check-prefix=FT %s < %t
-// RUN: FileCheck --check-prefix=CST %s < %t
-
-////////////////////////////////////////////////////////////////////////////////
-// Class definitions (check for indirect target metadata)
-
-class Cls1 {
-public:
-  // FT-DAG: define {{.*}} ptr @_ZN4Cls18receiverEPcPf({{.*}} !type [[F_TCLS1RECEIVER:![0-9]+]]
-  static int *receiver(char *a, float *b) { return 0; }
-};
-
-class Cls2 {
-public:
-  int *(*fp)(char *, float *);
-
-  // FT-DAG: define {{.*}} i32 @_ZN4Cls22f1Ecfd({{.*}} !type [[F_TCLS2F1:![0-9]+]]
-  int f1(char a, float b, double c) { return 0; }
-
-  // FT-DAG: define {{.*}} ptr @_ZN4Cls22f2EPcPfPd({{.*}} !type [[F_TCLS2F2:![0-9]+]]
-  int *f2(char *a, float *b, double *c) { return 0; }
-
-  // FT-DAG: define {{.*}} void @_ZN4Cls22f3E4Cls1({{.*}} !type [[F_TCLS2F3F4:![0-9]+]]
-  void f3(Cls1 a) {}
-
-  // FT-DAG: define {{.*}} void @_ZN4Cls22f4E4Cls1({{.*}} !type [[F_TCLS2F3F4]]
-  void f4(const Cls1 a) {}
-
-  // FT-DAG: define {{.*}} void @_ZN4Cls22f5EP4Cls1({{.*}} !type [[F_TCLS2F5:![0-9]+]]
-  void f5(Cls1 *a) {}
-
-  // FT-DAG: define {{.*}} void @_ZN4Cls22f6EPK4Cls1({{.*}} !type [[F_TCLS2F6:![0-9]+]]
-  void f6(const Cls1 *a) {}
-
-  // FT-DAG: define {{.*}} void @_ZN4Cls22f7ER4Cls1({{.*}} !type [[F_TCLS2F7:![0-9]+]]
-  void f7(Cls1 &a) {}
-
-  // FT-DAG: define {{.*}} void @_ZN4Cls22f8ERK4Cls1({{.*}} !type [[F_TCLS2F8:![0-9]+]]
-  void f8(const Cls1 &a) {}
-
-  // FT-DAG: define {{.*}} void @_ZNK4Cls22f9Ev({{.*}} !type [[F_TCLS2F9:![0-9]+]]
-  void f9() const {}
-};
-
-// FT-DAG: [[F_TCLS1RECEIVER]] = !{i64 0, !"_ZTSFPvS_S_E.generalized"}
-// FT-DAG: [[F_TCLS2F2]]   = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"}
-// FT-DAG: [[F_TCLS2F1]]   = !{i64 0, !"_ZTSFicfdE.generalized"}
-// FT-DAG: [[F_TCLS2F3F4]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
-// FT-DAG: [[F_TCLS2F5]]   = !{i64 0, !"_ZTSFvPvE.generalized"}
-// FT-DAG: [[F_TCLS2F6]]   = !{i64 0, !"_ZTSFvPKvE.generalized"}
-// FT-DAG: [[F_TCLS2F7]]   = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
-// FT-DAG: [[F_TCLS2F8]]   = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
-// FT-DAG: [[F_TCLS2F9]]   = !{i64 0, !"_ZTSKFvvE.generalized"}
-
-////////////////////////////////////////////////////////////////////////////////
-// Callsites (check for indirect callsite operand bundles)
-
-// CST-LABEL: define {{.*}} @_Z3foov
-void foo() {
-  Cls2 ObjCls2;
-  ObjCls2.fp = &Cls1::receiver;
-
-  // CST: call noundef ptr %{{.*}} [ "type"(metadata !"_ZTSFPvS_S_E.generalized") ]
-  ObjCls2.fp(0, 0);
-
-  auto fp_f1 = &Cls2::f1;
-  auto fp_f2 = &Cls2::f2;
-  auto fp_f3 = &Cls2::f3;
-  auto fp_f4 = &Cls2::f4;
-  auto fp_f5 = &Cls2::f5;
-  auto fp_f6 = &Cls2::f6;
-  auto fp_f7 = &Cls2::f7;
-  auto fp_f8 = &Cls2::f8;
-  auto fp_f9 = &Cls2::f9;
-
-  Cls2 *ObjCls2Ptr = &ObjCls2;
-  Cls1 Cls1Param;
-
-  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFicfdE.generalized") ]
-  (ObjCls2Ptr->*fp_f1)(0, 0, 0);
-
-  // CST: call noundef ptr %{{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
-  (ObjCls2Ptr->*fp_f2)(0, 0, 0);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ]
-  (ObjCls2Ptr->*fp_f3)(Cls1Param);
-
-  // CST: call void  %{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ]
-  (ObjCls2Ptr->*fp_f4)(Cls1Param);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPvE.generalized") ]
-  (ObjCls2Ptr->*fp_f5)(&Cls1Param);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPKvE.generalized") ]
-  (ObjCls2Ptr->*fp_f6)(&Cls1Param);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvR4Cls1E.generalized") ]
-  (ObjCls2Ptr->*fp_f7)(Cls1Param);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvRK4Cls1E.generalized") ]
-  (ObjCls2Ptr->*fp_f8)(Cls1Param);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSKFvvE.generalized") ]
-  (ObjCls2Ptr->*fp_f9)();
-}
diff --git a/clang/test/CodeGen/call-graph-section-2.cpp b/clang/test/CodeGen/call-graph-section-2.cpp
deleted file mode 100644
index 4187faea495be..0000000000000
--- a/clang/test/CodeGen/call-graph-section-2.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-// Tests that we assign appropriate identifiers to indirect calls and targets
-// specifically for C++ templates.
-
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \
-// RUN: -emit-llvm -o %t %s
-// RUN: FileCheck --check-prefix=FT    %s < %t
-// RUN: FileCheck --check-prefix=CST   %s < %t
-// RUN: FileCheck --check-prefix=CHECK %s < %t
-
-////////////////////////////////////////////////////////////////////////////////
-// Class definitions and template classes (check for indirect target metadata)
-
-class Cls1 {};
-
-// Cls2 is instantiated with T=Cls1 in foo(). Following checks are for this
-// instantiation.
-template <class T>
-class Cls2 {
-public:
-  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f1Ev({{.*}} !type [[F_TCLS2F1:![0-9]+]]
-  void f1() {}
-
-  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f2ES0_({{.*}} !type [[F_TCLS2F2:![0-9]+]]
-  void f2(T a) {}
-
-  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f3EPS0_({{.*}} !type [[F_TCLS2F3:![0-9]+]]
-  void f3(T *a) {}
-
-  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f4EPKS0_({{.*}} !type [[F_TCLS2F4:![0-9]+]]
-  void f4(const T *a) {}
-
-  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f5ERS0_({{.*}} !type [[F_TCLS2F5:![0-9]+]]
-  void f5(T &a) {}
-
-  // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f6ERKS0_({{.*}} !type [[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-DAG: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFvvE.generalized"}
-// FT-DAG: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
-// FT-DAG: [[F_TCLS2F3]] = !{i64 0, !"_ZTSFvPvE.generalized"}
-// FT-DAG: [[F_TCLS2F4]] = !{i64 0, !"_ZTSFvPKvE.generalized"}
-// FT-DAG: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
-// FT-DAG: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
-
-////////////////////////////////////////////////////////////////////////////////
-// Callsites (check for indirect callsite operand bundles)
-
-template <class T>
-T *T_func(T a, T *b, const T *c, T &d, const T &e) { return b; }
-
-// CST-LABEL: define {{.*}} @_Z3foov
-void foo() {
-  // Methods for Cls2<Cls1> is checked above within the template description.
-  Cls2<Cls1> Obj;
-
-  // CHECK-DAG: define {{.*}} @_Z6T_funcI4Cls1EPT_S1_S2_PKS1_RS1_RS3_({{.*}} !type [[F_TFUNC_CLS1:![0-9]+]]
-  // CHECK-DAG: [[F_TFUNC_CLS1]] = !{i64 0, !"_ZTSFPv4Cls1S_PKvRS0_RKS0_E.generalized"}
-  Obj.fp = T_func<Cls1>;
-  Cls1 Cls1Obj;
-
-  // CST: call noundef ptr %{{.*}} [ "type"(metadata !"_ZTSFPv4Cls1S_PKvRS0_RKS0_E.generalized") ]
-  Obj.fp(Cls1Obj, &Cls1Obj, &Cls1Obj, Cls1Obj, Cls1Obj);
-
-  // Make indirect calls to Cls2's member methods
-  auto fp_f1 = &Cls2<Cls1>::f1;
-  auto fp_f2 = &Cls2<Cls1>::f2;
-  auto fp_f3 = &Cls2<Cls1>::f3;
-  auto fp_f4 = &Cls2<Cls1>::f4;
-  auto fp_f5 = &Cls2<Cls1>::f5;
-  auto fp_f6 = &Cls2<Cls1>::f6;
-
-  auto *Obj2Ptr = &Obj;
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvvE.generalized") ]
-  (Obj2Ptr->*fp_f1)();
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ]
-  (Obj2Ptr->*fp_f2)(Cls1Obj);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPvE.generalized") ]
-  (Obj2Ptr->*fp_f3)(&Cls1Obj);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPKvE.generalized") ]
-  (Obj2Ptr->*fp_f4)(&Cls1Obj);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvR4Cls1E.generalized") ]
-  (Obj2Ptr->*fp_f5)(Cls1Obj);
-
-  // CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvRK4Cls1E.generalized") ]
-  (Obj2Ptr->*fp_f6)(Cls1Obj);
-}
diff --git a/clang/test/CodeGen/call-graph-section-3.cpp b/clang/test/CodeGen/call-graph-section-3.cpp
deleted file mode 100644
index 77bb110c664ef..0000000000000
--- a/clang/test/CodeGen/call-graph-section-3.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-// Tests that we assign appropriate identifiers to indirect calls and targets
-// specifically for virtual methods.
-
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \
-// RUN: -emit-llvm -o %t %s
-// RUN: FileCheck --check-prefix=FT %s < %t
-// RUN: FileCheck --check-prefix=CST %s < %t
-
-////////////////////////////////////////////////////////////////////////////////
-// Class definitions (check for indirect target metadata)
-
-class Base {
-public:
-  // FT-DAG: define {{.*}} @_ZN4Base2vfEPc({{.*}} !type [[F_TVF:![0-9]+]]
-  virtual int vf(char *a) { return 0; };
-};
-
-class Derived : public Base {
-public:
-  // FT-DAG: define {{.*}} @_ZN7Derived2vfEPc({{.*}} !type [[F_TVF]]
-  int vf(char *a) override { return 1; };
-};
-
-// FT-DAG: [[F_TVF]] = !{i64 0, !"_ZTSFiPvE.generalized"}
-
-////////////////////////////////////////////////////////////////////////////////
-// Callsites (check for indirect callsite operand bundles)
-
-// CST-LABEL: define {{.*}} @_Z3foov
-void foo() {
-  auto B = Base();
-  auto D = Derived();
-
-  Base *Bptr = &B;
-  Base *BptrToD = &D;
-  Derived *Dptr = &D;
-
-  auto FpBaseVf = &Base::vf;
-  auto FpDerivedVf = &Derived::vf;
-
-  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ]
-  (Bptr->*FpBaseVf)(0);
-
-  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ]
-  (BptrToD->*FpBaseVf)(0);
-
-  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ]
-  (Dptr->*FpBaseVf)(0);
-
-  // CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ]
-  (Dptr->*FpDerivedVf)(0);
-}
diff --git a/clang/test/CodeGen/call-graph-section.c b/clang/test/CodeGen/call-graph-section.c
deleted file mode 100644
index ed1bdb876152a..0000000000000
--- a/clang/test/CodeGen/call-graph-section.c
+++ /dev/null
@@ -1,85 +0,0 @@
-// Tests that we assign appropriate identifiers to indirect calls and targets.
-
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \
-// RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,ITANIUM %s
-
-// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fcall-graph-section -S \
-// RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s
-
-// CHECK-DAG: define {{(dso_local)?}} void @foo({{.*}} !type [[F_TVOID:![0-9]+]]
-void foo() {
-}
-
-// CHECK-DAG: define {{(dso_local)?}} void @bar({{.*}} !type [[F_TVOID]]
-void bar() {
-  void (*fp)() = foo;
-  // ITANIUM: call {{.*}} [ "type"(metadata !"_ZTSFvE.generalized") ]
-  // MS:      call {{.*}} [ "type"(metadata !"?6AX at Z.generalized") ]
-  fp();
-}
-
-// CHECK-DAG: define {{(dso_local)?}} i32 @baz({{.*}} !type [[F_TPRIMITIVE:![0-9]+]]
-int baz(char a, float b, double c) {
-  return 1;
-}
-
-// CHECK-DAG: define {{(dso_local)?}} ptr @qux({{.*}} !type [[F_TPTR:![0-9]+]]
-int *qux(char *a, float *b, double *c) {
-  return 0;
-}
-
-// CHECK-DAG: define {{(dso_local)?}} void @corge({{.*}} !type [[F_TVOID]]
-void corge() {
-  int (*fp_baz)(char, float, double) = baz;
-  // ITANIUM: call i32 {{.*}} [ "type"(metadata !"_ZTSFicfdE.generalized") ]
-  // MS:      call i32 {{.*}} [ "type"(metadata !"?6AHDMN at Z.generalized") ]
-  fp_baz('a', .0f, .0);
-
-  int *(*fp_qux)(char *, float *, double *) = qux;
-  // ITANIUM: call ptr {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
-  // MS:      call ptr {{.*}} [ "type"(metadata !"?6APEAXPEAX00 at Z.generalized") ]
-  fp_qux(0, 0, 0);
-}
-
-struct st1 {
-  int *(*fp)(char *, float *, double *);
-};
-
-struct st2 {
-  struct st1 m;
-};
-
-// CHECK-DAG: define {{(dso_local)?}} void @stparam({{.*}} !type [[F_TSTRUCT:![0-9]+]]
-void stparam(struct st2 a, struct st2 *b) {}
-
-// CHECK-DAG: define {{(dso_local)?}} void @stf({{.*}} !type [[F_TVOID]]
-void stf() {
-  struct st1 St1;
-  St1.fp = qux;
-  // ITANIUM: call ptr {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
-  // MS:      call ptr {{.*}} [ "type"(metadata !"?6APEAXPEAX00 at Z.generalized") ]
-  St1.fp(0, 0, 0);
-
-  struct st2 St2;
-  St2.m.fp = qux;
-  // ITANIUM: call ptr {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
-  // MS:      call ptr {{.*}} [ "type"(metadata !"?6APEAXPEAX00 at Z.generalized") ]
-  St2.m.fp(0, 0, 0);
-
-  // ITANIUM: call void {{.*}} [ "type"(metadata !"_ZTSFv3st2PvE.generalized") ]
-  // MS:      call void {{.*}} [ "type"(metadata !"?6AXUst2@@PEAX at Z.generalized") ]
-  void (*fp_stparam)(struct st2, struct st2 *) = stparam;
-  fp_stparam(St2, &St2);
-}
-
-// ITANIUM-DAG: [[F_TVOID]] = !{i64 0, !"_ZTSFvE.generalized"}
-// MS-DAG:      [[F_TVOID]] = !{i64 0, !"?6AX at Z.generalized"}
-
-// ITANIUM-DAG: [[F_TPRIMITIVE]] = !{i64 0, !"_ZTSFicfdE.generalized"}
-// MS-DAG:      [[F_TPRIMITIVE]] = !{i64 0, !"?6AHDMN at Z.generalized"}
-
-// ITANIUM-DAG: [[F_TPTR]] = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"}
-// MS-DAG:      [[F_TPTR]] = !{i64 0, !"?6APEAXPEAX00 at Z.generalized"}
-
-// ITANIUM-DAG: [[F_TSTRUCT]] = !{i64 0, !"_ZTSFv3st2PvE.generalized"}
-// MS-DAG:      [[F_TSTRUCT]] = !{i64 0, !"?6AXUst2@@PEAX at Z.generalized"}
diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h
index d5448d781363d..eb93192700a83 100644
--- a/llvm/include/llvm/CodeGen/CommandFlags.h
+++ b/llvm/include/llvm/CodeGen/CommandFlags.h
@@ -132,6 +132,8 @@ bool getEnableStackSizeSection();
 
 bool getEnableAddrsig();
 
+bool getEnableCallGraphSection();
+
 bool getEmitCallSiteInfo();
 
 bool getEnableMachineFunctionSplitter();
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index 88f253805ca99..68270d5fcfa85 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -146,10 +146,11 @@ namespace llvm {
           EmulatedTLS(false), EnableTLSDESC(false), EnableIPRA(false),
           EmitStackSizeSection(false), EnableMachineOutliner(false),
           EnableMachineFunctionSplitter(false), SupportsDefaultOutlining(false),
-          EmitAddrsig(false), BBAddrMap(false), EmitCallSiteInfo(false),
-          SupportsDebugEntryValues(false), EnableDebugEntryValues(false),
-          ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
-          XRayFunctionIndex(true), DebugStrictDwarf(false), Hotpatch(false),
+          EmitAddrsig(false), BBAddrMap(false), EmitCallGraphSection(false),
+          EmitCallSiteInfo(false), SupportsDebugEntryValues(false),
+          EnableDebugEntryValues(false), ValueTrackingVariableLocations(false),
+          ForceDwarfFrameSection(false), XRayFunctionIndex(true),
+          DebugStrictDwarf(false), Hotpatch(false),
           PPCGenScalarMASSEntries(false), JMCInstrument(false),
           EnableCFIFixup(false), MisExpect(false), XCOFFReadOnlyPointers(false),
           VerifyArgABICompliance(true),
@@ -329,6 +330,9 @@ namespace llvm {
     /// to selectively generate basic block sections.
     std::shared_ptr<MemoryBuffer> BBSectionsFuncListBuf;
 
+    /// Emit section containing call graph metadata.
+    unsigned EmitCallGraphSection : 1;
+
     /// The flag enables call site info production. It is used only for debug
     /// info, and it is restricted only to optimized code. This can be used for
     /// something else, so that should be controlled in the frontend.
diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp
index d180cfcea658c..c2a7a0d7ea663 100644
--- a/llvm/lib/CodeGen/CommandFlags.cpp
+++ b/llvm/lib/CodeGen/CommandFlags.cpp
@@ -101,6 +101,7 @@ CGOPT(EABI, EABIVersion)
 CGOPT(DebuggerKind, DebuggerTuningOpt)
 CGOPT(bool, EnableStackSizeSection)
 CGOPT(bool, EnableAddrsig)
+CGOPT(bool, EnableCallGraphSection)
 CGOPT(bool, EmitCallSiteInfo)
 CGOPT(bool, EnableMachineFunctionSplitter)
 CGOPT(bool, EnableDebugEntryValues)
@@ -460,6 +461,11 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
       cl::init(false));
   CGBINDOPT(EnableAddrsig);
 
+  static cl::opt<bool> EnableCallGraphSection(
+      "call-graph-section", cl::desc("Emit a call graph section"),
+      cl::init(false));
+  CGBINDOPT(EnableCallGraphSection);
+
   static cl::opt<bool> EmitCallSiteInfo(
       "emit-call-site-info",
       cl::desc(
@@ -587,6 +593,7 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
   Options.EmitStackSizeSection = getEnableStackSizeSection();
   Options.EnableMachineFunctionSplitter = getEnableMachineFunctionSplitter();
   Options.EmitAddrsig = getEnableAddrsig();
+  Options.EmitCallGraphSection = getEnableCallGraphSection();
   Options.EmitCallSiteInfo = getEmitCallSiteInfo();
   Options.EnableDebugEntryValues = getEnableDebugEntryValues();
   Options.ForceDwarfFrameSection = getForceDwarfFrameSection();
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 0ad7ba555bfad..b72672e7b8e56 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3707,10 +3707,9 @@ void Verifier::visitCallBase(CallBase &Call) {
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
       visitIntrinsicCall(ID, Call);
 
-  // Verify that a callsite has at most one "deopt", at most one "funclet", at
-  // most one "gc-transition", at most one "cfguardtarget", at most one "type",
-  // at most one "preallocated" operand bundle, and at most one "ptrauth"
-  // operand bundle.
+  // Verify that a callsite has at most one operand bundle for each of the
+  // following: "deopt", "funclet", "gc-transition", "cfguardtarget", "type",
+  // "preallocated", and "ptrauth".
   bool FoundDeoptBundle = false, FoundFuncletBundle = false,
        FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false,
        FoundPreallocatedBundle = false, FoundGCLiveBundle = false,
diff --git a/llvm/test/Verifier/operand-bundles.ll b/llvm/test/Verifier/operand-bundles.ll
index 788006494edce..575cafad66279 100644
--- a/llvm/test/Verifier/operand-bundles.ll
+++ b/llvm/test/Verifier/operand-bundles.ll
@@ -105,13 +105,13 @@ declare ptr @objc_retainAutoreleasedReturnValue(ptr)
 declare ptr @objc_unsafeClaimAutoreleasedReturnValue(ptr)
 declare void @llvm.assume(i1)
 
-define void @f_type(i32* %ptr) {
+define void @f_type(ptr %ptr) {
 ; CHECK: Multiple "type" operand bundles
 ; CHECK-NEXT: call void @g() [ "type"(metadata !"_ZTSFvE.generalized"), "type"(metadata !"_ZTSFvE.generalized") ]
 ; CHECK-NOT: call void @g() [ "type"(metadata !"_ZTSFvE.generalized") ]
 
  entry:
-  %l = load i32, i32* %ptr
+  %l = load i32, ptr %ptr, align 4
   call void @g() [ "type"(metadata !"_ZTSFvE.generalized"), "type"(metadata !"_ZTSFvE.generalized") ]
   call void @g() [ "type"(metadata !"_ZTSFvE.generalized") ]
   %x = add i32 42, 1

>From 1d7ee612e408ee7e64e984eb08e6d7089a435d09 Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Sun, 2 Feb 2025 00:58:49 +0000
Subject: [PATCH 06/33] Simplify MIR test.

Created using spr 1.3.6-beta.1
---
 .../CodeGen/MIR/X86/call-site-info-typeid.mir | 21 ++++++-------------
 1 file changed, 6 insertions(+), 15 deletions(-)

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 5ab797bfcc18f..a99ee50a608fb 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -8,11 +8,6 @@
 # CHECK-NEXT: 123456789 }
 
 --- |
-  ; ModuleID = 'test.ll'
-  source_filename = "test.ll"
-  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-  target triple = "x86_64-unknown-linux-gnu"
-  
   define dso_local void @foo(i8 signext %a) {
   entry:
     ret void
@@ -21,10 +16,10 @@
   define dso_local i32 @main() {
   entry:
     %retval = alloca i32, align 4
-    %fp = alloca void (i8)*, align 8
-    store i32 0, i32* %retval, align 4
-    store void (i8)* @foo, void (i8)** %fp, align 8
-    %0 = load void (i8)*, void (i8)** %fp, align 8
+    %fp = alloca ptr, align 8
+    store i32 0, ptr %retval, align 4
+    store ptr @foo, ptr %fp, align 8
+    %0 = load ptr, ptr %fp, align 8
     call void %0(i8 signext 97)
     ret i32 0
   }
@@ -42,12 +37,8 @@ body:             |
 name:            main
 tracksRegLiveness: true
 stack:
-  - { id: 0, name: retval, type: default, offset: 0, size: 4, alignment: 4, 
-      stack-id: default, callee-saved-register: '', callee-saved-restored: true, 
-      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
-  - { id: 1, name: fp, type: default, offset: 0, size: 8, alignment: 8, 
-      stack-id: default, callee-saved-register: '', callee-saved-restored: true, 
-      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 0, name: retval, size: 4, alignment: 4 }
+  - { id: 1, name: fp, size: 8, alignment: 8 }
 callSites:
   - { bb: 0, offset: 6, fwdArgRegs: [], typeId: 
     123456789 }

>From 9db0468ec19e4ee0720b6a5bb9adeab5a91a20a4 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 5 Feb 2025 23:07:12 +0000
Subject: [PATCH 07/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/include/llvm/IR/LLVMContext.h                  |  2 +-
 .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp    |  7 ++++---
 llvm/lib/IR/LLVMContext.cpp                         |  6 +++---
 llvm/lib/IR/Verifier.cpp                            | 13 +++++++------
 llvm/test/Verifier/operand-bundles.ll               | 10 +++++-----
 5 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h
index a84d470e76d5d..97ff6b73f4473 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -96,7 +96,7 @@ class LLVMContext {
     OB_ptrauth = 7,                // "ptrauth"
     OB_kcfi = 8,                   // "kcfi"
     OB_convergencectrl = 9,        // "convergencectrl"
-    OB_type = 10,                  // "type"
+    OB_callee_type = 10,           // "callee_type"
   };
 
   /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8d224bd55e1d2..a8b94afb7e002 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3333,7 +3333,8 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
              {LLVMContext::OB_deopt, LLVMContext::OB_gc_transition,
               LLVMContext::OB_gc_live, LLVMContext::OB_funclet,
               LLVMContext::OB_cfguardtarget, LLVMContext::OB_ptrauth,
-              LLVMContext::OB_clang_arc_attachedcall, LLVMContext::OB_type}) &&
+              LLVMContext::OB_clang_arc_attachedcall,
+              LLVMContext::OB_callee_type}) &&
          "Cannot lower invokes with arbitrary operand bundles yet!");
 
   const Value *Callee(I.getCalledOperand());
@@ -3424,7 +3425,7 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
   // have to do anything here to lower funclet bundles.
   assert(!I.hasOperandBundlesOtherThan({LLVMContext::OB_deopt,
                                         LLVMContext::OB_funclet,
-                                        LLVMContext::OB_type}) &&
+                                        LLVMContext::OB_callee_type}) &&
          "Cannot lower callbrs with arbitrary operand bundles yet!");
 
   assert(I.isInlineAsm() && "Only know how to handle inlineasm callbr");
@@ -9588,7 +9589,7 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
              {LLVMContext::OB_deopt, LLVMContext::OB_funclet,
               LLVMContext::OB_cfguardtarget, LLVMContext::OB_preallocated,
               LLVMContext::OB_clang_arc_attachedcall, LLVMContext::OB_kcfi,
-              LLVMContext::OB_convergencectrl, LLVMContext::OB_type}) &&
+              LLVMContext::OB_convergencectrl, LLVMContext::OB_callee_type}) &&
          "Cannot lower calls with arbitrary operand bundles!");
 
   SDValue Callee = getValue(I.getCalledOperand());
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 8ab7c37583361..18e95978bd9f6 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -82,9 +82,9 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
     assert(Entry->second == BundleTagID && "operand bundle id drifted!");
   }
 
-  [[maybe_unused]] auto *TypeEntry = pImpl->getOrInsertBundleTag("type");
-  assert(TypeEntry->second == LLVMContext::OB_type &&
-         "type operand bundle id drifted!");
+  [[maybe_unused]] auto *TypeEntry = pImpl->getOrInsertBundleTag("callee_type");
+  assert(TypeEntry->second == LLVMContext::OB_callee_type &&
+         "callee_type operand bundle id drifted!");
 
   SyncScope::ID SingleThreadSSID =
       pImpl->getOrInsertSyncScopeID("singlethread");
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 19f7c3388bac6..34c751e6357c6 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3722,13 +3722,13 @@ void Verifier::visitCallBase(CallBase &Call) {
       visitIntrinsicCall(ID, Call);
 
   // Verify that a callsite has at most one operand bundle for each of the
-  // following: "deopt", "funclet", "gc-transition", "cfguardtarget", "type",
-  // "preallocated", and "ptrauth".
+  // following: "deopt", "funclet", "gc-transition", "cfguardtarget",
+  // "callee_type", "preallocated", and "ptrauth".
   bool FoundDeoptBundle = false, FoundFuncletBundle = false,
        FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false,
        FoundPreallocatedBundle = false, FoundGCLiveBundle = false,
        FoundPtrauthBundle = false, FoundKCFIBundle = false,
-       FoundAttachedCallBundle = false, FoundTypeBundle = false;
+       FoundAttachedCallBundle = false, FoundCalleeTypeBundle = false;
   for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) {
     OperandBundleUse BU = Call.getOperandBundleAt(i);
     uint32_t Tag = BU.getTagID();
@@ -3791,9 +3791,10 @@ void Verifier::visitCallBase(CallBase &Call) {
             "Multiple \"clang.arc.attachedcall\" operand bundles", Call);
       FoundAttachedCallBundle = true;
       verifyAttachedCallBundle(Call, BU);
-    } else if (Tag == LLVMContext::OB_type) {
-      Check(!FoundTypeBundle, "Multiple \"type\" operand bundles", Call);
-      FoundTypeBundle = true;
+    } else if (Tag == LLVMContext::OB_callee_type) {
+      Check(!FoundCalleeTypeBundle, "Multiple \"callee_type\" operand bundles",
+            Call);
+      FoundCalleeTypeBundle = true;
     }
   }
 
diff --git a/llvm/test/Verifier/operand-bundles.ll b/llvm/test/Verifier/operand-bundles.ll
index 575cafad66279..79b5af35b353e 100644
--- a/llvm/test/Verifier/operand-bundles.ll
+++ b/llvm/test/Verifier/operand-bundles.ll
@@ -106,14 +106,14 @@ declare ptr @objc_unsafeClaimAutoreleasedReturnValue(ptr)
 declare void @llvm.assume(i1)
 
 define void @f_type(ptr %ptr) {
-; CHECK: Multiple "type" operand bundles
-; CHECK-NEXT: call void @g() [ "type"(metadata !"_ZTSFvE.generalized"), "type"(metadata !"_ZTSFvE.generalized") ]
-; CHECK-NOT: call void @g() [ "type"(metadata !"_ZTSFvE.generalized") ]
+; CHECK: Multiple "callee_type" operand bundles
+; CHECK-NEXT: call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized"), "callee_type"(metadata !"_ZTSFvE.generalized") ]
+; CHECK-NOT: call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized") ]
 
  entry:
   %l = load i32, ptr %ptr, align 4
-  call void @g() [ "type"(metadata !"_ZTSFvE.generalized"), "type"(metadata !"_ZTSFvE.generalized") ]
-  call void @g() [ "type"(metadata !"_ZTSFvE.generalized") ]
+  call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized"), "callee_type"(metadata !"_ZTSFvE.generalized") ]
+  call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized") ]
   %x = add i32 42, 1
   ret void
 }

>From f6ea85324f829ad66ad1f60793e51ce4084211aa Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 11 Feb 2025 21:21:12 +0000
Subject: [PATCH 08/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/include/llvm/CodeGen/CommandFlags.h |  2 --
 llvm/include/llvm/Target/TargetOptions.h | 12 ++++--------
 llvm/lib/CodeGen/CommandFlags.cpp        |  7 -------
 3 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h
index 8476b313756d0..000aed782a805 100644
--- a/llvm/include/llvm/CodeGen/CommandFlags.h
+++ b/llvm/include/llvm/CodeGen/CommandFlags.h
@@ -132,8 +132,6 @@ bool getEnableStackSizeSection();
 
 bool getEnableAddrsig();
 
-bool getEnableCallGraphSection();
-
 bool getEmitCallSiteInfo();
 
 bool getEnableMachineFunctionSplitter();
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index a2b8c62ffb259..fd8dad4f6f791 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -147,11 +147,10 @@ namespace llvm {
           EmitStackSizeSection(false), EnableMachineOutliner(false),
           EnableMachineFunctionSplitter(false),
           EnableStaticDataPartitioning(false), SupportsDefaultOutlining(false),
-          EmitAddrsig(false), BBAddrMap(false), EmitCallGraphSection(false),
-          EmitCallSiteInfo(false), SupportsDebugEntryValues(false),
-          EnableDebugEntryValues(false), ValueTrackingVariableLocations(false),
-          ForceDwarfFrameSection(false), XRayFunctionIndex(true),
-          DebugStrictDwarf(false), Hotpatch(false),
+          EmitAddrsig(false), BBAddrMap(false), EmitCallSiteInfo(false),
+          SupportsDebugEntryValues(false), EnableDebugEntryValues(false),
+          ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
+          XRayFunctionIndex(true), DebugStrictDwarf(false), Hotpatch(false),
           PPCGenScalarMASSEntries(false), JMCInstrument(false),
           EnableCFIFixup(false), MisExpect(false), XCOFFReadOnlyPointers(false),
           VerifyArgABICompliance(true),
@@ -334,9 +333,6 @@ namespace llvm {
     /// to selectively generate basic block sections.
     std::shared_ptr<MemoryBuffer> BBSectionsFuncListBuf;
 
-    /// Emit section containing call graph metadata.
-    unsigned EmitCallGraphSection : 1;
-
     /// The flag enables call site info production. It is used only for debug
     /// info, and it is restricted only to optimized code. This can be used for
     /// something else, so that should be controlled in the frontend.
diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp
index f7f796daf02a2..023656cde0089 100644
--- a/llvm/lib/CodeGen/CommandFlags.cpp
+++ b/llvm/lib/CodeGen/CommandFlags.cpp
@@ -101,7 +101,6 @@ CGOPT(EABI, EABIVersion)
 CGOPT(DebuggerKind, DebuggerTuningOpt)
 CGOPT(bool, EnableStackSizeSection)
 CGOPT(bool, EnableAddrsig)
-CGOPT(bool, EnableCallGraphSection)
 CGOPT(bool, EmitCallSiteInfo)
 CGOPT(bool, EnableMachineFunctionSplitter)
 CGOPT(bool, EnableStaticDataPartitioning)
@@ -462,11 +461,6 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
       cl::init(false));
   CGBINDOPT(EnableAddrsig);
 
-  static cl::opt<bool> EnableCallGraphSection(
-      "call-graph-section", cl::desc("Emit a call graph section"),
-      cl::init(false));
-  CGBINDOPT(EnableCallGraphSection);
-
   static cl::opt<bool> EmitCallSiteInfo(
       "emit-call-site-info",
       cl::desc(
@@ -601,7 +595,6 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
   Options.EnableMachineFunctionSplitter = getEnableMachineFunctionSplitter();
   Options.EnableStaticDataPartitioning = getEnableStaticDataPartitioning();
   Options.EmitAddrsig = getEnableAddrsig();
-  Options.EmitCallGraphSection = getEnableCallGraphSection();
   Options.EmitCallSiteInfo = getEmitCallSiteInfo();
   Options.EnableDebugEntryValues = getEnableDebugEntryValues();
   Options.ForceDwarfFrameSection = getForceDwarfFrameSection();

>From 86e2c9dc37170499252ed50c6bbef2931e106fbb Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 13 Mar 2025 01:03:40 +0000
Subject: [PATCH 09/33] Add requested tests part 1.

Created using spr 1.3.6-beta.1
---
 ...te-info-ambiguous-indirect-call-typeid.mir | 145 ++++++++++++++++++
 .../call-site-info-direct-calls-typeid.mir    | 145 ++++++++++++++++++
 2 files changed, 290 insertions(+)
 create mode 100644 llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir
 create mode 100644 llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir

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
new file mode 100644
index 0000000000000..9d1b099cc9093
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir
@@ -0,0 +1,145 @@
+# Test MIR printer and parser for type id field in callSites. It is used
+# for propogating call site type identifiers to emit in the call graph section.
+
+# RUN: llc --call-graph-section %s -run-pass=none -o - | FileCheck %s
+# CHECK: name: main
+# CHECK: callSites:
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
+# CHECK-NEXT: 1234567890 }
+
+--- |  
+  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
+  define dso_local noundef i32 @_Z3addii(i32 noundef %a, i32 noundef %b) #0 !type !6 !type !6 {
+  entry:
+    %a.addr = alloca i32, align 4
+    %b.addr = alloca i32, align 4
+    store i32 %a, ptr %a.addr, align 4
+    store i32 %b, ptr %b.addr, align 4
+    %0 = load i32, ptr %a.addr, align 4
+    %1 = load i32, ptr %b.addr, align 4
+    %add = add nsw i32 %0, %1
+    ret i32 %add
+  }
+  
+  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
+  define dso_local noundef i32 @_Z8multiplyii(i32 noundef %a, i32 noundef %b) #0 !type !6 !type !6 {
+  entry:
+    %a.addr = alloca i32, align 4
+    %b.addr = alloca i32, align 4
+    store i32 %a, ptr %a.addr, align 4
+    store i32 %b, ptr %b.addr, align 4
+    %0 = load i32, ptr %a.addr, align 4
+    %1 = load i32, ptr %b.addr, align 4
+    %mul = mul nsw i32 %0, %1
+    ret i32 %mul
+  }
+  
+  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
+  define dso_local noundef ptr @_Z13get_operationb(i1 noundef zeroext %is_addition) #0 !type !7 !type !7 {
+  entry:
+    %is_addition.addr = alloca i8, align 1
+    %storedv = zext i1 %is_addition to i8
+    store i8 %storedv, ptr %is_addition.addr, align 1
+    %0 = load i8, ptr %is_addition.addr, align 1
+    %loadedv = trunc i8 %0 to i1
+    br i1 %loadedv, label %cond.true, label %cond.false
+  
+  cond.true:                                        ; preds = %entry
+    br label %cond.end
+  
+  cond.false:                                       ; preds = %entry
+    br label %cond.end
+  
+  cond.end:                                         ; preds = %cond.false, %cond.true
+    %cond = phi ptr [ @_Z3addii, %cond.true ], [ @_Z8multiplyii, %cond.false ]
+    ret ptr %cond
+  }
+  
+  ; Function Attrs: mustprogress noinline norecurse optnone uwtable
+  define dso_local noundef i32 @main(i32 noundef %argc) #1 !type !8 !type !8 {
+  entry:
+    %retval = alloca i32, align 4
+    %argc.addr = alloca i32, align 4
+    %x = alloca i32, align 4
+    %y = alloca i32, align 4
+    %op = alloca ptr, align 8
+    store i32 0, ptr %retval, align 4
+    store i32 %argc, ptr %argc.addr, align 4
+    store i32 5, ptr %x, align 4
+    store i32 10, ptr %y, align 4
+    %0 = load i32, ptr %argc.addr, align 4
+    %rem = srem i32 %0, 2
+    %cmp = icmp eq i32 %rem, 0
+    %call = call noundef ptr @_Z13get_operationb(i1 noundef zeroext %cmp) [ "callee_type"(metadata !"_ZTSFPvbE.generalized") ]
+    store ptr %call, ptr %op, align 8
+    %1 = load ptr, ptr %op, align 8
+    %2 = load i32, ptr %x, align 4
+    %3 = load i32, ptr %y, align 4
+    %call1 = call noundef i32 %1(i32 noundef %2, i32 noundef %3) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    ret i32 %call1
+  }
+  
+  attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+  attributes #1 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+  
+  !6 = !{i64 0, !"_ZTSFiiiE.generalized"}
+  !7 = !{i64 0, !"_ZTSFPvbE.generalized"}
+  !8 = !{i64 0, !"_ZTSFiiE.generalized"}
+
+...
+---
+name:            main
+liveins:
+  - { reg: '$edi', virtual-reg: '%0' }
+stack:
+  - { id: 0, name: retval, size: 4 }
+  - { id: 1, name: argc.addr, size: 4 }
+  - { id: 2, name: x, size: 4 }
+  - { id: 3, name: y, size: 4 }
+  - { id: 4, name: op, size: 8 }
+callSites:
+  - { bb: 0, offset: 18, fwdArgRegs: [] }
+  - { bb: 0, offset: 29, fwdArgRegs: [], typeId: 
+    1234567890 }
+body:             |
+  bb.0.entry:
+    liveins: $edi
+  
+    %0:gr32 = COPY $edi
+    %1:gr32 = COPY killed %0
+    MOV32mi %stack.0.retval, 1, $noreg, 0, $noreg, 0 :: (store (s32) into %ir.retval)
+    MOV32mr %stack.1.argc.addr, 1, $noreg, 0, $noreg, %1 :: (store (s32) into %ir.argc.addr)
+    MOV32mi %stack.2.x, 1, $noreg, 0, $noreg, 5 :: (store (s32) into %ir.x)
+    MOV32mi %stack.3.y, 1, $noreg, 0, $noreg, 10 :: (store (s32) into %ir.y)
+    %21:gr32 = MOV32rm %stack.1.argc.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.argc.addr)
+    %19:gr32 = MOV32ri 2
+    $eax = COPY %21
+    CDQ implicit-def $eax, implicit-def $edx, implicit $eax
+    IDIV32r %19, implicit-def $eax, implicit-def $edx, implicit-def $eflags, implicit $eax, implicit $edx
+    %20:gr32 = COPY $edx
+    CMP32ri %20, 0, implicit-def $eflags
+    %15:gr8 = SETCCr 4, implicit $eflags
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    %12:gr32 = MOVZX32rr8 %15
+    %13:gr32 = AND32ri %12, 1, implicit-def dead $eflags
+    $edi = COPY %13
+    CALL64pcrel32 @_Z13get_operationb, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
+    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    %14:gr64 = COPY $rax
+    %10:gr64 = COPY %14
+    MOV64mr %stack.4.op, 1, $noreg, 0, $noreg, %10 :: (store (s64) into %ir.op)
+    %9:gr64 = MOV64rm %stack.4.op, 1, $noreg, 0, $noreg :: (load (s64) from %ir.op)
+    %8:gr32 = MOV32rm %stack.2.x, 1, $noreg, 0, $noreg :: (load (s32) from %ir.x)
+    %7:gr32 = MOV32rm %stack.3.y, 1, $noreg, 0, $noreg :: (load (s32) from %ir.y)
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    $edi = COPY %8
+    $esi = COPY %7
+    CALL64r %9, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    %6:gr32 = COPY $eax
+    %2:gr32 = COPY %6
+    $eax = COPY %2
+    RET64 implicit $eax
+
+...
diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
new file mode 100644
index 0000000000000..564cc8268e5cd
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
@@ -0,0 +1,145 @@
+# Test MIR printer and parser to NOT have `typeId` field in callSites. `typeId` is used
+# for propogating call site type identifiers to emit in the call graph section for
+# indirect targets only. This test do not contain any indirect targets.
+
+# RUN: llc --call-graph-section %s -run-pass=none -o - | FileCheck %s
+# CHECK-NOT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
+# CHECK: name: _Z3barii
+# CHECK: callSites:
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
+# CHECK: name: _Z3fooii
+# CHECK: callSites:
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
+
+--- |  
+  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
+  define dso_local noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y) #0 !type !6 !type !6 {
+  entry:
+    %x.addr = alloca i32, align 4
+    %y.addr = alloca i32, align 4
+    store i32 %x, ptr %x.addr, align 4
+    store i32 %y, ptr %y.addr, align 4
+    %0 = load i32, ptr %x.addr, align 4
+    %1 = load i32, ptr %y.addr, align 4
+    %add = add nsw i32 %0, %1
+    ret i32 %add
+  }
+  
+  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
+  define dso_local noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y) #0 !type !6 !type !6 {
+  entry:
+    %x.addr = alloca i32, align 4
+    %y.addr = alloca i32, align 4
+    store i32 %x, ptr %x.addr, align 4
+    store i32 %y, ptr %y.addr, align 4
+    %0 = load i32, ptr %x.addr, align 4
+    %1 = load i32, ptr %y.addr, align 4
+    %mul = mul nsw i32 %0, %1
+    ret i32 %mul
+  }
+  
+  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
+  define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) #0 !type !6 !type !6 {
+  entry:
+    %x.addr = alloca i32, align 4
+    %y.addr = alloca i32, align 4
+    store i32 %x, ptr %x.addr, align 4
+    store i32 %y, ptr %y.addr, align 4
+    %0 = load i32, ptr %x.addr, align 4
+    %1 = load i32, ptr %y.addr, align 4
+    %call = call noundef i32 @_Z4buzzii(i32 noundef %0, i32 noundef %1) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %2 = load i32, ptr %x.addr, align 4
+    %3 = load i32, ptr %y.addr, align 4
+    %call1 = call noundef i32 @_Z4fizzii(i32 noundef %2, i32 noundef %3) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %sub = sub nsw i32 %call, %call1
+    ret i32 %sub
+  }
+  
+  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
+  define dso_local noundef i32 @_Z3fooii(i32 noundef %x, i32 noundef %y) #0 !type !6 !type !6 {
+  entry:
+    %x.addr = alloca i32, align 4
+    %y.addr = alloca i32, align 4
+    store i32 %x, ptr %x.addr, align 4
+    store i32 %y, ptr %y.addr, align 4
+    %0 = load i32, ptr %x.addr, align 4
+    %1 = load i32, ptr %y.addr, align 4
+    %call = call noundef i32 @_Z3barii(i32 noundef %0, i32 noundef %1) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    ret i32 %call
+  }  
+  
+  !6 = !{i64 0, !"_ZTSFiiiE.generalized"}
+
+...
+---
+name:            _Z3barii
+stack:
+  - { id: 0, name: x.addr, size: 4 }
+  - { id: 1, name: y.addr, size: 4 }
+callSites:
+  - { bb: 0, offset: 11, fwdArgRegs: [] }
+  - { bb: 0, offset: 20, fwdArgRegs: [] }
+body:             |
+  bb.0.entry:
+    liveins: $edi, $esi
+  
+    %2:gr32 = COPY $esi
+    %0:gr32 = COPY $edi
+    %1:gr32 = COPY killed %0
+    %3:gr32 = COPY killed %2
+    MOV32mr %stack.0.x.addr, 1, $noreg, 0, $noreg, %1 :: (store (s32) into %ir.x.addr)
+    MOV32mr %stack.1.y.addr, 1, $noreg, 0, $noreg, %3 :: (store (s32) into %ir.y.addr)
+    %17:gr32 = MOV32rm %stack.0.x.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.x.addr)
+    %16:gr32 = MOV32rm %stack.1.y.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.y.addr)
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    $edi = COPY %17
+    $esi = COPY %16
+    CALL64pcrel32 @_Z4buzzii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    %15:gr32 = COPY $eax
+    %5:gr32 = COPY %15
+    %12:gr32 = MOV32rm %stack.0.x.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.x.addr)
+    %11:gr32 = MOV32rm %stack.1.y.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.y.addr)
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    $edi = COPY %12
+    $esi = COPY %11
+    CALL64pcrel32 @_Z4fizzii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    %10:gr32 = COPY $eax
+    %6:gr32 = COPY %10
+    %7:gr32 = SUB32rr %5, %6, implicit-def $eflags
+    $eax = COPY %7
+    RET64 implicit $eax
+
+...
+---
+name:            _Z3fooii
+stack:
+  - { id: 0, name: x.addr, size: 4 }
+  - { id: 1, name: y.addr, size: 4 }
+callSites:
+  - { bb: 0, offset: 11, fwdArgRegs: [] }
+body:             |
+  bb.0.entry:
+    liveins: $edi, $esi
+  
+    %2:gr32 = COPY $esi
+    %0:gr32 = COPY $edi
+    %1:gr32 = COPY killed %0
+    %3:gr32 = COPY killed %2
+    MOV32mr %stack.0.x.addr, 1, $noreg, 0, $noreg, %1 :: (store (s32) into %ir.x.addr)
+    MOV32mr %stack.1.y.addr, 1, $noreg, 0, $noreg, %3 :: (store (s32) into %ir.y.addr)
+    %9:gr32 = MOV32rm %stack.0.x.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.x.addr)
+    %8:gr32 = MOV32rm %stack.1.y.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.y.addr)
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    $edi = COPY %9
+    $esi = COPY %8
+    CALL64pcrel32 @_Z3barii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    %7:gr32 = COPY $eax
+    %4:gr32 = COPY %7
+    $eax = COPY %4
+    RET64 implicit $eax
+
+...

>From 941dde570c6de52c41101a06c8ccb28f377021ee Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 13 Mar 2025 01:21:26 +0000
Subject: [PATCH 10/33] Update comments in tests.

Created using spr 1.3.6-beta.1
---
 .../X86/call-site-info-ambiguous-indirect-call-typeid.mir   | 3 ---
 .../CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir  | 6 +++---
 2 files changed, 3 insertions(+), 6 deletions(-)

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 9d1b099cc9093..40fb1ddbbc004 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
@@ -80,9 +80,6 @@
     ret i32 %call1
   }
   
-  attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
-  attributes #1 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
-  
   !6 = !{i64 0, !"_ZTSFiiiE.generalized"}
   !7 = !{i64 0, !"_ZTSFPvbE.generalized"}
   !8 = !{i64 0, !"_ZTSFiiE.generalized"}
diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
index 564cc8268e5cd..528ddb5908d0d 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
@@ -1,6 +1,6 @@
-# Test MIR printer and parser to NOT have `typeId` field in callSites. `typeId` is used
-# for propogating call site type identifiers to emit in the call graph section for
-# indirect targets only. This test do not contain any indirect targets.
+# Test MIR printer and parser to NOT have `typeId` field in callSites.
+# `typeId` is used for propogating call site type identifiers for
+# indirect targets only. This test does not contain any indirect targets.
 
 # RUN: llc --call-graph-section %s -run-pass=none -o - | FileCheck %s
 # CHECK-NOT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:

>From 431fafc60347e65219f1cccd0cff474432c928ed Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Sat, 15 Mar 2025 01:09:45 +0000
Subject: [PATCH 11/33] Clean up test files.

Created using spr 1.3.6-beta.1
---
 ...te-info-ambiguous-indirect-call-typeid.mir | 107 +++++-------------
 .../call-site-info-direct-calls-typeid.mir    | 107 +++++-------------
 .../CodeGen/MIR/X86/call-site-info-typeid.mir |  31 +----
 3 files changed, 60 insertions(+), 185 deletions(-)

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 40fb1ddbbc004..18aad1813339a 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
@@ -9,55 +9,48 @@
 # CHECK-NEXT: 1234567890 }
 
 --- |  
-  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
-  define dso_local noundef i32 @_Z3addii(i32 noundef %a, i32 noundef %b) #0 !type !6 !type !6 {
+  define dso_local noundef i32 @_Z3addii(i32 noundef %a, i32 noundef %b) !type !0 !type !0 {
   entry:
     %a.addr = alloca i32, align 4
     %b.addr = alloca i32, align 4
     store i32 %a, ptr %a.addr, align 4
     store i32 %b, ptr %b.addr, align 4
-    %0 = load i32, ptr %a.addr, align 4
-    %1 = load i32, ptr %b.addr, align 4
-    %add = add nsw i32 %0, %1
+    %a_val = load i32, ptr %a.addr, align 4
+    %b_val = load i32, ptr %b.addr, align 4
+    %add = add nsw i32 %a_val, %b_val
     ret i32 %add
   }
   
-  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
-  define dso_local noundef i32 @_Z8multiplyii(i32 noundef %a, i32 noundef %b) #0 !type !6 !type !6 {
+  define dso_local noundef i32 @_Z8multiplyii(i32 noundef %a, i32 noundef %b) !type !0 !type !0 {
   entry:
     %a.addr = alloca i32, align 4
     %b.addr = alloca i32, align 4
     store i32 %a, ptr %a.addr, align 4
     store i32 %b, ptr %b.addr, align 4
-    %0 = load i32, ptr %a.addr, align 4
-    %1 = load i32, ptr %b.addr, align 4
-    %mul = mul nsw i32 %0, %1
+    %a_val = load i32, ptr %a.addr, align 4
+    %b_val = load i32, ptr %b.addr, align 4
+    %mul = mul nsw i32 %a_val, %b_val
     ret i32 %mul
   }
   
-  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
-  define dso_local noundef ptr @_Z13get_operationb(i1 noundef zeroext %is_addition) #0 !type !7 !type !7 {
+  define dso_local noundef ptr @_Z13get_operationb(i1 noundef zeroext %is_addition) !type !1 !type !1 {
   entry:
     %is_addition.addr = alloca i8, align 1
     %storedv = zext i1 %is_addition to i8
     store i8 %storedv, ptr %is_addition.addr, align 1
-    %0 = load i8, ptr %is_addition.addr, align 1
-    %loadedv = trunc i8 %0 to i1
-    br i1 %loadedv, label %cond.true, label %cond.false
-  
-  cond.true:                                        ; preds = %entry
-    br label %cond.end
+    %is_addition_val = load i8, ptr %is_addition.addr, align 1
+    %loadedv = trunc i8 %is_addition_val to i1
+    br i1 %loadedv, label %cond.end, label %cond.false
   
   cond.false:                                       ; preds = %entry
     br label %cond.end
   
-  cond.end:                                         ; preds = %cond.false, %cond.true
-    %cond = phi ptr [ @_Z3addii, %cond.true ], [ @_Z8multiplyii, %cond.false ]
+  cond.end:                                         ; preds = %cond.false, %entry
+    %cond = phi ptr [ @_Z8multiplyii, %cond.false ], [ @_Z3addii, %entry ]
     ret ptr %cond
   }
   
-  ; Function Attrs: mustprogress noinline norecurse optnone uwtable
-  define dso_local noundef i32 @main(i32 noundef %argc) #1 !type !8 !type !8 {
+  define dso_local noundef i32 @main(i32 noundef %argc) !type !2 !type !2 {
   entry:
     %retval = alloca i32, align 4
     %argc.addr = alloca i32, align 4
@@ -68,75 +61,33 @@
     store i32 %argc, ptr %argc.addr, align 4
     store i32 5, ptr %x, align 4
     store i32 10, ptr %y, align 4
-    %0 = load i32, ptr %argc.addr, align 4
-    %rem = srem i32 %0, 2
+    %argc_val = load i32, ptr %argc.addr, align 4
+    %rem = srem i32 %argc_val, 2
     %cmp = icmp eq i32 %rem, 0
     %call = call noundef ptr @_Z13get_operationb(i1 noundef zeroext %cmp) [ "callee_type"(metadata !"_ZTSFPvbE.generalized") ]
     store ptr %call, ptr %op, align 8
-    %1 = load ptr, ptr %op, align 8
-    %2 = load i32, ptr %x, align 4
-    %3 = load i32, ptr %y, align 4
-    %call1 = call noundef i32 %1(i32 noundef %2, i32 noundef %3) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %op_val = load ptr, ptr %op, align 8
+    %x_val = load i32, ptr %x, align 4
+    %y_val = load i32, ptr %y, align 4
+    %call1 = call noundef i32 %op_val(i32 noundef %x_val, i32 noundef %y_val) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
     ret i32 %call1
   }
   
-  !6 = !{i64 0, !"_ZTSFiiiE.generalized"}
-  !7 = !{i64 0, !"_ZTSFPvbE.generalized"}
-  !8 = !{i64 0, !"_ZTSFiiE.generalized"}
+  !0 = !{i64 0, !"_ZTSFiiiE.generalized"}
+  !1 = !{i64 0, !"_ZTSFPvbE.generalized"}
+  !2 = !{i64 0, !"_ZTSFiiE.generalized"}
 
 ...
 ---
 name:            main
-liveins:
-  - { reg: '$edi', virtual-reg: '%0' }
-stack:
-  - { id: 0, name: retval, size: 4 }
-  - { id: 1, name: argc.addr, size: 4 }
-  - { id: 2, name: x, size: 4 }
-  - { id: 3, name: y, size: 4 }
-  - { id: 4, name: op, size: 8 }
 callSites:
-  - { bb: 0, offset: 18, fwdArgRegs: [] }
-  - { bb: 0, offset: 29, fwdArgRegs: [], typeId: 
+  - { bb: 0, offset: 0, fwdArgRegs: [] }
+  - { bb: 0, offset: 2, fwdArgRegs: [], typeId: 
     1234567890 }
 body:             |
   bb.0.entry:
-    liveins: $edi
-  
-    %0:gr32 = COPY $edi
-    %1:gr32 = COPY killed %0
-    MOV32mi %stack.0.retval, 1, $noreg, 0, $noreg, 0 :: (store (s32) into %ir.retval)
-    MOV32mr %stack.1.argc.addr, 1, $noreg, 0, $noreg, %1 :: (store (s32) into %ir.argc.addr)
-    MOV32mi %stack.2.x, 1, $noreg, 0, $noreg, 5 :: (store (s32) into %ir.x)
-    MOV32mi %stack.3.y, 1, $noreg, 0, $noreg, 10 :: (store (s32) into %ir.y)
-    %21:gr32 = MOV32rm %stack.1.argc.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.argc.addr)
-    %19:gr32 = MOV32ri 2
-    $eax = COPY %21
-    CDQ implicit-def $eax, implicit-def $edx, implicit $eax
-    IDIV32r %19, implicit-def $eax, implicit-def $edx, implicit-def $eflags, implicit $eax, implicit $edx
-    %20:gr32 = COPY $edx
-    CMP32ri %20, 0, implicit-def $eflags
-    %15:gr8 = SETCCr 4, implicit $eflags
-    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    %12:gr32 = MOVZX32rr8 %15
-    %13:gr32 = AND32ri %12, 1, implicit-def dead $eflags
-    $edi = COPY %13
-    CALL64pcrel32 @_Z13get_operationb, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
-    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    %14:gr64 = COPY $rax
-    %10:gr64 = COPY %14
-    MOV64mr %stack.4.op, 1, $noreg, 0, $noreg, %10 :: (store (s64) into %ir.op)
-    %9:gr64 = MOV64rm %stack.4.op, 1, $noreg, 0, $noreg :: (load (s64) from %ir.op)
-    %8:gr32 = MOV32rm %stack.2.x, 1, $noreg, 0, $noreg :: (load (s32) from %ir.x)
-    %7:gr32 = MOV32rm %stack.3.y, 1, $noreg, 0, $noreg :: (load (s32) from %ir.y)
-    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    $edi = COPY %8
-    $esi = COPY %7
-    CALL64r %9, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
-    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    %6:gr32 = COPY $eax
-    %2:gr32 = COPY %6
-    $eax = COPY %2
-    RET64 implicit $eax
+    CALL64pcrel32 @_Z13get_operationb, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax    
+    %7:gr64 = COPY $rax    
+    CALL64r %7, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
 
 ...
diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
index 528ddb5908d0d..c94b20138da55 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
@@ -13,133 +13,78 @@
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
 
 --- |  
-  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
-  define dso_local noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y) #0 !type !6 !type !6 {
+  define dso_local noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y) !type !0 !type !0 {
   entry:
     %x.addr = alloca i32, align 4
     %y.addr = alloca i32, align 4
     store i32 %x, ptr %x.addr, align 4
     store i32 %y, ptr %y.addr, align 4
-    %0 = load i32, ptr %x.addr, align 4
-    %1 = load i32, ptr %y.addr, align 4
-    %add = add nsw i32 %0, %1
+    %x_val = load i32, ptr %x.addr, align 4
+    %y_val = load i32, ptr %y.addr, align 4
+    %add = add nsw i32 %x_val, %y_val
     ret i32 %add
   }
   
-  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
-  define dso_local noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y) #0 !type !6 !type !6 {
+  define dso_local noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y) !type !0 !type !0 {
   entry:
     %x.addr = alloca i32, align 4
     %y.addr = alloca i32, align 4
     store i32 %x, ptr %x.addr, align 4
     store i32 %y, ptr %y.addr, align 4
-    %0 = load i32, ptr %x.addr, align 4
-    %1 = load i32, ptr %y.addr, align 4
-    %mul = mul nsw i32 %0, %1
+    %x_val = load i32, ptr %x.addr, align 4
+    %y_val = load i32, ptr %y.addr, align 4
+    %mul = mul nsw i32 %x_val, %y_val
     ret i32 %mul
   }
   
-  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
-  define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) #0 !type !6 !type !6 {
+  define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) !type !0 !type !0 {
   entry:
     %x.addr = alloca i32, align 4
     %y.addr = alloca i32, align 4
     store i32 %x, ptr %x.addr, align 4
     store i32 %y, ptr %y.addr, align 4
-    %0 = load i32, ptr %x.addr, align 4
-    %1 = load i32, ptr %y.addr, align 4
-    %call = call noundef i32 @_Z4buzzii(i32 noundef %0, i32 noundef %1) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
-    %2 = load i32, ptr %x.addr, align 4
-    %3 = load i32, ptr %y.addr, align 4
-    %call1 = call noundef i32 @_Z4fizzii(i32 noundef %2, i32 noundef %3) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %x_val = load i32, ptr %x.addr, align 4
+    %y_val = load i32, ptr %y.addr, align 4
+    %call = call noundef i32 @_Z4buzzii(i32 noundef %x_val, i32 noundef %y_val) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %x_val_2 = load i32, ptr %x.addr, align 4
+    %y_val_2 = load i32, ptr %y.addr, align 4
+    %call1 = call noundef i32 @_Z4fizzii(i32 noundef %x_val_2, i32 noundef %y_val_2) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
     %sub = sub nsw i32 %call, %call1
     ret i32 %sub
   }
   
-  ; Function Attrs: mustprogress noinline nounwind optnone uwtable
-  define dso_local noundef i32 @_Z3fooii(i32 noundef %x, i32 noundef %y) #0 !type !6 !type !6 {
+  define dso_local noundef i32 @_Z3fooii(i32 noundef %x, i32 noundef %y) !type !0 !type !0 {
   entry:
     %x.addr = alloca i32, align 4
     %y.addr = alloca i32, align 4
     store i32 %x, ptr %x.addr, align 4
     store i32 %y, ptr %y.addr, align 4
-    %0 = load i32, ptr %x.addr, align 4
-    %1 = load i32, ptr %y.addr, align 4
-    %call = call noundef i32 @_Z3barii(i32 noundef %0, i32 noundef %1) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %x_val = load i32, ptr %x.addr, align 4
+    %y_val = load i32, ptr %y.addr, align 4
+    %call = call noundef i32 @_Z3barii(i32 noundef %x_val, i32 noundef %y_val) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
     ret i32 %call
-  }  
+  }
   
-  !6 = !{i64 0, !"_ZTSFiiiE.generalized"}
+  !0 = !{i64 0, !"_ZTSFiiiE.generalized"}
 
 ...
 ---
 name:            _Z3barii
-stack:
-  - { id: 0, name: x.addr, size: 4 }
-  - { id: 1, name: y.addr, size: 4 }
 callSites:
-  - { bb: 0, offset: 11, fwdArgRegs: [] }
-  - { bb: 0, offset: 20, fwdArgRegs: [] }
+  - { bb: 0, offset: 0, fwdArgRegs: [] }
+  - { bb: 0, offset: 1, fwdArgRegs: [] }
 body:             |
   bb.0.entry:
-    liveins: $edi, $esi
-  
-    %2:gr32 = COPY $esi
-    %0:gr32 = COPY $edi
-    %1:gr32 = COPY killed %0
-    %3:gr32 = COPY killed %2
-    MOV32mr %stack.0.x.addr, 1, $noreg, 0, $noreg, %1 :: (store (s32) into %ir.x.addr)
-    MOV32mr %stack.1.y.addr, 1, $noreg, 0, $noreg, %3 :: (store (s32) into %ir.y.addr)
-    %17:gr32 = MOV32rm %stack.0.x.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.x.addr)
-    %16:gr32 = MOV32rm %stack.1.y.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.y.addr)
-    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    $edi = COPY %17
-    $esi = COPY %16
-    CALL64pcrel32 @_Z4buzzii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
-    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    %15:gr32 = COPY $eax
-    %5:gr32 = COPY %15
-    %12:gr32 = MOV32rm %stack.0.x.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.x.addr)
-    %11:gr32 = MOV32rm %stack.1.y.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.y.addr)
-    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    $edi = COPY %12
-    $esi = COPY %11
-    CALL64pcrel32 @_Z4fizzii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
-    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    %10:gr32 = COPY $eax
-    %6:gr32 = COPY %10
-    %7:gr32 = SUB32rr %5, %6, implicit-def $eflags
-    $eax = COPY %7
-    RET64 implicit $eax
+    CALL64pcrel32 @_Z4buzzii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax    
+    CALL64pcrel32 @_Z4fizzii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax    
 
 ...
 ---
 name:            _Z3fooii
-stack:
-  - { id: 0, name: x.addr, size: 4 }
-  - { id: 1, name: y.addr, size: 4 }
 callSites:
-  - { bb: 0, offset: 11, fwdArgRegs: [] }
+  - { bb: 0, offset: 0, fwdArgRegs: [] }
 body:             |
   bb.0.entry:
-    liveins: $edi, $esi
-  
-    %2:gr32 = COPY $esi
-    %0:gr32 = COPY $edi
-    %1:gr32 = COPY killed %0
-    %3:gr32 = COPY killed %2
-    MOV32mr %stack.0.x.addr, 1, $noreg, 0, $noreg, %1 :: (store (s32) into %ir.x.addr)
-    MOV32mr %stack.1.y.addr, 1, $noreg, 0, $noreg, %3 :: (store (s32) into %ir.y.addr)
-    %9:gr32 = MOV32rm %stack.0.x.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.x.addr)
-    %8:gr32 = MOV32rm %stack.1.y.addr, 1, $noreg, 0, $noreg :: (load (s32) from %ir.y.addr)
-    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    $edi = COPY %9
-    $esi = COPY %8
     CALL64pcrel32 @_Z3barii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
-    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    %7:gr32 = COPY $eax
-    %4:gr32 = COPY %7
-    $eax = COPY %4
-    RET64 implicit $eax
 
 ...
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 a99ee50a608fb..9342c3a70ed40 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -19,41 +19,20 @@
     %fp = alloca ptr, align 8
     store i32 0, ptr %retval, align 4
     store ptr @foo, ptr %fp, align 8
-    %0 = load ptr, ptr %fp, align 8
-    call void %0(i8 signext 97)
+    %fp_val = load ptr, ptr %fp, align 8
+    call void %fp_val(i8 signext 97)
     ret i32 0
   }
 
-...
----
-name:            foo
-tracksRegLiveness: true
-body:             |
-  bb.0.entry:
-    RET 0
-
 ...
 ---
 name:            main
-tracksRegLiveness: true
-stack:
-  - { id: 0, name: retval, size: 4, alignment: 4 }
-  - { id: 1, name: fp, size: 8, alignment: 8 }
 callSites:
-  - { bb: 0, offset: 6, fwdArgRegs: [], typeId: 
+  - { bb: 0, offset: 1, fwdArgRegs: [], typeId: 
     123456789 }
 body:             |
-  bb.0.entry:
-    MOV32mi %stack.0.retval, 1, $noreg, 0, $noreg, 0 :: (store (s32) into %ir.retval)
-    MOV64mi32 %stack.1.fp, 1, $noreg, 0, $noreg, @foo :: (store (s64) into %ir.fp)
-    %0:gr64 = MOV32ri64 @foo
-    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    %1:gr32 = MOV32ri 97
-    $edi = COPY %1
+  bb.0.entry:    
+    %0:gr64 = MOV32ri64 @foo    
     CALL64r killed %0, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp
-    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
-    %2:gr32 = MOV32r0 implicit-def dead $eflags
-    $eax = COPY %2
-    RET 0, $eax
 
 ...

>From b9434254662ad2b5daad7671af46d6b869c553ae Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 19 Mar 2025 02:53:46 +0000
Subject: [PATCH 12/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/test/Verifier/operand-bundles.ll | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/test/Verifier/operand-bundles.ll b/llvm/test/Verifier/operand-bundles.ll
index 79b5af35b353e..ed6e10f210c75 100644
--- a/llvm/test/Verifier/operand-bundles.ll
+++ b/llvm/test/Verifier/operand-bundles.ll
@@ -108,14 +108,14 @@ declare void @llvm.assume(i1)
 define void @f_type(ptr %ptr) {
 ; CHECK: Multiple "callee_type" operand bundles
 ; CHECK-NEXT: call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized"), "callee_type"(metadata !"_ZTSFvE.generalized") ]
-; CHECK-NOT: call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized") ]
 
  entry:
-  %l = load i32, ptr %ptr, align 4
+  %ptr_val = load i32, ptr %ptr, align 4
   call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized"), "callee_type"(metadata !"_ZTSFvE.generalized") ]
-  call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized") ]
   %x = add i32 42, 1
   ret void
 }
 
 attributes #0 = { noreturn }
+
+; CHECK-NEXT: error: input module is broken!

>From 7f8e4d95ef0c86a3bc0135ec5d247da322969f09 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Sat, 19 Apr 2025 02:15:55 +0000
Subject: [PATCH 13/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/include/llvm/IR/FixedMetadataKinds.def   |  1 +
 llvm/include/llvm/IR/LLVMContext.h            |  1 -
 llvm/include/llvm/IR/Metadata.h               |  2 ++
 llvm/lib/Analysis/MemoryProfileInfo.cpp       | 21 +++++++++++++++++++
 .../SelectionDAG/SelectionDAGBuilder.cpp      | 10 ++++-----
 llvm/lib/IR/LLVMContext.cpp                   |  4 ----
 llvm/lib/IR/Verifier.cpp                      | 12 ++++-------
 llvm/lib/Transforms/Utils/Local.cpp           |  5 +++++
 .../Bitcode/operand-bundles-bc-analyzer.ll    |  5 ++---
 llvm/test/Verifier/operand-bundles.ll         | 13 ------------
 10 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index df572e8791e13..90276eae13e4b 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -53,3 +53,4 @@ LLVM_FIXED_MD_KIND(MD_DIAssignID, "DIAssignID", 38)
 LLVM_FIXED_MD_KIND(MD_coro_outside_frame, "coro.outside.frame", 39)
 LLVM_FIXED_MD_KIND(MD_mmra, "mmra", 40)
 LLVM_FIXED_MD_KIND(MD_noalias_addrspace, "noalias.addrspace", 41)
+LLVM_FIXED_MD_KIND(MD_callee_type, "callee_type", 42)
diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h
index 97ff6b73f4473..bbd125fd38cf1 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -96,7 +96,6 @@ class LLVMContext {
     OB_ptrauth = 7,                // "ptrauth"
     OB_kcfi = 8,                   // "kcfi"
     OB_convergencectrl = 9,        // "convergencectrl"
-    OB_callee_type = 10,           // "callee_type"
   };
 
   /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index ec7d030a20de8..43a3ba20589dd 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -1470,6 +1470,8 @@ class MDNode : public Metadata {
                                        const Instruction *BInstr);
   static MDNode *getMergedMemProfMetadata(MDNode *A, MDNode *B);
   static MDNode *getMergedCallsiteMetadata(MDNode *A, MDNode *B);
+  static MDNode *getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
+                                             MDNode *B);
 };
 
 /// Tuple of metadata.
diff --git a/llvm/lib/Analysis/MemoryProfileInfo.cpp b/llvm/lib/Analysis/MemoryProfileInfo.cpp
index a22344e19d045..94ddd96226fc5 100644
--- a/llvm/lib/Analysis/MemoryProfileInfo.cpp
+++ b/llvm/lib/Analysis/MemoryProfileInfo.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/MemoryProfileInfo.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/Support/CommandLine.h"
 
@@ -435,3 +436,23 @@ MDNode *MDNode::getMergedCallsiteMetadata(MDNode *A, MDNode *B) {
     return A;
   return B;
 }
+
+MDNode *MDNode::getMergedCalleeTypeMetadata([[maybe_unused]] LLVMContext &Ctx,
+                                            MDNode *A, MDNode *B) {
+  SmallVector<Metadata *, 8> AB;
+  SmallSet<Metadata *, 8> MergedCallees;
+  auto AddUniqueCallees = [&](llvm::MDNode *N) {
+    if (!N)
+      return;
+    for (const MDOperand &Op : N->operands()) {
+      Metadata *MD = Op.get();
+      if (!MergedCallees.contains(MD)) {
+        MergedCallees.insert(MD);
+        AB.push_back(MD);
+      }
+    }
+  };
+  AddUniqueCallees(A);
+  AddUniqueCallees(B);
+  return llvm::MDNode::get(Ctx, AB);
+}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 52b088e7ec12b..5a5596a542f72 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3332,8 +3332,7 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
              {LLVMContext::OB_deopt, LLVMContext::OB_gc_transition,
               LLVMContext::OB_gc_live, LLVMContext::OB_funclet,
               LLVMContext::OB_cfguardtarget, LLVMContext::OB_ptrauth,
-              LLVMContext::OB_clang_arc_attachedcall,
-              LLVMContext::OB_callee_type}) &&
+              LLVMContext::OB_clang_arc_attachedcall}) &&
          "Cannot lower invokes with arbitrary operand bundles yet!");
 
   const Value *Callee(I.getCalledOperand());
@@ -3422,9 +3421,8 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
 
   // Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't
   // have to do anything here to lower funclet bundles.
-  assert(!I.hasOperandBundlesOtherThan({LLVMContext::OB_deopt,
-                                        LLVMContext::OB_funclet,
-                                        LLVMContext::OB_callee_type}) &&
+  assert(!I.hasOperandBundlesOtherThan(
+             {LLVMContext::OB_deopt, LLVMContext::OB_funclet}) &&
          "Cannot lower callbrs with arbitrary operand bundles yet!");
 
   assert(I.isInlineAsm() && "Only know how to handle inlineasm callbr");
@@ -9609,7 +9607,7 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
              {LLVMContext::OB_deopt, LLVMContext::OB_funclet,
               LLVMContext::OB_cfguardtarget, LLVMContext::OB_preallocated,
               LLVMContext::OB_clang_arc_attachedcall, LLVMContext::OB_kcfi,
-              LLVMContext::OB_convergencectrl, LLVMContext::OB_callee_type}) &&
+              LLVMContext::OB_convergencectrl}) &&
          "Cannot lower calls with arbitrary operand bundles!");
 
   SDValue Callee = getValue(I.getCalledOperand());
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 18e95978bd9f6..447e5d92e0b99 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -82,10 +82,6 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
     assert(Entry->second == BundleTagID && "operand bundle id drifted!");
   }
 
-  [[maybe_unused]] auto *TypeEntry = pImpl->getOrInsertBundleTag("callee_type");
-  assert(TypeEntry->second == LLVMContext::OB_callee_type &&
-         "callee_type operand bundle id drifted!");
-
   SyncScope::ID SingleThreadSSID =
       pImpl->getOrInsertSyncScopeID("singlethread");
   assert(SingleThreadSSID == SyncScope::SingleThread &&
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 34c751e6357c6..8432779c107de 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3721,14 +3721,14 @@ void Verifier::visitCallBase(CallBase &Call) {
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
       visitIntrinsicCall(ID, Call);
 
-  // Verify that a callsite has at most one operand bundle for each of the
-  // following: "deopt", "funclet", "gc-transition", "cfguardtarget",
-  // "callee_type", "preallocated", and "ptrauth".
+  // Verify that a callsite has at most one "deopt", at most one "funclet", at
+  // most one "gc-transition", at most one "cfguardtarget", at most one
+  // "preallocated" operand bundle, and at most one "ptrauth" operand bundle.
   bool FoundDeoptBundle = false, FoundFuncletBundle = false,
        FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false,
        FoundPreallocatedBundle = false, FoundGCLiveBundle = false,
        FoundPtrauthBundle = false, FoundKCFIBundle = false,
-       FoundAttachedCallBundle = false, FoundCalleeTypeBundle = false;
+       FoundAttachedCallBundle = false;
   for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) {
     OperandBundleUse BU = Call.getOperandBundleAt(i);
     uint32_t Tag = BU.getTagID();
@@ -3791,10 +3791,6 @@ void Verifier::visitCallBase(CallBase &Call) {
             "Multiple \"clang.arc.attachedcall\" operand bundles", Call);
       FoundAttachedCallBundle = true;
       verifyAttachedCallBundle(Call, BU);
-    } else if (Tag == LLVMContext::OB_callee_type) {
-      Check(!FoundCalleeTypeBundle, "Multiple \"callee_type\" operand bundles",
-            Call);
-      FoundCalleeTypeBundle = true;
     }
   }
 
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 2c6328300738f..4f08c4b703574 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3388,6 +3388,11 @@ static void combineMetadata(Instruction *K, const Instruction *J,
         if (!AAOnly)
           K->setMetadata(Kind, MDNode::getMergedCallsiteMetadata(KMD, JMD));
         break;
+      case LLVMContext::MD_callee_type:
+        if (!AAOnly)
+          K->setMetadata(Kind, MDNode::getMergedCalleeTypeMetadata(
+                                   K->getContext(), KMD, JMD));
+        break;
       case LLVMContext::MD_preserve_access_index:
         // Preserve !preserve.access.index in K.
         break;
diff --git a/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll b/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll
index ca3f3a929194a..d860104b9cb3d 100644
--- a/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll
+++ b/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll
@@ -13,7 +13,6 @@
 ; CHECK-NEXT:    <OPERAND_BUNDLE_TAG
 ; CHECK-NEXT:    <OPERAND_BUNDLE_TAG
 ; CHECK-NEXT:    <OPERAND_BUNDLE_TAG
-; CHECK-NEXT:    <OPERAND_BUNDLE_TAG
 ; CHECK-NEXT:  </OPERAND_BUNDLE_TAGS_BLOCK
 
 ; CHECK:   <FUNCTION_BLOCK
@@ -26,9 +25,9 @@
 
 declare void @callee0()
 
-define void @f0(ptr %ptr) {
+define void @f0(i32* %ptr) {
  entry:
-  %l = load i32, ptr %ptr
+  %l = load i32, i32* %ptr
   %x = add i32 42, 1
   call void @callee0() [ "foo"(i32 42, i64 100, i32 %x), "bar"(float  0.000000e+00, i64 100, i32 %l) ]
   ret void
diff --git a/llvm/test/Verifier/operand-bundles.ll b/llvm/test/Verifier/operand-bundles.ll
index ed6e10f210c75..db85b6ae6ef5f 100644
--- a/llvm/test/Verifier/operand-bundles.ll
+++ b/llvm/test/Verifier/operand-bundles.ll
@@ -105,17 +105,4 @@ declare ptr @objc_retainAutoreleasedReturnValue(ptr)
 declare ptr @objc_unsafeClaimAutoreleasedReturnValue(ptr)
 declare void @llvm.assume(i1)
 
-define void @f_type(ptr %ptr) {
-; CHECK: Multiple "callee_type" operand bundles
-; CHECK-NEXT: call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized"), "callee_type"(metadata !"_ZTSFvE.generalized") ]
-
- entry:
-  %ptr_val = load i32, ptr %ptr, align 4
-  call void @g() [ "callee_type"(metadata !"_ZTSFvE.generalized"), "callee_type"(metadata !"_ZTSFvE.generalized") ]
-  %x = add i32 42, 1
-  ret void
-}
-
 attributes #0 = { noreturn }
-
-; CHECK-NEXT: error: input module is broken!

>From 533454f0572be158dd598316939ebe8c5219ea3a Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 23 Apr 2025 01:01:50 +0000
Subject: [PATCH 14/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 .../InstCombine/InstCombineCalls.cpp          |  5 ++++
 .../InstCombine/callee-type-metadata.ll       | 25 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/callee-type-metadata.ll

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 400ebcf493713..66e9dc1684969 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -4111,6 +4111,11 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
             Call, Builder.CreateBitOrPointerCast(ReturnedArg, CallTy));
     }
 
+  // Drop unnecessary callee_type metadata from calls that were converted
+  // into direct calls.
+  if (Call.getMetadata(LLVMContext::MD_callee_type) && !Call.isIndirectCall())
+    Call.setMetadata(LLVMContext::MD_callee_type, nullptr);
+
   // Drop unnecessary kcfi operand bundles from calls that were converted
   // into direct calls.
   auto Bundle = Call.getOperandBundle(LLVMContext::OB_kcfi);
diff --git a/llvm/test/Transforms/InstCombine/callee-type-metadata.ll b/llvm/test/Transforms/InstCombine/callee-type-metadata.ll
new file mode 100644
index 0000000000000..5c86e95ae3f4c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/callee-type-metadata.ll
@@ -0,0 +1,25 @@
+;; Test if the callee_type metadata is dropped when an indirect function call through a function ptr is promoted
+;; to a direct function call during instcombine.
+
+; RUN: opt < %s -O2 | llvm-dis | FileCheck %s
+
+define dso_local noundef i32 @_Z13call_indirectPFicEc(ptr noundef %func, i8 noundef signext %x) local_unnamed_addr !type !0 {
+entry:
+  %call = call noundef i32 %func(i8 noundef signext %x), !callee_type !1
+  ret i32 %call
+}
+
+define dso_local noundef i32 @_Z3barv() local_unnamed_addr !type !3 {
+entry:
+  ; CHECK: %call.i = tail call noundef i32 @_Z3fooc(i8 noundef signext 97)
+  ; CHECK-NOT: %call.i = tail call noundef i32 @_Z3fooc(i8 noundef signext 97), !callee_type !1
+  %call = call noundef i32 @_Z13call_indirectPFicEc(ptr noundef nonnull @_Z3fooc, i8 noundef signext 97)
+  ret i32 %call
+}
+
+declare !type !2 noundef i32 @_Z3fooc(i8 noundef signext)
+
+!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFivE.generalized"}

>From 8c7b1ab4fa0040543dca7fc62951440b866a82fb Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 23 Apr 2025 03:52:10 +0000
Subject: [PATCH 15/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/include/llvm/IR/Metadata.h |  6 ++++++
 llvm/lib/IR/Verifier.cpp        | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index 43a3ba20589dd..02403dd5c752b 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -1259,6 +1259,12 @@ class MDNode : public Metadata {
   bool isReplaceable() const { return isTemporary() || isAlwaysReplaceable(); }
   bool isAlwaysReplaceable() const { return getMetadataID() == DIAssignIDKind; }
 
+  bool hasGeneralizedMDString() const {
+    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/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 8432779c107de..07de968b5dbfe 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -530,6 +530,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
   void visitCallStackMetadata(MDNode *MD);
   void visitMemProfMetadata(Instruction &I, MDNode *MD);
   void visitCallsiteMetadata(Instruction &I, MDNode *MD);
+  void visitCalleeTypeMetadata(Instruction &I, MDNode *MD);
   void visitDIAssignIDMetadata(Instruction &I, MDNode *MD);
   void visitMMRAMetadata(Instruction &I, MDNode *MD);
   void visitAnnotationMetadata(MDNode *Annotation);
@@ -5050,6 +5051,20 @@ void Verifier::visitCallsiteMetadata(Instruction &I, MDNode *MD) {
   visitCallStackMetadata(MD);
 }
 
+void Verifier::visitCalleeTypeMetadata(Instruction &I, MDNode *MD) {
+  Check(isa<CallBase>(I), "!callee_type metadata should only exist on calls",
+        &I);
+  CallBase *CB = cast<CallBase>(&I);
+  Check(CB->isIndirectCall(),
+        "!callee_type metadata should only exist on indirect function calls",
+        &I);
+  for (const auto &Op : MD->operands()) {
+    auto *TypeMD = cast<MDNode>(Op.get());
+    Check(TypeMD->hasGeneralizedMDString(),
+          "Invalid \"callee_type\" type identifier", &I);
+  }
+}
+
 void Verifier::visitAnnotationMetadata(MDNode *Annotation) {
   Check(isa<MDTuple>(Annotation), "annotation must be a tuple");
   Check(Annotation->getNumOperands() >= 1,
@@ -5325,6 +5340,9 @@ void Verifier::visitInstruction(Instruction &I) {
   if (MDNode *MD = I.getMetadata(LLVMContext::MD_callsite))
     visitCallsiteMetadata(I, MD);
 
+  if (MDNode *MD = I.getMetadata(LLVMContext::MD_callee_type))
+    visitCalleeTypeMetadata(I, MD);
+
   if (MDNode *MD = I.getMetadata(LLVMContext::MD_DIAssignID))
     visitDIAssignIDMetadata(I, MD);
 

>From c1f37fc0add6a2b46d6a54b4c8470d7ff624dfff Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 23 Apr 2025 23:38:40 +0000
Subject: [PATCH 16/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 .../InstCombine/callee-type-metadata.ll          | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/callee-type-metadata.ll b/llvm/test/Transforms/InstCombine/callee-type-metadata.ll
index 5c86e95ae3f4c..8cf99432c00b7 100644
--- a/llvm/test/Transforms/InstCombine/callee-type-metadata.ll
+++ b/llvm/test/Transforms/InstCombine/callee-type-metadata.ll
@@ -1,23 +1,23 @@
 ;; Test if the callee_type metadata is dropped when an indirect function call through a function ptr is promoted
 ;; to a direct function call during instcombine.
 
-; RUN: opt < %s -O2 | llvm-dis | FileCheck %s
+; RUN: opt < %s -passes="cgscc(inline),instcombine" -S | FileCheck %s
 
-define dso_local noundef i32 @_Z13call_indirectPFicEc(ptr noundef %func, i8 noundef signext %x) local_unnamed_addr !type !0 {
+define i32 @_Z13call_indirectPFicEc(ptr %func, i8 %x) local_unnamed_addr !type !0 {
 entry:
-  %call = call noundef i32 %func(i8 noundef signext %x), !callee_type !1
+  %call = call i32 %func(i8 %x), !callee_type !1
   ret i32 %call
 }
 
-define dso_local noundef i32 @_Z3barv() local_unnamed_addr !type !3 {
+define i32 @_Z3barv() local_unnamed_addr !type !3 {
 entry:
-  ; CHECK: %call.i = tail call noundef i32 @_Z3fooc(i8 noundef signext 97)
-  ; CHECK-NOT: %call.i = tail call noundef i32 @_Z3fooc(i8 noundef signext 97), !callee_type !1
-  %call = call noundef i32 @_Z13call_indirectPFicEc(ptr noundef nonnull @_Z3fooc, i8 noundef signext 97)
+  ; CHECK: %call.i = call i32 @_Z3fooc(i8 97)
+  ; CHECK-NOT: %call.i = call i32 @_Z3fooc(i8 97), !callee_type !1
+  %call = call i32 @_Z13call_indirectPFicEc(ptr nonnull @_Z3fooc, i8 97)
   ret i32 %call
 }
 
-declare !type !2 noundef i32 @_Z3fooc(i8 noundef signext)
+declare !type !2 i32 @_Z3fooc(i8 signext)
 
 !0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
 !1 = !{!2}

>From d4b6ae070c95cc4a2dce122c82af18f8d3174bb2 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 24 Apr 2025 02:24:46 +0000
Subject: [PATCH 17/33] Address review comments.

Created using spr 1.3.6-beta.1
---
 llvm/lib/CodeGen/MIRPrinter.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index ef0a4ccccd4cd..e9fe4ab09c9bd 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -558,26 +558,29 @@ void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF,
                                         const MachineFunction &MF,
                                         ModuleSlotTracker &MST) {
   const auto *TRI = MF.getSubtarget().getRegisterInfo();
-  for (auto CSInfo : MF.getCallSitesInfo()) {
+  for (auto CSInfoMap : MF.getCallSitesInfo()) {
     yaml::CallSiteInfo YmlCS;
     yaml::MachineInstrLoc CallLocation;
 
     // Prepare instruction position.
-    MachineBasicBlock::const_instr_iterator CallI = CSInfo.first->getIterator();
+    MachineBasicBlock::const_instr_iterator CallI =
+        CSInfoMap.first->getIterator();
     CallLocation.BlockNum = CallI->getParent()->getNumber();
     // Get call instruction offset from the beginning of block.
     CallLocation.Offset =
         std::distance(CallI->getParent()->instr_begin(), CallI);
     YmlCS.CallLocation = CallLocation;
+
+    auto [ArgRegPairs, CalleeTypeIds] = CSInfoMap.second;
     // Construct call arguments and theirs forwarding register info.
-    for (auto ArgReg : CSInfo.second.ArgRegPairs) {
+    for (auto ArgReg : ArgRegPairs) {
       yaml::CallSiteInfo::ArgRegPair YmlArgReg;
       YmlArgReg.ArgNo = ArgReg.ArgNo;
       printRegMIR(ArgReg.Reg, YmlArgReg.Reg, TRI);
       YmlCS.ArgForwardingRegs.emplace_back(YmlArgReg);
     }
     // Get type ids.
-    for (auto *CalleeTypeId : CSInfo.second.CalleeTypeIds) {
+    for (auto *CalleeTypeId : CalleeTypeIds) {
       YmlCS.CalleeTypeIds.push_back(CalleeTypeId->getZExtValue());
     }
     YMF.CallSitesInfo.push_back(std::move(YmlCS));

>From 9f94841f38015166161444327ddbaeb810366f48 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 24 Apr 2025 20:39:29 +0000
Subject: [PATCH 18/33] Fix the test file formatting for calleeTypeIds.

Created using spr 1.3.6-beta.1
---
 .../MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir  | 3 +--
 llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir            | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

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 a7073cb1ca5f0..1a9477640f8f3 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
@@ -49,8 +49,7 @@
 name:            main
 callSites:
   - { bb: 0, offset: 0, fwdArgRegs: [] }
-  - { bb: 0, offset: 2, fwdArgRegs: [], calleeTypeIds: 
-    [ 1234567890 ] }
+  - { bb: 0, offset: 2, fwdArgRegs: [], calleeTypeIds: [ 1234567890 ] }
 body:             |
   bb.0.entry:
     CALL64pcrel32 @_Z13get_operationb, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax    
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 e2f212e52d176..c44a4df439609 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -25,8 +25,7 @@
 ---
 name:            main
 callSites:
-  - { bb: 0, offset: 1, fwdArgRegs: [], calleeTypeIds: 
-    [ 123456789 ] }
+  - { bb: 0, offset: 1, fwdArgRegs: [], calleeTypeIds: [ 123456789 ] }
 body:             |
   bb.0.entry:    
     %0:gr64 = MOV32ri64 @foo    

>From fb9326112115e82dab4bfa5aec530df231e52d7d Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 24 Apr 2025 23:50:17 +0000
Subject: [PATCH 19/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/lib/IR/Verifier.cpp                   |  5 +++-
 llvm/test/Verifier/callee-type-metadata.ll | 28 ++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Verifier/callee-type-metadata.ll

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 07de968b5dbfe..51da2d62ba160 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5059,9 +5059,12 @@ void Verifier::visitCalleeTypeMetadata(Instruction &I, MDNode *MD) {
         "!callee_type metadata should only exist on indirect function calls",
         &I);
   for (const auto &Op : MD->operands()) {
+    Check(isa<MDNode>(Op.get()),
+          "The callee_type metadata must be a list of type metadata nodes");
     auto *TypeMD = cast<MDNode>(Op.get());
     Check(TypeMD->hasGeneralizedMDString(),
-          "Invalid \"callee_type\" type identifier", &I);
+          "Only generalized type metadata can be part of the callee_type "
+          "metadata list");
   }
 }
 
diff --git a/llvm/test/Verifier/callee-type-metadata.ll b/llvm/test/Verifier/callee-type-metadata.ll
new file mode 100644
index 0000000000000..6382a87758fe1
--- /dev/null
+++ b/llvm/test/Verifier/callee-type-metadata.ll
@@ -0,0 +1,28 @@
+;; Test if the callee_type metadata attached to indirect call sites adhere to the expected format.
+
+; RUN: not opt -passes=verify < %s 2>&1 | FileCheck %s
+define i32 @_Z13call_indirectPFicEc(ptr %func, i8 signext %x) !type !0 {
+entry:
+  %func.addr = alloca ptr, align 8
+  %x.addr = alloca i8, align 1
+  store ptr %func, ptr %func.addr, align 8
+  store i8 %x, ptr %x.addr, align 1
+  %fptr = load ptr, ptr %func.addr, align 8
+  %fptr_val = load i8, ptr %x.addr, align 1
+  ;; No failures expected for this callee_type metdata.
+  %call = call i32 %fptr(i8 signext %fptr_val), !callee_type !1
+  ;; callee_type metdata is a type metadata instead of a list of type metadata nodes.
+  ; CHECK: The callee_type metadata must be a list of type metadata nodes
+  %call2 = call i32 %fptr(i8 signext %fptr_val), !callee_type !0
+  ;; callee_type metdata is a list of non "gneralized" type metadata.  
+  ; CHECK: Only generalized type metadata can be part of the callee_type metadata list
+  %call3 = call i32 %fptr(i8 signext %fptr_val), !callee_type !4
+  ret i32 %call
+}
+
+!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFicE"}
+!4 = !{!3}
+; CHECK-NEXT: error: input module is broken!

>From 84e71ce996ef901527dcae821b775a47172b0d85 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Mon, 28 Apr 2025 22:48:36 +0000
Subject: [PATCH 20/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/lib/Transforms/Utils/ValueMapper.cpp     |  7 +++++++
 .../drop-callee-type-metadata.ll}             |  7 +++----
 .../InstCombine/drop-callee-type-metadata.ll  | 19 +++++++++++++++++++
 3 files changed, 29 insertions(+), 4 deletions(-)
 rename llvm/test/Transforms/{InstCombine/callee-type-metadata.ll => Inline/drop-callee-type-metadata.ll} (71%)
 create mode 100644 llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll

diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp
index b8569454379bf..7906e0d2ae3fc 100644
--- a/llvm/lib/Transforms/Utils/ValueMapper.cpp
+++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp
@@ -985,6 +985,13 @@ void Mapper::remapInstruction(Instruction *I) {
              "Referenced value not in value map!");
   }
 
+  // Drop callee_type metadata from calls that were remapped
+  // into a direct call from an indirect one.
+  if (auto *CB = dyn_cast<CallBase>(I)) {
+    if (CB->getMetadata(LLVMContext::MD_callee_type) && !CB->isIndirectCall())
+      CB->setMetadata(LLVMContext::MD_callee_type, nullptr);
+  }
+
   // Remap phi nodes' incoming blocks.
   if (PHINode *PN = dyn_cast<PHINode>(I)) {
     for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
diff --git a/llvm/test/Transforms/InstCombine/callee-type-metadata.ll b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
similarity index 71%
rename from llvm/test/Transforms/InstCombine/callee-type-metadata.ll
rename to llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
index 8cf99432c00b7..84463bd3948b3 100644
--- a/llvm/test/Transforms/InstCombine/callee-type-metadata.ll
+++ b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
@@ -1,7 +1,7 @@
-;; Test if the callee_type metadata is dropped when an indirect function call through a function ptr is promoted
-;; to a direct function call during instcombine.
+;; Test if the callee_type metadata is dropped when it is
+;; is mapped to a direct function call from an indirect call during inlining.
 
-; RUN: opt < %s -passes="cgscc(inline),instcombine" -S | FileCheck %s
+; RUN: opt < %s -passes="inline" -S | FileCheck %s
 
 define i32 @_Z13call_indirectPFicEc(ptr %func, i8 %x) local_unnamed_addr !type !0 {
 entry:
@@ -16,7 +16,6 @@ entry:
   %call = call i32 @_Z13call_indirectPFicEc(ptr nonnull @_Z3fooc, i8 97)
   ret i32 %call
 }
-
 declare !type !2 i32 @_Z3fooc(i8 signext)
 
 !0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
diff --git a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
new file mode 100644
index 0000000000000..0231343fb56b2
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
@@ -0,0 +1,19 @@
+;; Test if the callee_type metadata is dropped when it is attached
+;; to a direct function call during instcombine.
+
+; RUN: opt < %s -passes="instcombine" -disable-verify -S | FileCheck %s
+
+define i32 @_Z3barv() local_unnamed_addr !type !3 {
+entry:
+  ; CHECK: %call = call i32 @_Z3fooc(i8 97)
+  ; CHECK-NOT: %call = call i32 @_Z3fooc(i8 97), !callee_type !1
+  %call = call i32 @_Z3fooc(i8 97), !callee_type !1
+  ret i32 %call
+}
+
+declare !type !2 i32 @_Z3fooc(i8 signext)
+
+!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFivE.generalized"}

>From 79791a293d9daec5ef5efa17244be4271d3d2d66 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Mon, 5 May 2025 23:12:54 +0000
Subject: [PATCH 21/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/lib/IR/Metadata.cpp                                  | 6 ++----
 llvm/lib/IR/Verifier.cpp                                  | 6 +-----
 llvm/test/Transforms/Inline/drop-callee-type-metadata.ll  | 2 +-
 .../Transforms/InstCombine/drop-callee-type-metadata.ll   | 2 +-
 llvm/test/Verifier/callee-type-metadata.ll                | 8 +-------
 5 files changed, 6 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 2ab6fcd2d0759..82c1b96f5fb7e 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1306,15 +1306,13 @@ MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
                                             MDNode *B) {
   SmallVector<Metadata *, 8> AB;
   SmallSet<Metadata *, 8> MergedCallees;
-  auto AddUniqueCallees = [&](llvm::MDNode *N) {
+  auto AddUniqueCallees = [&AB, &MergedCallees](llvm::MDNode *N) {
     if (!N)
       return;
     for (const MDOperand &Op : N->operands()) {
       Metadata *MD = Op.get();
-      if (!MergedCallees.contains(MD)) {
-        MergedCallees.insert(MD);
+      if (MergedCallees.insert(MD).second)
         AB.push_back(MD);
-      }
     }
   };
   AddUniqueCallees(A);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 914ecc00aa862..9d8ab4742e1b6 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5100,11 +5100,7 @@ void Verifier::visitCallsiteMetadata(Instruction &I, MDNode *MD) {
 void Verifier::visitCalleeTypeMetadata(Instruction &I, MDNode *MD) {
   Check(isa<CallBase>(I), "!callee_type metadata should only exist on calls",
         &I);
-  CallBase *CB = cast<CallBase>(&I);
-  Check(CB->isIndirectCall(),
-        "!callee_type metadata should only exist on indirect function calls",
-        &I);
-  for (const auto &Op : MD->operands()) {
+  for (const MDOperand &Op : MD->operands()) {
     Check(isa<MDNode>(Op.get()),
           "The callee_type metadata must be a list of type metadata nodes");
     auto *TypeMD = cast<MDNode>(Op.get());
diff --git a/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
index c8457aa81970d..ce7830536c200 100644
--- a/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
+++ b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
@@ -1,7 +1,7 @@
 ;; Test if the callee_type metadata is dropped when it is
 ;; is mapped to a direct function call from an indirect call during inlining.
 
-; RUN: opt < %s -passes="inline" -disable-verify -S | FileCheck %s
+; RUN: opt -passes="inline" -S < %s | FileCheck %s
 
 define i32 @_Z13call_indirectPFicEc(ptr %func, i8 %x) local_unnamed_addr !type !0 {
 entry:
diff --git a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
index b2bd9350d0749..13c60f675d66d 100644
--- a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
+++ b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
@@ -1,7 +1,7 @@
 ;; Test if the callee_type metadata is dropped when it is attached
 ;; to a direct function call during instcombine.
 
-; RUN: opt < %s -passes="instcombine" -disable-verify -S | FileCheck %s
+; RUN: opt -passes="instcombine" -S < %s | FileCheck %s
 
 define i32 @_Z3barv() local_unnamed_addr !type !3 {
 entry:
diff --git a/llvm/test/Verifier/callee-type-metadata.ll b/llvm/test/Verifier/callee-type-metadata.ll
index 0345da9a64145..0107dec27de34 100644
--- a/llvm/test/Verifier/callee-type-metadata.ll
+++ b/llvm/test/Verifier/callee-type-metadata.ll
@@ -14,15 +14,9 @@ entry:
   ;; callee_type metdata is a type metadata instead of a list of type metadata nodes.
   ; CHECK: The callee_type metadata must be a list of type metadata nodes
   %call2 = call i32 %fptr(i8 signext %x_val), !callee_type !0
-  ;; callee_type metdata is a list of non "gneralized" type metadata.  
+  ;; callee_type metdata must be a list of "generalized" type metadata.
   ; CHECK: Only generalized type metadata can be part of the callee_type metadata list
   %call3 = call i32 %fptr(i8 signext %x_val), !callee_type !4
-  ;; callee_type metadata should not be part of a direct call.
-  ; CHECK: !callee_type metadata should only exist on indirect function calls
-  %call_direct = call i32 @_Z3barc(i8 signext %x_val), !callee_type !1
-  ;; callee_type metadata should not be part of a direct call.
-  ; CHECK: !callee_type metadata should only exist on indirect function calls
-  %call_direct_wrong_signature = call i32 @_Z3barc(i8 signext %x_val), !callee_type !4
   ret i32 %call
 }
 

>From 9bb885a6d7991c88eed1ac5d990d36a290a24362 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Sat, 10 May 2025 00:32:56 +0000
Subject: [PATCH 22/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/docs/CalleeTypeMetadata.rst | 32 ++++++++++++++++++++++++++++++++
 llvm/docs/LangRef.rst            |  5 +++++
 llvm/docs/Reference.rst          |  1 +
 3 files changed, 38 insertions(+)
 create mode 100644 llvm/docs/CalleeTypeMetadata.rst

diff --git a/llvm/docs/CalleeTypeMetadata.rst b/llvm/docs/CalleeTypeMetadata.rst
new file mode 100644
index 0000000000000..8c35dec125f0c
--- /dev/null
+++ b/llvm/docs/CalleeTypeMetadata.rst
@@ -0,0 +1,32 @@
+====================
+Callee Type Metadata
+====================
+
+Introduction
+============
+This ``!callee_type`` metadata is introduced as part of an ongoing effort to generate a call graph
+section in the object file. The broader design for the call graph section and the compiler flags which
+will enable the feature will be documented as those changes land. The ``!callee_type`` metadata is used
+to identify types of intended callees of indirect call instructions. The ``!callee_type`` metadata is a
+list of one or more ``!type`` metadata objects (See :doc:`TypeMetadata`) with each ``!type`` metadata
+pointing to a callee's :ref:`type identifier
+<calleetype-type-identifier>`.
+
+.. _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 c8cc38c23cff3..9feca0e84d671 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8091,6 +8091,11 @@ change in the future.
 
 See :doc:`TypeMetadata`.
 
+'``callee_type``' Metadata
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+See :doc:`CalleeTypeMetadata`.
+
 '``associated``' Metadata
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/llvm/docs/Reference.rst b/llvm/docs/Reference.rst
index e1f46b00f2b30..b67ec2332edb0 100644
--- a/llvm/docs/Reference.rst
+++ b/llvm/docs/Reference.rst
@@ -14,6 +14,7 @@ LLVM and API reference documentation.
    BlockFrequencyTerminology
    BranchWeightMetadata
    Bugpoint
+   CalleeTypeMetadata
    CIBestPractices
    CommandGuide/index
    ConvergenceAndUniformity

>From 39c3c6250220626f9a3f901e2826ba61686cf634 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 13 May 2025 17:24:41 +0000
Subject: [PATCH 23/33] Remove dso_local and noundef from tests.

Created using spr 1.3.6-beta.1
---
 llvm/lib/CodeGen/MIRParser/MIRParser.cpp           |  2 +-
 ...ll-site-info-ambiguous-indirect-call-typeid.mir | 12 ++++++------
 .../MIR/X86/call-site-info-direct-calls-typeid.mir | 14 +++++++-------
 .../test/CodeGen/MIR/X86/call-site-info-typeid.mir |  2 +-
 4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index b3d298d9a2894..83be215b98dc2 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -518,7 +518,7 @@ bool MIRParserImpl::initializeCallSiteInfo(
 
   if (!YamlMF.CallSitesInfo.empty() &&
       !(TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection))
-    return error(Twine("call site info provided but not used"));
+    return error("call site info provided but not used");
   return false;
 }
 
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 1a9477640f8f3..0ce3f27b2a4a8 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
@@ -10,13 +10,13 @@
 
 --- |  
   
-  declare !type !0 noundef i32 @_Z3addii(i32 noundef, i32 noundef)
+  declare !type !0 i32 @_Z3addii(i32, i32)
 
-  declare !type !0 noundef i32 @_Z8multiplyii(i32 noundef, i32 noundef)
+  declare !type !0 i32 @_Z8multiplyii(i32, i32)
   
-  declare !type !1 noundef ptr @_Z13get_operationb(i1 noundef zeroext %is_addition)
+  declare !type !1 ptr @_Z13get_operationb(i1 zeroext %is_addition)
   
-  define dso_local noundef i32 @main(i32 noundef %argc) !type !2 {
+  define i32 @main(i32 %argc) !type !2 {
   entry:
     %retval = alloca i32, align 4
     %argc.addr = alloca i32, align 4
@@ -30,12 +30,12 @@
     %argc_val = load i32, ptr %argc.addr, align 4
     %rem = srem i32 %argc_val, 2
     %cmp = icmp eq i32 %rem, 0
-    %call = call noundef ptr @_Z13get_operationb(i1 noundef zeroext %cmp)
+    %call = call ptr @_Z13get_operationb(i1 zeroext %cmp)
     store ptr %call, ptr %op, align 8
     %op_val = load ptr, ptr %op, align 8
     %x_val = load i32, ptr %x, align 4
     %y_val = load i32, ptr %y, align 4
-    %call1 = call noundef i32 %op_val(i32 noundef %x_val, i32 noundef %y_val), !callee_type !3
+    %call1 = call i32 %op_val(i32 %x_val, i32 %y_val), !callee_type !3
     ret i32 %call1
   }
   
diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
index 4c1007da3095d..17c459d868a8f 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
@@ -13,11 +13,11 @@
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
 
 --- |  
-  declare !type !0 noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y)
+  declare !type !0 i32 @_Z4fizzii(i32 %x, i32 %y)
 
-  declare !type !0 noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y)
+  declare !type !0 i32 @_Z4buzzii(i32 %x, i32 %y)
 
-  define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) !type !0 {
+  define i32 @_Z3barii(i32 %x, i32 %y) !type !0 {
   entry:
     %x.addr = alloca i32, align 4
     %y.addr = alloca i32, align 4
@@ -25,15 +25,15 @@
     store i32 %y, ptr %y.addr, align 4
     %x_val = load i32, ptr %x.addr, align 4
     %y_val = load i32, ptr %y.addr, align 4
-    %call = call noundef i32 @_Z4buzzii(i32 noundef %x_val, i32 noundef %y_val)
+    %call = call i32 @_Z4buzzii(i32 %x_val, i32 %y_val)
     %x_val_2 = load i32, ptr %x.addr, align 4
     %y_val_2 = load i32, ptr %y.addr, align 4
-    %call1 = call noundef i32 @_Z4fizzii(i32 noundef %x_val_2, i32 noundef %y_val_2)
+    %call1 = call i32 @_Z4fizzii(i32 %x_val_2, i32 %y_val_2)
     %sub = sub nsw i32 %call, %call1
     ret i32 %sub
   }
   
-  define dso_local noundef i32 @_Z3fooii(i32 noundef %x, i32 noundef %y) !type !0 {
+  define i32 @_Z3fooii(i32 %x, i32 %y) !type !0 {
   entry:
     %x.addr = alloca i32, align 4
     %y.addr = alloca i32, align 4
@@ -41,7 +41,7 @@
     store i32 %y, ptr %y.addr, align 4
     %x_val = load i32, ptr %x.addr, align 4
     %y_val = load i32, ptr %y.addr, align 4
-    %call = call noundef i32 @_Z3barii(i32 noundef %x_val, i32 noundef %y_val)
+    %call = call i32 @_Z3barii(i32 %x_val, i32 %y_val)
     ret i32 %call
   }
   
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 c44a4df439609..d60484a75ac72 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -10,7 +10,7 @@
 --- |
   declare void @foo(i8 signext %a)
   
-  define dso_local i32 @main() {
+  define i32 @main() {
   entry:
     %retval = alloca i32, align 4
     %fp = alloca ptr, align 8

>From 0848196a79696dbbb57963564c4dde103f3f43e0 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 14 May 2025 02:06:38 +0000
Subject: [PATCH 24/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/docs/CalleeTypeMetadata.rst | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/llvm/docs/CalleeTypeMetadata.rst b/llvm/docs/CalleeTypeMetadata.rst
index 8c35dec125f0c..9e0038229d78d 100644
--- a/llvm/docs/CalleeTypeMetadata.rst
+++ b/llvm/docs/CalleeTypeMetadata.rst
@@ -4,13 +4,14 @@ Callee Type Metadata
 
 Introduction
 ============
-This ``!callee_type`` metadata is introduced as part of an ongoing effort to generate a call graph
-section in the object file. The broader design for the call graph section and the compiler flags which
-will enable the feature will be documented as those changes land. The ``!callee_type`` metadata is used
-to identify types of intended callees of indirect call instructions. The ``!callee_type`` metadata is a
+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 ``!type`` metadata objects (See :doc:`TypeMetadata`) with each ``!type`` metadata
-pointing to a callee's :ref:`type identifier
-<calleetype-type-identifier>`.
+pointing to a callee's :ref:`type identifier <calleetype-type-identifier>`.
+LLVM's `control flow integrity`_ also uses the ``!type`` metadata in its implementation.
+
+.. _Control Flow Integrity(CFI): https://clang.llvm.org/docs/ControlFlowIntegrity.html
 
 .. _calleetype-type-identifier:
 

>From fb9fdab322cb588cc7c5403ff8f9ac25d96e99b4 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 14 May 2025 02:11:07 +0000
Subject: [PATCH 25/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/docs/CalleeTypeMetadata.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/docs/CalleeTypeMetadata.rst b/llvm/docs/CalleeTypeMetadata.rst
index 9e0038229d78d..0190c4dc1cbff 100644
--- a/llvm/docs/CalleeTypeMetadata.rst
+++ b/llvm/docs/CalleeTypeMetadata.rst
@@ -9,9 +9,9 @@ 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 ``!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`_ also uses the ``!type`` metadata in its implementation.
+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
+.. _Control Flow Integrity (CFI): https://clang.llvm.org/docs/ControlFlowIntegrity.html
 
 .. _calleetype-type-identifier:
 

>From d95d4f91f536a26869079c68694b7b5722f985e7 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 27 May 2025 18:29:02 +0000
Subject: [PATCH 26/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/test/Assembler/callee-type-metadata.ll   | 24 +++++++++++++++
 .../Inline/drop-callee-type-metadata.ll       | 29 ++++++++++++++-----
 .../InstCombine/drop-callee-type-metadata.ll  | 18 ++++++++----
 llvm/test/Verifier/callee-type-metadata.ll    | 19 ++++--------
 4 files changed, 64 insertions(+), 26 deletions(-)
 create mode 100644 llvm/test/Assembler/callee-type-metadata.ll

diff --git a/llvm/test/Assembler/callee-type-metadata.ll b/llvm/test/Assembler/callee-type-metadata.ll
new file mode 100644
index 0000000000000..371473b9313cc
--- /dev/null
+++ b/llvm/test/Assembler/callee-type-metadata.ll
@@ -0,0 +1,24 @@
+;; Test if the callee_type metadata attached to indirect call sites adhere to the expected format.
+
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+define i32 @_Z13call_indirectPFicEc(ptr %func, i8 signext %x) !type !0 {
+entry:
+  %func.addr = alloca ptr, align 8
+  %x.addr = alloca i8, align 1
+  store ptr %func, ptr %func.addr, align 8
+  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: %call = call i32 %fptr(i8 signext %x_val), !callee_type !1
+  %call = call i32 %fptr(i8 signext %x_val), !callee_type !1
+  ret i32 %call
+}
+
+declare !type !2 i32 @_Z3barc(i8 signext)
+
+!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFicE"}
+!4 = !{!3}
+!8 = !{i64 0, !"_ZTSFicE.generalized"}
diff --git a/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
index ce7830536c200..547588089c5b0 100644
--- a/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
+++ b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll
@@ -1,20 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ;; Test if the callee_type metadata is dropped when it is
 ;; is mapped to a direct function call from an indirect call during inlining.
 
-; RUN: opt -passes="inline" -S < %s | FileCheck %s
+; RUN: opt -passes=inline -S < %s | FileCheck %s
 
-define i32 @_Z13call_indirectPFicEc(ptr %func, i8 %x) local_unnamed_addr !type !0 {
+define i32 @_Z13call_indirectPFicEc(ptr %func, i8 %x) !type !0 {
+; CHECK-LABEL: define i32 @_Z13call_indirectPFicEc(
+; CHECK-SAME: ptr [[FUNC:%.*]], i8 [[X:%.*]]) !type [[META0:![0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 [[FUNC]](i8 [[X]]), !callee_type [[META1:![0-9]+]]
+; CHECK-NEXT:    ret i32 [[CALL]]
+;
 entry:
   %call = call i32 %func(i8 %x), !callee_type !1
   ret i32 %call
 }
 
-define i32 @_Z3barv() local_unnamed_addr !type !3 {
+define i32 @_Z3barv() !type !3 {
+; CHECK-LABEL: define i32 @_Z3barv(
+; CHECK-SAME: ) !type [[META3:![0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL_I:%.*]] = call i32 @_Z3fooc(i8 97)
+; CHECK-NEXT:    ret i32 [[CALL_I]]
+;
 entry:
-  ; CHECK-LABEL: define i32 @_Z3barv()
-  ; CHECK-NEXT: entry:
-  ; CHECK-NOT: !callee_type
-  ; CHECK-NEXT: %call.i = call i32 @_Z3fooc(i8 97)
   %call = call i32 @_Z13call_indirectPFicEc(ptr nonnull @_Z3fooc, i8 97)
   ret i32 %call
 }
@@ -24,3 +33,9 @@ declare !type !2 i32 @_Z3fooc(i8 signext)
 !1 = !{!2}
 !2 = !{i64 0, !"_ZTSFicE.generalized"}
 !3 = !{i64 0, !"_ZTSFivE.generalized"}
+;.
+; CHECK: [[META0]] = !{i64 0, !"_ZTSFiPvcE.generalized"}
+; CHECK: [[META1]] = !{[[META2:![0-9]+]]}
+; CHECK: [[META2]] = !{i64 0, !"_ZTSFicE.generalized"}
+; CHECK: [[META3]] = !{i64 0, !"_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 13c60f675d66d..debb5eddb9208 100644
--- a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
+++ b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
@@ -1,14 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ;; Test if the callee_type metadata is dropped when it is attached
 ;; to a direct function call during instcombine.
 
-; RUN: opt -passes="instcombine" -S < %s | FileCheck %s
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
 
-define i32 @_Z3barv() local_unnamed_addr !type !3 {
+define i32 @_Z3barv() !type !3 {
+; CHECK-LABEL: define i32 @_Z3barv(
+; CHECK-SAME: ) !type [[META0:![0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @_Z3fooc(i8 97)
+; CHECK-NEXT:    ret i32 [[CALL]]
+;
 entry:
-  ; CHECK-LABEL: define i32 @_Z3barv()
-  ; CHECK-NEXT: entry:
-  ; CHECK-NOT: !callee_type
-  ; CHECK-NEXT: %call = call i32 @_Z3fooc(i8 97)  
   %call = call i32 @_Z3fooc(i8 97), !callee_type !1
   ret i32 %call
 }
@@ -19,3 +22,6 @@ declare !type !2 i32 @_Z3fooc(i8 signext)
 !1 = !{!2}
 !2 = !{i64 0, !"_ZTSFicE.generalized"}
 !3 = !{i64 0, !"_ZTSFivE.generalized"}
+;.
+; CHECK: [[META0]] = !{i64 0, !"_ZTSFivE.generalized"}
+;.
diff --git a/llvm/test/Verifier/callee-type-metadata.ll b/llvm/test/Verifier/callee-type-metadata.ll
index 0107dec27de34..694daab14c784 100644
--- a/llvm/test/Verifier/callee-type-metadata.ll
+++ b/llvm/test/Verifier/callee-type-metadata.ll
@@ -1,6 +1,6 @@
 ;; Test if the callee_type metadata attached to indirect call sites adhere to the expected format.
 
-; RUN: not opt -passes=verify < %s 2>&1 | FileCheck %s
+; RUN: not llvm-as -disable-output < %s 2>&1 | FileCheck %s
 define i32 @_Z13call_indirectPFicEc(ptr %func, i8 signext %x) !type !0 {
 entry:
   %func.addr = alloca ptr, align 8
@@ -8,23 +8,16 @@ entry:
   store ptr %func, ptr %func.addr, align 8
   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
-  ;; No failures expected for this callee_type metdata.
-  %call = call i32 %fptr(i8 signext %x_val), !callee_type !1
+  %x_val = load i8, ptr %x.addr, align 1  
   ;; callee_type metdata is a type metadata instead of a list of type metadata nodes.
   ; CHECK: The callee_type metadata must be a list of type metadata nodes
-  %call2 = call i32 %fptr(i8 signext %x_val), !callee_type !0
+  %call = call i32 %fptr(i8 signext %x_val), !callee_type !0
   ;; callee_type metdata must be a list of "generalized" type metadata.
   ; CHECK: Only generalized type metadata can be part of the callee_type metadata list
-  %call3 = call i32 %fptr(i8 signext %x_val), !callee_type !4
+  %call2 = call i32 %fptr(i8 signext %x_val), !callee_type !2
   ret i32 %call
 }
 
-declare !type !2 i32 @_Z3barc(i8 signext)
-
 !0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
-!1 = !{!2}
-!2 = !{i64 0, !"_ZTSFicE.generalized"}
-!3 = !{i64 0, !"_ZTSFicE"}
-!4 = !{!3}
-!8 = !{i64 0, !"_ZTSFicE.generalized"}
+!1 = !{i64 0, !"_ZTSFicE"}
+!2 = !{!1}

>From 99e871ffe36c9dd8e2eb45682d5f2199ca5eacce Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 11 Jun 2025 00:16:17 +0000
Subject: [PATCH 27/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/docs/CalleeTypeMetadata.rst              |   4 +-
 llvm/lib/IR/Metadata.cpp                      |   4 +-
 .../InstCombine/InstCombineCalls.cpp          |   4 +-
 llvm/lib/Transforms/Utils/Local.cpp           |  17 +-
 llvm/test/Assembler/callee-type-metadata.ll   |   3 -
 .../InstCombine/drop-callee-type-metadata.ll  |   8 +-
 .../SimplifyCFG/merge-callee-type-metadata.ll | 148 ++++++++++++++++++
 7 files changed, 170 insertions(+), 18 deletions(-)
 create mode 100644 llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll

diff --git a/llvm/docs/CalleeTypeMetadata.rst b/llvm/docs/CalleeTypeMetadata.rst
index 0190c4dc1cbff..45d0657966a8c 100644
--- a/llvm/docs/CalleeTypeMetadata.rst
+++ b/llvm/docs/CalleeTypeMetadata.rst
@@ -7,8 +7,8 @@ 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 ``!type`` metadata objects (See :doc:`TypeMetadata`) with each ``!type`` metadata
-pointing to a callee's :ref:`type identifier <calleetype-type-identifier>`.
+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
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 82c1b96f5fb7e..4894cf41ae7e1 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1306,7 +1306,7 @@ MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
                                             MDNode *B) {
   SmallVector<Metadata *, 8> AB;
   SmallSet<Metadata *, 8> MergedCallees;
-  auto AddUniqueCallees = [&AB, &MergedCallees](llvm::MDNode *N) {
+  auto AddUniqueCallees = [&AB, &MergedCallees](MDNode *N) {
     if (!N)
       return;
     for (const MDOperand &Op : N->operands()) {
@@ -1317,7 +1317,7 @@ MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
   };
   AddUniqueCallees(A);
   AddUniqueCallees(B);
-  return llvm::MDNode::get(Ctx, AB);
+  return MDNode::get(Ctx, AB);
 }
 
 MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 04790af1dbd2b..308d7bc7c91b5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -4163,8 +4163,10 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
 
   // Drop unnecessary callee_type metadata from calls that were converted
   // into direct calls.
-  if (Call.getMetadata(LLVMContext::MD_callee_type) && !Call.isIndirectCall())
+  if (Call.getMetadata(LLVMContext::MD_callee_type) && !Call.isIndirectCall()) {
     Call.setMetadata(LLVMContext::MD_callee_type, nullptr);
+    Changed = true;
+  }
 
   // Drop unnecessary kcfi operand bundles from calls that were converted
   // into direct calls.
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index d37fccfaaa301..d8f68089b1074 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3365,6 +3365,7 @@ static void combineMetadata(Instruction *K, const Instruction *J,
       case LLVMContext::MD_mmra:
       case LLVMContext::MD_memprof:
       case LLVMContext::MD_callsite:
+      case LLVMContext::MD_callee_type:
         break;
       case LLVMContext::MD_align:
         if (!AAOnly && (DoesKMove || !K->hasMetadata(LLVMContext::MD_noundef)))
@@ -3377,11 +3378,6 @@ static void combineMetadata(Instruction *K, const Instruction *J,
           K->setMetadata(Kind,
             MDNode::getMostGenericAlignmentOrDereferenceable(JMD, KMD));
         break;
-      case LLVMContext::MD_callee_type:
-        if (!AAOnly)
-          K->setMetadata(Kind, MDNode::getMergedCalleeTypeMetadata(
-                                   K->getContext(), KMD, JMD));
-        break;
       case LLVMContext::MD_preserve_access_index:
         // Preserve !preserve.access.index in K.
         break;
@@ -3442,6 +3438,17 @@ static void combineMetadata(Instruction *K, const Instruction *J,
                    MDNode::getMergedCallsiteMetadata(KCallSite, JCallSite));
   }
 
+  // Merge callee_type metadata.
+  // Handle separately to support cases where only one instruction has the
+  // metadata.
+  auto *JCalleeType = J->getMetadata(LLVMContext::MD_callee_type);
+  auto *KCalleeType = K->getMetadata(LLVMContext::MD_callee_type);
+  if (!AAOnly && (JCalleeType || KCalleeType)) {
+    K->setMetadata(LLVMContext::MD_callee_type,
+                   MDNode::getMergedCalleeTypeMetadata(
+                       K->getContext(), KCalleeType, JCalleeType));
+  }
+
   // Merge prof metadata.
   // Handle separately to support cases where only one instruction has the
   // metadata.
diff --git a/llvm/test/Assembler/callee-type-metadata.ll b/llvm/test/Assembler/callee-type-metadata.ll
index 371473b9313cc..9c3cfbe82fc13 100644
--- a/llvm/test/Assembler/callee-type-metadata.ll
+++ b/llvm/test/Assembler/callee-type-metadata.ll
@@ -19,6 +19,3 @@ declare !type !2 i32 @_Z3barc(i8 signext)
 !0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
 !1 = !{!2}
 !2 = !{i64 0, !"_ZTSFicE.generalized"}
-!3 = !{i64 0, !"_ZTSFicE"}
-!4 = !{!3}
-!8 = !{i64 0, !"_ZTSFicE.generalized"}
diff --git a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
index debb5eddb9208..83215f78be1b0 100644
--- a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
+++ b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll
@@ -1,14 +1,13 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ;; Test if the callee_type metadata is dropped when it is attached
 ;; to a direct function call during instcombine.
 
 ; RUN: opt -passes=instcombine -S < %s | FileCheck %s
 
-define i32 @_Z3barv() !type !3 {
+define i32 @_Z3barv() !type !0 {
 ; CHECK-LABEL: define i32 @_Z3barv(
 ; CHECK-SAME: ) !type [[META0:![0-9]+]] {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CALL:%.*]] = call i32 @_Z3fooc(i8 97)
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @_Z3fooc(i8 97){{$}}
 ; CHECK-NEXT:    ret i32 [[CALL]]
 ;
 entry:
@@ -18,10 +17,9 @@ entry:
 
 declare !type !2 i32 @_Z3fooc(i8 signext)
 
-!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
+!0 = !{i64 0, !"_ZTSFivE.generalized"}
 !1 = !{!2}
 !2 = !{i64 0, !"_ZTSFicE.generalized"}
-!3 = !{i64 0, !"_ZTSFivE.generalized"}
 ;.
 ; CHECK: [[META0]] = !{i64 0, !"_ZTSFivE.generalized"}
 ;.
diff --git a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
new file mode 100644
index 0000000000000..8d230425520c2
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
@@ -0,0 +1,148 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
+;; Test if the callee_type metadata is merged correctly.
+
+; RUN: opt -passes=simplifycfg -S < %s | FileCheck %s
+
+;; Test if the callee_type metadata is merged correctly when
+;; the instructions carry differring callee_type metadata.
+define ptr @_Z10test_diffb(i1 zeroext %b) {
+; CHECK-LABEL: define ptr @_Z10test_diffb(
+; CHECK-SAME: i1 zeroext [[B:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @_Znwm(i64 4), !callee_type [[META0:![0-9]+]]
+; CHECK-NEXT:    ret ptr [[CALL]]
+;
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %call = call ptr @_Znwm(i64 4), !callee_type !4
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %call1 = call ptr @_Znwm(i64 4), !callee_type !3
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %x.0 = phi ptr [ %call, %if.then ], [ %call1, %if.else ]
+  ret ptr %x.0
+}
+
+;; Test if the callee_type metadata is merged correctly when
+;; the instructions carry same callee_type metadata.
+define ptr @_Z10test_sameb(i1 zeroext %b) {
+; CHECK-LABEL: define ptr @_Z10test_sameb(
+; CHECK-SAME: i1 zeroext [[B:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @_Znwm(i64 4), !callee_type [[META3:![0-9]+]]
+; CHECK-NEXT:    ret ptr [[CALL]]
+;
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %call = call ptr @_Znwm(i64 4), !callee_type !3
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %call1 = call ptr @_Znwm(i64 4), !callee_type !3
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %x.0 = phi ptr [ %call, %if.then ], [ %call1, %if.else ]
+  ret ptr %x.0
+}
+
+;; Test if the callee_type metadata is merged correctly when
+;; only the right instruction has callee_type metadata.
+define ptr @_Z10test_leftb(i1 zeroext %b) {
+; CHECK-LABEL: define ptr @_Z10test_leftb(
+; CHECK-SAME: i1 zeroext [[B:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @_Znwm(i64 4), !callee_type [[META4:![0-9]+]]
+; CHECK-NEXT:    ret ptr [[CALL]]
+;
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %call = call ptr @_Znwm(i64 4), !callee_type !4
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %call1 = call ptr @_Znwm(i64 4)
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %x.0 = phi ptr [ %call, %if.then ], [ %call1, %if.else ]
+  ret ptr %x.0
+}
+
+;; Test if the callee_type metadata is merged correctly when
+;; each of the callee_type metadata are lists.
+define ptr @_Z10test_rightb(i1 zeroext %b) {
+; CHECK-LABEL: define ptr @_Z10test_rightb(
+; CHECK-SAME: i1 zeroext [[B:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @_Znwm(i64 4), !callee_type [[META3]]
+; CHECK-NEXT:    ret ptr [[CALL]]
+;
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %call = call ptr @_Znwm(i64 4)
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %call1 = call ptr @_Znwm(i64 4), !callee_type !3
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %x.0 = phi ptr [ %call, %if.then ], [ %call1, %if.else ]
+  ret ptr %x.0
+}
+
+;; Test if the callee_type metadata is merged correctly when
+;; only the left instruction has callee_type metadata.
+define ptr @_Z10test_listb(i1 zeroext %b) {
+; CHECK-LABEL: define ptr @_Z10test_listb(
+; CHECK-SAME: i1 zeroext [[B:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @_Znwm(i64 4), !callee_type [[META5:![0-9]+]]
+; CHECK-NEXT:    ret ptr [[CALL]]
+;
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %call = call ptr @_Znwm(i64 4), !callee_type !6
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %call1 = call ptr @_Znwm(i64 4), !callee_type !5
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %x.0 = phi ptr [ %call, %if.then ], [ %call1, %if.else ]
+  ret ptr %x.0
+}
+
+declare ptr @_Znwm(i64)
+
+!0 = !{i64 0, !"callee_type0.generalized"}
+!1 = !{i64 0, !"callee_type1.generalized"}
+!2 = !{i64 0, !"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: [[META3]] = !{[[META2]]}
+; CHECK: [[META4]] = !{[[META1]]}
+; CHECK: [[META5]] = !{[[META2]], [[META1]], [[META6:![0-9]+]]}
+; CHECK: [[META6]] = !{i64 0, !"callee_type1.generalized"}
+;.

>From 27e073c571e720bebbe25f2c983d248612209ad2 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 11 Jun 2025 00:32:31 +0000
Subject: [PATCH 28/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/lib/IR/Metadata.cpp                                    | 2 +-
 .../Transforms/SimplifyCFG/merge-callee-type-metadata.ll    | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 4894cf41ae7e1..7ba3f5ec6391d 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1305,7 +1305,7 @@ static void addRange(SmallVectorImpl<ConstantInt *> &EndPoints,
 MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
                                             MDNode *B) {
   SmallVector<Metadata *, 8> AB;
-  SmallSet<Metadata *, 8> MergedCallees;
+  SmallPtrSet<Metadata *, 8> MergedCallees;
   auto AddUniqueCallees = [&AB, &MergedCallees](MDNode *N) {
     if (!N)
       return;
diff --git a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
index 8d230425520c2..42bc9b6732176 100644
--- a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
+++ b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
@@ -54,7 +54,7 @@ if.end:                                           ; preds = %if.else, %if.then
 }
 
 ;; Test if the callee_type metadata is merged correctly when
-;; only the right instruction has callee_type metadata.
+;; only the left instruction has callee_type metadata.
 define ptr @_Z10test_leftb(i1 zeroext %b) {
 ; CHECK-LABEL: define ptr @_Z10test_leftb(
 ; CHECK-SAME: i1 zeroext [[B:%.*]]) {
@@ -79,7 +79,7 @@ if.end:                                           ; preds = %if.else, %if.then
 }
 
 ;; Test if the callee_type metadata is merged correctly when
-;; each of the callee_type metadata are lists.
+;; only the right instruction has callee_type metadata.
 define ptr @_Z10test_rightb(i1 zeroext %b) {
 ; CHECK-LABEL: define ptr @_Z10test_rightb(
 ; CHECK-SAME: i1 zeroext [[B:%.*]]) {
@@ -104,7 +104,7 @@ if.end:                                           ; preds = %if.else, %if.then
 }
 
 ;; Test if the callee_type metadata is merged correctly when
-;; only the left instruction has callee_type metadata.
+;; each of the callee_type metadata are lists.
 define ptr @_Z10test_listb(i1 zeroext %b) {
 ; CHECK-LABEL: define ptr @_Z10test_listb(
 ; CHECK-SAME: i1 zeroext [[B:%.*]]) {

>From 6a6768e2be89453eff99872dda3f4fe664e9e7a2 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 18 Jul 2025 15:33:44 +0000
Subject: [PATCH 29/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/lib/IR/Verifier.cpp                   | 3 +--
 llvm/test/Verifier/callee-type-metadata.ll | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index cc7f28cf81cca..9bd573e773610 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5195,9 +5195,8 @@ void Verifier::visitCallsiteMetadata(Instruction &I, MDNode *MD) {
 }
 
 static inline bool isConstantIntMetadataOperand(const Metadata *MD) {
-  if (auto *VAL = dyn_cast<ValueAsMetadata>(MD)) {
+  if (auto *VAL = dyn_cast<ValueAsMetadata>(MD))
     return isa<ConstantInt>(VAL->getValue());
-  }
   return false;
 }
 
diff --git a/llvm/test/Verifier/callee-type-metadata.ll b/llvm/test/Verifier/callee-type-metadata.ll
index 471e831167038..50cf37b941fe9 100644
--- a/llvm/test/Verifier/callee-type-metadata.ll
+++ b/llvm/test/Verifier/callee-type-metadata.ll
@@ -30,4 +30,4 @@ entry:
 !5 = !{!"expected_int", !"_ZTSFicE"}
 !6 = !{!5}
 !7 = !{i64 0, !"_ZTSFicE"}
-!8 = !{!7}
\ No newline at end of file
+!8 = !{!7}

>From cf8aeaec9444717560f4070e3f25289dd04ac5d0 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 18 Jul 2025 17:35:32 +0000
Subject: [PATCH 30/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/lib/Transforms/Utils/Local.cpp           | 19 +++++++++++--------
 .../SimplifyCFG/merge-callee-type-metadata.ll | 15 +++++++--------
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index fc8c4ea002b68..7d0dd447c91ac 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3158,14 +3158,17 @@ static void combineMetadata(Instruction *K, const Instruction *J,
   }
 
   // Merge callee_type metadata.
-  // Given the called operands are identical, presence of at least one
-  // callee_type metadata guarantees the intended callee.
-  auto *JCalleeType = J->getMetadata(LLVMContext::MD_callee_type);
-  auto *KCalleeType = K->getMetadata(LLVMContext::MD_callee_type);
-  if (!AAOnly && (JCalleeType || KCalleeType)) {
-    K->setMetadata(LLVMContext::MD_callee_type,
-                   MDNode::getMergedCalleeTypeMetadata(
-                       K->getContext(), KCalleeType, JCalleeType));
+  if (!AAOnly) {
+    auto *JCalleeType = J->getMetadata(LLVMContext::MD_callee_type);
+    auto *KCalleeType = K->getMetadata(LLVMContext::MD_callee_type);
+    // Drop the callee_type metadata if either of the call instructions do not
+    // have it.
+    if (JCalleeType && KCalleeType) {
+      K->setMetadata(LLVMContext::MD_callee_type,
+                     MDNode::getMergedCalleeTypeMetadata(
+                         K->getContext(), KCalleeType, JCalleeType));
+    } else
+      K->setMetadata(LLVMContext::MD_callee_type, nullptr);
   }
 
   // Merge prof metadata.
diff --git a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
index a01baaba19280..3e56939b1642f 100644
--- a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
+++ b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll
@@ -61,7 +61,7 @@ if.end:                                           ; preds = %if.else, %if.then
   ret ptr %x.0
 }
 
-;; Test if the callee_type metadata is merged correctly when
+;; Test if the callee_type metadata is dropped correctly when
 ;; only the left instruction has callee_type metadata.
 define ptr @_Z10test_leftb(i1 zeroext %b) {
 ; CHECK-LABEL: define ptr @_Z10test_leftb(
@@ -69,7 +69,7 @@ define ptr @_Z10test_leftb(i1 zeroext %b) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    [[FN:%.*]] = alloca ptr, align 8
 ; CHECK-NEXT:    store ptr @_Znwm, ptr [[FN]], align 8
-; CHECK-NEXT:    [[CALL:%.*]] = call ptr [[FN]](i64 4), !callee_type [[META4:![0-9]+]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr [[FN]](i64 4)
 ; CHECK-NEXT:    ret ptr [[CALL]]
 ;
 entry:
@@ -90,7 +90,7 @@ if.end:                                           ; preds = %if.else, %if.then
   ret ptr %x.0
 }
 
-;; Test if the callee_type metadata is merged correctly when
+;; Test if the callee_type metadata is dropped correctly when
 ;; only the right instruction has callee_type metadata.
 define ptr @_Z10test_rightb(i1 zeroext %b) {
 ; CHECK-LABEL: define ptr @_Z10test_rightb(
@@ -98,7 +98,7 @@ define ptr @_Z10test_rightb(i1 zeroext %b) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    [[FN:%.*]] = alloca ptr, align 8
 ; CHECK-NEXT:    store ptr @_Znwm, ptr [[FN]], align 8
-; CHECK-NEXT:    [[CALL:%.*]] = call ptr [[FN]](i64 4), !callee_type [[META3]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr [[FN]](i64 4)
 ; CHECK-NEXT:    ret ptr [[CALL]]
 ;
 entry:
@@ -127,7 +127,7 @@ define ptr @_Z10test_listb(i1 zeroext %b) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    [[FN:%.*]] = alloca ptr, align 8
 ; CHECK-NEXT:    store ptr @_Znwm, ptr [[FN]], align 8
-; CHECK-NEXT:    [[CALL:%.*]] = call ptr [[FN]](i64 4), !callee_type [[META5:![0-9]+]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr [[FN]](i64 4), !callee_type [[META4:![0-9]+]]
 ; CHECK-NEXT:    ret ptr [[CALL]]
 ;
 entry:
@@ -162,7 +162,6 @@ declare ptr @_Znwm(i64)
 ; CHECK: [[META1]] = !{i64 0, !"callee_type2.generalized"}
 ; CHECK: [[META2]] = !{i64 0, !"callee_type0.generalized"}
 ; CHECK: [[META3]] = !{[[META2]]}
-; CHECK: [[META4]] = !{[[META1]]}
-; CHECK: [[META5]] = !{[[META2]], [[META1]], [[META6:![0-9]+]]}
-; CHECK: [[META6]] = !{i64 0, !"callee_type1.generalized"}
+; CHECK: [[META4]] = !{[[META2]], [[META1]], [[META5:![0-9]+]]}
+; CHECK: [[META5]] = !{i64 0, !"callee_type1.generalized"}
 ;.

>From 58b5d3dee4c6f6a512911bbb50bf396300904d1b Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 18 Jul 2025 21:01:02 +0000
Subject: [PATCH 31/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/lib/IR/Metadata.cpp            |  6 ++++--
 llvm/lib/Transforms/Utils/Local.cpp | 20 ++++++--------------
 2 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 8f3f9df3afafd..929c1d8d6d36e 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1305,11 +1305,13 @@ static void addRange(SmallVectorImpl<ConstantInt *> &EndPoints,
 
 MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
                                             MDNode *B) {
+  // Drop the callee_type metadata if either of the call instructions do not
+  // have it.
+  if (!A || !B)
+    return nullptr;
   SmallVector<Metadata *, 8> AB;
   SmallPtrSet<Metadata *, 8> MergedCallees;
   auto AddUniqueCallees = [&AB, &MergedCallees](MDNode *N) {
-    if (!N)
-      return;
     for (Metadata *MD : N->operands()) {
       if (MergedCallees.insert(MD).second)
         AB.push_back(MD);
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 7d0dd447c91ac..f21e00f53eb12 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3080,7 +3080,13 @@ static void combineMetadata(Instruction *K, const Instruction *J,
       case LLVMContext::MD_mmra:
       case LLVMContext::MD_memprof:
       case LLVMContext::MD_callsite:
+        break;
       case LLVMContext::MD_callee_type:
+        if (!AAOnly) {
+          K->setMetadata(
+              LLVMContext::MD_callee_type,
+              MDNode::getMergedCalleeTypeMetadata(K->getContext(), KMD, JMD));
+        }
         break;
       case LLVMContext::MD_align:
         if (!AAOnly && (DoesKMove || !K->hasMetadata(LLVMContext::MD_noundef)))
@@ -3157,20 +3163,6 @@ static void combineMetadata(Instruction *K, const Instruction *J,
                    MDNode::getMergedCallsiteMetadata(KCallSite, JCallSite));
   }
 
-  // Merge callee_type metadata.
-  if (!AAOnly) {
-    auto *JCalleeType = J->getMetadata(LLVMContext::MD_callee_type);
-    auto *KCalleeType = K->getMetadata(LLVMContext::MD_callee_type);
-    // Drop the callee_type metadata if either of the call instructions do not
-    // have it.
-    if (JCalleeType && KCalleeType) {
-      K->setMetadata(LLVMContext::MD_callee_type,
-                     MDNode::getMergedCalleeTypeMetadata(
-                         K->getContext(), KCalleeType, JCalleeType));
-    } else
-      K->setMetadata(LLVMContext::MD_callee_type, nullptr);
-  }
-
   // Merge prof metadata.
   // Handle separately to support cases where only one instruction has the
   // metadata.

>From 37d8b4000285568178d339af2e8e39fc900a117b Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 18 Jul 2025 21:34:56 +0000
Subject: [PATCH 32/33] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?=
 =?UTF-8?q?changes=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1

[skip ci]
---
 llvm/include/llvm/IR/Metadata.h     | 4 ++--
 llvm/lib/IR/Metadata.cpp            | 7 +++----
 llvm/lib/Transforms/Utils/Local.cpp | 5 ++---
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index 7ed562286bc3c..af252aa24567a 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -1474,8 +1474,8 @@ class MDNode : public Metadata {
                                                 const Instruction *BInstr);
   LLVM_ABI static MDNode *getMergedMemProfMetadata(MDNode *A, MDNode *B);
   LLVM_ABI static MDNode *getMergedCallsiteMetadata(MDNode *A, MDNode *B);
-  LLVM_ABI static MDNode *getMergedCalleeTypeMetadata(LLVMContext &Ctx,
-                                                      MDNode *A, MDNode *B);
+  LLVM_ABI static MDNode *getMergedCalleeTypeMetadata(const MDNode *A,
+                                                      const MDNode *B);
 };
 
 /// Tuple of metadata.
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 929c1d8d6d36e..0dbd07f4865dc 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1303,15 +1303,14 @@ static void addRange(SmallVectorImpl<ConstantInt *> &EndPoints,
   EndPoints.push_back(High);
 }
 
-MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
-                                            MDNode *B) {
+MDNode *MDNode::getMergedCalleeTypeMetadata(const MDNode *A, const MDNode *B) {
   // Drop the callee_type metadata if either of the call instructions do not
   // have it.
   if (!A || !B)
     return nullptr;
   SmallVector<Metadata *, 8> AB;
   SmallPtrSet<Metadata *, 8> MergedCallees;
-  auto AddUniqueCallees = [&AB, &MergedCallees](MDNode *N) {
+  auto AddUniqueCallees = [&AB, &MergedCallees](const MDNode *N) {
     for (Metadata *MD : N->operands()) {
       if (MergedCallees.insert(MD).second)
         AB.push_back(MD);
@@ -1319,7 +1318,7 @@ MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
   };
   AddUniqueCallees(A);
   AddUniqueCallees(B);
-  return MDNode::get(Ctx, AB);
+  return MDNode::get(A->getContext(), AB);
 }
 
 MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) {
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index f21e00f53eb12..548070eb1578d 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3083,9 +3083,8 @@ static void combineMetadata(Instruction *K, const Instruction *J,
         break;
       case LLVMContext::MD_callee_type:
         if (!AAOnly) {
-          K->setMetadata(
-              LLVMContext::MD_callee_type,
-              MDNode::getMergedCalleeTypeMetadata(K->getContext(), KMD, JMD));
+          K->setMetadata(LLVMContext::MD_callee_type,
+                         MDNode::getMergedCalleeTypeMetadata(KMD, JMD));
         }
         break;
       case LLVMContext::MD_align:

>From 79920a88ea86b00d7bd816602be4a7c7e27b85d3 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 23 Jul 2025 02:51:10 +0000
Subject: [PATCH 33/33] Reduce tests. Rename function names in tests.

Created using spr 1.3.6-beta.1
---
 ...te-info-ambiguous-indirect-call-typeid.mir | 64 ++++++-------------
 .../call-site-info-direct-calls-typeid.mir    | 54 ++++++----------
 .../CodeGen/MIR/X86/call-site-info-typeid.mir | 24 +++----
 3 files changed, 46 insertions(+), 96 deletions(-)

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 c6198df2c1d3a..75585da8cbf22 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
@@ -1,59 +1,31 @@
-# Test MIR printer and parser for type id field in callSites. It is used
-# for propagating call site type identifiers to emit in the call graph section.
+# Test MIR printer and parser to check if a call instruction with multiple
+# callee types are handled correctly.
 
 # RUN: llc --call-graph-section %s -run-pass=none -o - | FileCheck --match-full-lines %s
-# CHECK: name: main
+# CHECK: name: ambiguous_caller
 # CHECK: callSites:
-# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [] }
-# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
-# CHECK-NEXT: [ 1234567890 ] }
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: {{.*}}, calleeTypeIds:
+# CHECK-NEXT: [ 1234, 5678 ] }
 
---- |  
-  
-  declare !type !0 i32 @_Z3addii(i32, i32)
-
-  declare !type !0 i32 @_Z8multiplyii(i32, i32)
-  
-  declare !type !1 ptr @_Z13get_operationb(i1 zeroext %is_addition)
-  
-  define i32 @main(i32 %argc) !type !2 {
+--- |
+  define ptr @ambiguous_caller() {
   entry:
-    %retval = alloca i32, align 4
-    %argc.addr = alloca i32, align 4
-    %x = alloca i32, align 4
-    %y = alloca i32, align 4
-    %op = alloca ptr, align 8
-    store i32 0, ptr %retval, align 4
-    store i32 %argc, ptr %argc.addr, align 4
-    store i32 5, ptr %x, align 4
-    store i32 10, ptr %y, align 4
-    %argc_val = load i32, ptr %argc.addr, align 4
-    %rem = srem i32 %argc_val, 2
-    %cmp = icmp eq i32 %rem, 0
-    %call = call ptr @_Z13get_operationb(i1 zeroext %cmp)
-    store ptr %call, ptr %op, align 8
-    %op_val = load ptr, ptr %op, align 8
-    %x_val = load i32, ptr %x, align 4
-    %y_val = load i32, ptr %y, align 4
-    %call1 = call i32 %op_val(i32 %x_val, i32 %y_val), !callee_type !3
-    ret i32 %call1
+    %fn = alloca ptr, align 8
+    %call1 = call ptr %fn(i64 4), !callee_type !0
+    ret ptr %call1
   }
   
-  !0 = !{i64 0, !"_ZTSFiiiE.generalized"}
-  !1 = !{i64 0, !"_ZTSFPvbE.generalized"}
-  !2 = !{i64 0, !"_ZTSFiiE.generalized"}
-  !3 = !{!0}
-
+  !0 = !{!1, !2}
+  !1 = !{i64 0, !"callee_type0.generalized"}
+  !2 = !{i64 0, !"callee_type2.generalized"}
 ...
 ---
-name:            main
+name:            ambiguous_caller
 callSites:
-  - { bb: 0, offset: 0, fwdArgRegs: [] }
-  - { bb: 0, offset: 2, fwdArgRegs: [], calleeTypeIds: [ 1234567890 ] }
+  - { bb: 0, offset: 1, fwdArgRegs: [], calleeTypeIds: [ 1234, 5678 ] }
 body:             |
   bb.0.entry:
-    CALL64pcrel32 @_Z13get_operationb, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax    
-    %7:gr64 = COPY $rax    
-    CALL64r %7, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
-
+    %0:gr64 = MOV32ri64 4
+    CALL64r killed %0, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
+    RET 0, $rax
 ...
diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
index 853e2ce85e188..f4decf2f70f2a 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
@@ -4,67 +4,51 @@
 
 # RUN: llc --call-graph-section %s -run-pass=none -o - | FileCheck --match-full-lines %s
 # CHECK-NOT: calleeTypeIds
-# CHECK: name: _Z3barii
+# CHECK: name: bar
 # CHECK: callSites:
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [] }
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [] }
-# CHECK: name: _Z3fooii
+# CHECK: name: foo
 # CHECK: callSites:
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [] }
 
---- |  
-  declare !type !0 i32 @_Z4fizzii(i32 %x, i32 %y)
-
-  declare !type !0 i32 @_Z4buzzii(i32 %x, i32 %y)
-
-  define i32 @_Z3barii(i32 %x, i32 %y) !type !0 {
+--- |
+  declare i32 @fizz(i32, i32)
+  
+  declare i32 @buzz(i32, i32)
+  
+  define i32 @bar(i32 %x, i32 %y) !type !0 {
   entry:
-    %x.addr = alloca i32, align 4
-    %y.addr = alloca i32, align 4
-    store i32 %x, ptr %x.addr, align 4
-    store i32 %y, ptr %y.addr, align 4
-    %x_val = load i32, ptr %x.addr, align 4
-    %y_val = load i32, ptr %y.addr, align 4
-    %call = call i32 @_Z4buzzii(i32 %x_val, i32 %y_val)
-    %x_val_2 = load i32, ptr %x.addr, align 4
-    %y_val_2 = load i32, ptr %y.addr, align 4
-    %call1 = call i32 @_Z4fizzii(i32 %x_val_2, i32 %y_val_2)
-    %sub = sub nsw i32 %call, %call1
-    ret i32 %sub
+    %call = call i32 @buzz(i32 %x, i32 %x)
+    %call1 = call i32 @fizz(i32 %x, i32 %x)
+    ret i32 0
   }
   
-  define i32 @_Z3fooii(i32 %x, i32 %y) !type !0 {
+  define i32 @foo(i32 %x, i32 %y) !type !0 {
   entry:
-    %x.addr = alloca i32, align 4
-    %y.addr = alloca i32, align 4
-    store i32 %x, ptr %x.addr, align 4
-    store i32 %y, ptr %y.addr, align 4
-    %x_val = load i32, ptr %x.addr, align 4
-    %y_val = load i32, ptr %y.addr, align 4
-    %call = call i32 @_Z3barii(i32 %x_val, i32 %y_val)
-    ret i32 %call
+    %call1 = call i32 @bar(i32 %x, i32 %x)
+    ret i32 0
   }
   
   !0 = !{i64 0, !"_ZTSFiiiE.generalized"}
-
 ...
 ---
-name:            _Z3barii
+name:            bar
 callSites:
   - { bb: 0, offset: 0, fwdArgRegs: [] }
   - { bb: 0, offset: 1, fwdArgRegs: [] }
 body:             |
   bb.0.entry:
-    CALL64pcrel32 @_Z4buzzii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax    
-    CALL64pcrel32 @_Z4fizzii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax    
+    CALL64pcrel32 target-flags(x86-plt) @buzz, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+    CALL64pcrel32 target-flags(x86-plt) @fizz, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
 
 ...
 ---
-name:            _Z3fooii
+name:            foo
 callSites:
   - { bb: 0, offset: 0, fwdArgRegs: [] }
 body:             |
   bb.0.entry:
-    CALL64pcrel32 @_Z3barii, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+    CALL64pcrel32 target-flags(x86-plt) @bar, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
 
 ...
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 09cf69c1f1ffa..c646699bd8718 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -2,33 +2,27 @@
 # for propagating call site type identifiers to emit in the call graph section.
 
 # RUN: llc --call-graph-section %s -run-pass=none -o - | FileCheck --match-full-lines %s
-# CHECK: name: main
+# CHECK: name: call_foo
 # CHECK: callSites:
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
 # CHECK-NEXT: [ 123456789 ] }
 
 --- |
-  declare void @foo(i8 signext %a)
-  
-  define i32 @main() {
+  define i32 @call_foo() {
   entry:
-    %retval = alloca i32, align 4
-    %fp = alloca ptr, align 8
-    store i32 0, ptr %retval, align 4
-    store ptr @foo, ptr %fp, align 8
-    %fp_val = load ptr, ptr %fp, align 8
-    call void %fp_val(i8 signext 97)
+    %0 = load ptr, ptr null, align 8
+    call void %0(i8 0), !callee_type !0
     ret i32 0
   }
 
+  !0 = !{!1}
+  !1 = !{i64 0, !"_ZTSFvcE.generalized"}
 ...
 ---
-name:            main
+name:            call_foo
 callSites:
-  - { bb: 0, offset: 1, fwdArgRegs: [], calleeTypeIds: [ 123456789 ] }
+  - { bb: 0, offset: 0, fwdArgRegs: [], calleeTypeIds: [ 123456789 ] }
 body:             |
   bb.0.entry:    
-    %0:gr64 = MOV32ri64 @foo    
-    CALL64r killed %0, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp
-
+    CALL64m $noreg, 1, $noreg, 0, $noreg, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit-def $rsp, implicit-def $ssp :: (load (s64) from `ptr null`)
 ...



More information about the llvm-commits mailing list