[clang] [llvm] [llvm] Extract and propagate callee_type metadata (PR #87575)

Prabhu Rajasekaran via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 23 10:19:18 PDT 2025


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

>From d2d56f463c746ec312fb8f9d1b15fd582274106f Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Wed, 3 Apr 2024 15:48:01 -0700
Subject: [PATCH 01/38] =?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/CodeGen/MIRYamlMapping.h    |   5 +
 llvm/include/llvm/CodeGen/MachineFunction.h   |   7 +-
 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 +
 llvm/lib/CodeGen/MIRParser/MIRParser.cpp      |  10 +-
 llvm/lib/CodeGen/MIRPrinter.cpp               |   3 +
 llvm/lib/CodeGen/MachineFunction.cpp          |   2 +-
 .../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 +
 .../Bitcode/operand-bundles-bc-analyzer.ll    |   1 +
 .../CodeGen/MIR/X86/call-site-info-typeid.mir |  68 +++++
 llvm/test/Verifier/operand-bundles.ll         |  13 +
 34 files changed, 871 insertions(+), 25 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
 create mode 100644 llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir

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/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index bb8dbb0478ff5..d71cdc63414dd 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -480,6 +480,10 @@ struct CallSiteInfo {
   MachineInstrLoc CallLocation;
   std::vector<ArgRegPair> ArgForwardingRegs;
 
+  /// Numeric callee type identifier used for call graph section.
+  using TypeIdTy = std::optional<uint64_t>;
+  TypeIdTy TypeId;
+
   bool operator==(const CallSiteInfo &Other) const {
     return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
            CallLocation.Offset == Other.CallLocation.Offset;
@@ -508,6 +512,7 @@ template <> struct MappingTraits<CallSiteInfo> {
     YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
     YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
                        std::vector<CallSiteInfo::ArgRegPair>());
+    YamlIO.mapOptional("typeId", CSInfo.TypeId);
   }
 
   static const bool flow = true;
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index 470997b31fe85..ad9456960f0f6 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -485,6 +485,9 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
   struct CallSiteInfo {
     /// Vector of call argument and its forwarding register.
     SmallVector<ArgRegPair, 1> ArgRegPairs;
+
+    /// Callee type id.
+    ConstantInt *TypeId = nullptr;
   };
 
 private:
@@ -492,7 +495,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
   GISelChangeObserver *Observer = nullptr;
 
   using CallSiteInfoMap = DenseMap<const MachineInstr *, CallSiteInfo>;
-  /// Map a call instruction to call site arguments forwarding info.
+  /// Map a call instruction to call site arguments forwarding and type id.
   CallSiteInfoMap CallSitesInfo;
 
   /// A helper function that returns call site info for a give call
@@ -1346,7 +1349,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
     });
   }
 
-  /// Start tracking the arguments passed to the call \p CallI.
+  /// Start tracking the arguments passed to the call \p CallI and call type.
   void addCallSiteInfo(const MachineInstr *CallI, CallSiteInfo &&CallInfo) {
     assert(CallI->isCandidateForCallSiteEntry());
     bool Inserted =
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/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index 4d9a8dc5602ba..4737ff5cb43af 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -427,12 +427,18 @@ bool MIRParserImpl::initializeCallSiteInfo(
         return error(Error, ArgRegPair.Reg.SourceRange);
       CSInfo.ArgRegPairs.emplace_back(Reg, ArgRegPair.ArgNo);
     }
+    if (YamlCSInfo.TypeId.has_value()) {
+      IntegerType *Int64Ty = Type::getInt64Ty(Context);
+      CSInfo.TypeId = ConstantInt::get(Int64Ty, YamlCSInfo.TypeId.value(),
+                                       /*isSigned=*/false);
+    }
 
-    if (TM.Options.EmitCallSiteInfo)
+    if (TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection)
       MF.addCallSiteInfo(&*CallI, std::move(CSInfo));
   }
 
-  if (YamlMF.CallSitesInfo.size() && !TM.Options.EmitCallSiteInfo)
+  if (YamlMF.CallSitesInfo.size() &&
+      !(TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection))
     return error(Twine("Call site info provided but not used"));
   return false;
 }
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index bbc6d39d17fc4..e0479ba700215 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -546,6 +546,9 @@ void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF,
       printRegMIR(ArgReg.Reg, YmlArgReg.Reg, TRI);
       YmlCS.ArgForwardingRegs.emplace_back(YmlArgReg);
     }
+    // Get type id.
+    if (CSInfo.second.TypeId)
+      YmlCS.TypeId = CSInfo.second.TypeId->getZExtValue();
     YMF.CallSitesInfo.push_back(YmlCS);
   }
 
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index ad53214992667..dd0f4e1c66c37 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -878,7 +878,7 @@ MachineFunction::getCallSiteInfo(const MachineInstr *MI) {
   assert(MI->isCandidateForCallSiteEntry() &&
          "Call site info refers only to call (MI) candidates");
 
-  if (!Target.Options.EmitCallSiteInfo)
+  if (!Target.Options.EmitCallSiteInfo && !Target.Options.EmitCallGraphSection)
     return CallSitesInfo.end();
   return CallSitesInfo.find(MI);
 }
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/Bitcode/operand-bundles-bc-analyzer.ll b/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll
index d860104b9cb3d..5628e17b4936e 100644
--- a/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll
+++ b/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll
@@ -13,6 +13,7 @@
 ; 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
diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
new file mode 100644
index 0000000000000..5ab797bfcc18f
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -0,0 +1,68 @@
+# 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: [], typeId:
+# 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
+  }
+  
+  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
+    call void %0(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, 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: '' }
+callSites:
+  - { bb: 0, offset: 6, 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
+    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
+
+...
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 3065b9b275511f4bd1840187af7de8934078d9ed Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Mon, 29 Apr 2024 11:53:52 -0700
Subject: [PATCH 02/38] =?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 966ac5afb9a1bcb1d14481dd93a6268f87c7e06c Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Wed, 13 Nov 2024 17:20:14 -0800
Subject: [PATCH 03/38] =?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 1a8d810d352fbe84c0521c7614689b60ade693c8 Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Tue, 19 Nov 2024 15:25:34 -0800
Subject: [PATCH 04/38] Fixed the tests and addressed most of the review
 comments.

Created using spr 1.3.6-beta.1
---
 llvm/include/llvm/CodeGen/MachineFunction.h   | 15 +++--
 .../CodeGen/AArch64/call-site-info-typeid.ll  | 28 +++------
 .../test/CodeGen/ARM/call-site-info-typeid.ll | 28 +++------
 .../CodeGen/MIR/X86/call-site-info-typeid.ll  | 58 ++++++++-----------
 .../CodeGen/MIR/X86/call-site-info-typeid.mir | 13 ++---
 .../CodeGen/Mips/call-site-info-typeid.ll     | 28 +++------
 .../test/CodeGen/X86/call-site-info-typeid.ll | 28 +++------
 7 files changed, 71 insertions(+), 127 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index bb0b87a3a04a3..44633df38a651 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -493,7 +493,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
     /// Callee type id.
     ConstantInt *TypeId = nullptr;
 
-    CallSiteInfo() {}
+    CallSiteInfo() = default;
 
     /// Extracts the numeric type id from the CallBase's type operand bundle,
     /// and sets TypeId. This is used as type id for the indirect call in the
@@ -503,12 +503,11 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
       if (!CB.isIndirectCall())
         return;
 
-      auto Opt = CB.getOperandBundle(LLVMContext::OB_type);
-      if (!Opt.has_value()) {
-        errs() << "warning: cannot find indirect call type operand bundle for  "
-                  "call graph section\n";
+      std::optional<OperandBundleUse> Opt =
+          CB.getOperandBundle(LLVMContext::OB_type);
+      // Return if the operand bundle for call graph section cannot be found.
+      if (!Opt.has_value())
         return;
-      }
 
       // Get generalized type id string
       auto OB = Opt.value();
@@ -520,9 +519,9 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
              "invalid type identifier");
 
       // Compute numeric type id from generalized type id string
-      uint64_t TypeIdVal = llvm::MD5Hash(TypeIdStr->getString());
+      uint64_t TypeIdVal = MD5Hash(TypeIdStr->getString());
       IntegerType *Int64Ty = Type::getInt64Ty(CB.getContext());
-      TypeId = llvm::ConstantInt::get(Int64Ty, TypeIdVal, /*IsSigned=*/false);
+      TypeId = ConstantInt::get(Int64Ty, TypeIdVal, /*IsSigned=*/false);
     }
   };
 
diff --git a/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll b/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
index f0a6b44755c5c..f3b98c2c7a395 100644
--- a/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
@@ -1,14 +1,9 @@
-; Tests that call site type ids can be extracted and set from type operand
-; bundles.
+;; Tests that call site type ids can be extracted and set from type operand
+;; bundles.
 
-; Verify the exact typeId value to ensure it is not garbage but the value
-; computed as the type id from the type operand bundle.
-; RUN: llc --call-graph-section -mtriple aarch64-linux-gnu %s -stop-before=finalize-isel -o - | FileCheck %s
-
-; ModuleID = 'test.c'
-source_filename = "test.c"
-target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
-target triple = "aarch64-unknown-linux-gnu"
+;; Verify the exact typeId value to ensure it is not garbage but the value
+;; computed as the type id from the type operand bundle.
+; RUN: llc --call-graph-section -mtriple aarch64-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
 
 define dso_local void @foo(i8 signext %a) !type !3 {
 entry:
@@ -19,10 +14,10 @@ entry:
 define dso_local i32 @main() !type !4 {
 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
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
   ; CHECK-NEXT: 7854600665770582568 }
@@ -30,10 +25,5 @@ entry:
   ret i32 0
 }
 
-!llvm.module.flags = !{!0, !1, !2}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 7, !"uwtable", i32 1}
-!2 = !{i32 7, !"frame-pointer", i32 2}
 !3 = !{i64 0, !"_ZTSFvcE.generalized"}
 !4 = !{i64 0, !"_ZTSFiE.generalized"}
diff --git a/llvm/test/CodeGen/ARM/call-site-info-typeid.ll b/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
index ec7f8a425051b..9feeef9a564cc 100644
--- a/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
@@ -1,14 +1,9 @@
-; Tests that call site type ids can be extracted and set from type operand
-; bundles.
+;; Tests that call site type ids can be extracted and set from type operand
+;; bundles.
 
-; Verify the exact typeId value to ensure it is not garbage but the value
-; computed as the type id from the type operand bundle.
-; RUN: llc --call-graph-section -mtriple arm-linux-gnu %s -stop-before=finalize-isel -o - | FileCheck %s
-
-; ModuleID = 'test.c'
-source_filename = "test.c"
-target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
-target triple = "armv4t-unknown-linux-gnu"
+;; Verify the exact typeId value to ensure it is not garbage but the value
+;; computed as the type id from the type operand bundle.
+; RUN: llc --call-graph-section -mtriple arm-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
 
 define dso_local void @foo(i8 signext %a) !type !3 {
 entry:
@@ -19,10 +14,10 @@ entry:
 define dso_local i32 @main() !type !4 {
 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
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
   ; CHECK-NEXT: 7854600665770582568 }
@@ -30,10 +25,5 @@ entry:
   ret i32 0
 }
 
-!llvm.module.flags = !{!0, !1, !2}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 7, !"uwtable", i32 1}
-!2 = !{i32 7, !"frame-pointer", i32 2}
 !3 = !{i64 0, !"_ZTSFvcE.generalized"}
 !4 = !{i64 0, !"_ZTSFiE.generalized"}
diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.ll b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.ll
index b769a721cac06..a8b2de8d8f8cf 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.ll
@@ -1,16 +1,16 @@
-; Test MIR printer and parser for type id field in call site info. Test that
-; it works well with/without --emit-call-site-info.
+;; Test MIR printer and parser for type id field in call site info. Test that
+;; it works well with/without --emit-call-site-info.
 
-; Multiplex --call-graph-section and -emit-call-site-info as both utilize
-; CallSiteInfo and callSites.
+;; Multiplex --call-graph-section and -emit-call-site-info as both utilize
+;; CallSiteInfo and callSites.
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Test printer and parser with --call-graph-section only.
 
-; Test printer.
-; Verify that fwdArgRegs is not set, typeId is set.
-; Verify the exact typeId value to ensure it is not garbage but the value
-; computed as the type id from the type operand bundle.
+;; Test printer.
+;; Verify that fwdArgRegs is not set, typeId is set.
+;; Verify the exact typeId value to ensure it is not garbage but the value
+;; computed as the type id from the type operand bundle.
 ; RUN: llc --call-graph-section %s -stop-before=finalize-isel -o %t1.mir
 ; RUN: cat %t1.mir | FileCheck %s --check-prefix=PRINTER_CGS
 ; PRINTER_CGS: name: main
@@ -19,8 +19,8 @@
 ; PRINTER_CGS-NEXT: 7854600665770582568 }
 
 
-; Test parser.
-; Verify that we get the same result.
+;; Test parser.
+;; Verify that we get the same result.
 ; RUN: llc --call-graph-section %t1.mir -run-pass=finalize-isel -o - \
 ; RUN: | FileCheck %s --check-prefix=PARSER_CGS
 ; PARSER_CGS: name: main
@@ -31,8 +31,8 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Test printer and parser with -emit-call-site-info only.
 
-; Test printer.
-; Verify that fwdArgRegs is set, typeId is not set.
+;; Test printer.
+;; Verify that fwdArgRegs is set, typeId is not set.
 ; RUN: llc -emit-call-site-info %s -stop-before=finalize-isel -o %t2.mir
 ; RUN: cat %t2.mir | FileCheck %s --check-prefix=PRINTER_CSI
 ; PRINTER_CSI: name: main
@@ -42,8 +42,8 @@
 ; PRINTER_CSI-NOT: typeId:
 
 
-; Test parser.
-; Verify that we get the same result.
+;; Test parser.
+;; Verify that we get the same result.
 ; RUN: llc -emit-call-site-info %t2.mir -run-pass=finalize-isel -o - \
 ; RUN: | FileCheck %s --check-prefix=PARSER_CSI
 ; PARSER_CSI: name: main
@@ -55,10 +55,10 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Test printer and parser with both -emit-call-site-info and --call-graph-section.
 
-; Test printer.
-; Verify both fwdArgRegs and typeId are set.
-; Verify the exact typeId value to ensure it is not garbage but the value
-; computed as the type id from the type operand bundle.
+;; Test printer.
+;; Verify both fwdArgRegs and typeId are set.
+;; Verify the exact typeId value to ensure it is not garbage but the value
+;; computed as the type id from the type operand bundle.
 ; RUN: llc --call-graph-section -emit-call-site-info %s -stop-before=finalize-isel -o %t2.mir
 ; RUN: cat %t2.mir | FileCheck %s --check-prefix=PRINTER_CGS_CSI
 ; PRINTER_CGS_CSI: name: main
@@ -68,8 +68,8 @@
 ; PRINTER_CGS_CSI-NEXT:   7854600665770582568 }
 
 
-; Test parser.
-; Verify that we get the same result.
+;; Test parser.
+;; Verify that we get the same result.
 ; RUN: llc --call-graph-section -emit-call-site-info %t2.mir -run-pass=finalize-isel -o - \
 ; RUN: | FileCheck %s --check-prefix=PARSER_CGS_CSI
 ; PARSER_CGS_CSI: name: main
@@ -80,11 +80,6 @@
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-; ModuleID = 'test.c'
-source_filename = "test.c"
-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"
-
 ; Function Attrs: noinline nounwind optnone uwtable
 define dso_local void @foo(i8 signext %a) !type !3 {
 entry:
@@ -95,18 +90,13 @@ entry:
 define dso_local i32 @main() !type !4 {
 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) [ "type"(metadata !"_ZTSFvcE.generalized") ]
   ret i32 0
 }
 
-!llvm.module.flags = !{!0, !1, !2}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 7, !"uwtable", i32 1}
-!2 = !{i32 7, !"frame-pointer", i32 2}
 !3 = !{i64 0, !"_ZTSFvcE.generalized"}
 !4 = !{i64 0, !"_ZTSFiE.generalized"}
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..dd21246e5dedc 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
   }
diff --git a/llvm/test/CodeGen/Mips/call-site-info-typeid.ll b/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
index 8596ebb5aa094..91de6a83524e5 100644
--- a/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
@@ -1,14 +1,9 @@
-; Tests that call site type ids can be extracted and set from type operand
-; bundles.
+;; Tests that call site type ids can be extracted and set from type operand
+;; bundles.
 
-; Verify the exact typeId value to ensure it is not garbage but the value
-; computed as the type id from the type operand bundle.
-; RUN: llc --call-graph-section -mtriple=mips-linux-gnu %s -stop-before=finalize-isel -o - | FileCheck %s
-
-; ModuleID = 'test.c'
-source_filename = "test.c"
-target datalayout = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"
-target triple = "mips-unknown-linux-gnu"
+;; Verify the exact typeId value to ensure it is not garbage but the value
+;; computed as the type id from the type operand bundle.
+; RUN: llc --call-graph-section -mtriple=mips-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
 
 define dso_local void @foo(i8 signext %a) !type !3 {
 entry:
@@ -19,10 +14,10 @@ entry:
 define dso_local i32 @main() !type !4 {
 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
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
   ; CHECK-NEXT: 7854600665770582568 }
@@ -30,10 +25,5 @@ entry:
   ret i32 0
 }
 
-!llvm.module.flags = !{!0, !1, !2}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 7, !"uwtable", i32 1}
-!2 = !{i32 7, !"frame-pointer", i32 2}
 !3 = !{i64 0, !"_ZTSFvcE.generalized"}
 !4 = !{i64 0, !"_ZTSFiE.generalized"}
diff --git a/llvm/test/CodeGen/X86/call-site-info-typeid.ll b/llvm/test/CodeGen/X86/call-site-info-typeid.ll
index 61777b770155d..6fbdce4f3c206 100644
--- a/llvm/test/CodeGen/X86/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/X86/call-site-info-typeid.ll
@@ -1,14 +1,9 @@
-; Tests that call site type ids can be extracted and set from type operand
-; bundles.
+;; Tests that call site type ids can be extracted and set from type operand
+;; bundles.
 
-; Verify the exact typeId value to ensure it is not garbage but the value
-; computed as the type id from the type operand bundle.
-; RUN: llc --call-graph-section -mtriple=x86_64-unknown-linux %s -stop-before=finalize-isel -o - | FileCheck %s
-
-; ModuleID = 'test.c'
-source_filename = "test.c"
-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"
+;; Verify the exact typeId value to ensure it is not garbage but the value
+;; computed as the type id from the type operand bundle.
+; RUN: llc --call-graph-section -mtriple=x86_64-unknown-linux < %s -stop-before=finalize-isel -o - | FileCheck %s
 
 define dso_local void @foo(i8 signext %a) !type !3 {
 entry:
@@ -19,10 +14,10 @@ entry:
 define dso_local i32 @main() !type !4 {
 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
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
   ; CHECK-NEXT: 7854600665770582568 }
@@ -30,10 +25,5 @@ entry:
   ret i32 0
 }
 
-!llvm.module.flags = !{!0, !1, !2}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 7, !"uwtable", i32 1}
-!2 = !{i32 7, !"frame-pointer", i32 2}
 !3 = !{i64 0, !"_ZTSFvcE.generalized"}
 !4 = !{i64 0, !"_ZTSFiE.generalized"}

>From bb9d7143c60aa28a35cd180aaeba5739fe3e3e7a Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Wed, 20 Nov 2024 11:52:58 -0800
Subject: [PATCH 05/38] =?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 746e03c4c5d049e067cef25854137c130c750551 Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Tue, 10 Dec 2024 14:54:55 -0800
Subject: [PATCH 06/38] =?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/CodeGen/MachineFunction.h |   4 +-
 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 +-
 15 files changed, 32 insertions(+), 434 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/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index 8b1075a1a7b69..c8eb4b0c958ae 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -496,7 +496,7 @@ class LLVM_ABI MachineFunction {
   GISelChangeObserver *Observer = nullptr;
 
   using CallSiteInfoMap = DenseMap<const MachineInstr *, CallSiteInfo>;
-  /// Map a call instruction to call site arguments forwarding and type id.
+  /// Map a call instruction to call site arguments forwarding info.
   CallSiteInfoMap CallSitesInfo;
 
   /// A helper function that returns call site info for a give call
@@ -1358,7 +1358,7 @@ class LLVM_ABI MachineFunction {
     });
   }
 
-  /// Start tracking the arguments passed to the call \p CallI and call type.
+  /// Start tracking the arguments passed to the call \p CallI.
   void addCallSiteInfo(const MachineInstr *CallI, CallSiteInfo &&CallInfo) {
     assert(CallI->isCandidateForCallSiteEntry());
     bool Inserted =
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 cfcb9c455f92871d2de378147fd5c1f2fccf9e54 Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Wed, 5 Feb 2025 23:07:19 +0000
Subject: [PATCH 07/38] =?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 80f879e029ebf571699e75e38d50bd46eb30f3b3 Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Tue, 11 Feb 2025 22:34:05 +0000
Subject: [PATCH 08/38] Update IR verifier.

Created using spr 1.3.6-beta.1
---
 llvm/lib/IR/Verifier.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 34c751e6357c6..e01a59908ad80 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3794,6 +3794,11 @@ void Verifier::visitCallBase(CallBase &Call) {
     } else if (Tag == LLVMContext::OB_callee_type) {
       Check(!FoundCalleeTypeBundle, "Multiple \"callee_type\" operand bundles",
             Call);
+      auto *OBVal = BU.Inputs.front().get();
+      auto *TypeIdMD = cast<MetadataAsValue>(OBVal)->getMetadata();
+      auto *TypeIdStr = cast<MDString>(TypeIdMD);
+      Check(TypeIdStr->getString().ends_with(".generalized"),
+            "Invalid \"callee_type\" type identifier", Call);
       FoundCalleeTypeBundle = true;
     }
   }

>From f769ce6ec291d40c3ac6b5adfdfce493654cc16b Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 13 Mar 2025 01:03:42 +0000
Subject: [PATCH 09/38] =?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]
---
 ...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 647db9afb949621669d4275aa914245fb19a8896 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 13 Mar 2025 01:21:29 +0000
Subject: [PATCH 10/38] =?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]
---
 .../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 5e97695febf5a8c00e680084ff5e1925f358de70 Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Thu, 13 Mar 2025 17:34:26 +0000
Subject: [PATCH 11/38] Remove unnecessary asserts. Remove autos for better
 readability.

Created using spr 1.3.6-beta.1
---
 llvm/include/llvm/CodeGen/MachineFunction.h     | 15 ++++++---------
 llvm/lib/IR/Verifier.cpp                        |  7 ++++---
 llvm/lib/Target/AArch64/AArch64ISelLowering.cpp |  2 +-
 llvm/lib/Target/ARM/ARMISelLowering.cpp         |  2 +-
 llvm/lib/Target/Mips/MipsISelLowering.cpp       |  2 +-
 5 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index cdbdd12ef54fc..ef8586dda1040 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -513,20 +513,17 @@ class LLVM_ABI MachineFunction {
       if (!CB.isIndirectCall())
         return;
 
-      std::optional<OperandBundleUse> Opt =
+      std::optional<OperandBundleUse> CalleeTypeOB =
           CB.getOperandBundle(LLVMContext::OB_callee_type);
       // Return if the operand bundle for call graph section cannot be found.
-      if (!Opt)
+      if (!CalleeTypeOB)
         return;
 
       // Get generalized type id string
-      auto OB = *Opt;
-      assert(OB.Inputs.size() == 1 && "invalid input size");
-      auto *OBVal = OB.Inputs.front().get();
-      auto *TypeIdMD = cast<MetadataAsValue>(OBVal)->getMetadata();
-      auto *TypeIdStr = cast<MDString>(TypeIdMD);
-      assert(TypeIdStr->getString().ends_with(".generalized") &&
-             "invalid type identifier");
+      Value *CalleeTypeOBVal = CalleeTypeOB->Inputs.front().get();
+      Metadata *TypeIdMD =
+          cast<MetadataAsValue>(CalleeTypeOBVal)->getMetadata();
+      MDString *TypeIdStr = cast<MDString>(TypeIdMD);
 
       // Compute numeric type id from generalized type id string
       uint64_t TypeIdVal = MD5Hash(TypeIdStr->getString());
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index e01a59908ad80..b0a34488909f8 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3794,9 +3794,10 @@ void Verifier::visitCallBase(CallBase &Call) {
     } else if (Tag == LLVMContext::OB_callee_type) {
       Check(!FoundCalleeTypeBundle, "Multiple \"callee_type\" operand bundles",
             Call);
-      auto *OBVal = BU.Inputs.front().get();
-      auto *TypeIdMD = cast<MetadataAsValue>(OBVal)->getMetadata();
-      auto *TypeIdStr = cast<MDString>(TypeIdMD);
+      Value *CalleeTypeOBVal = BU.Inputs.front().get();
+      Metadata *TypeIdMD =
+          cast<MetadataAsValue>(CalleeTypeOBVal)->getMetadata();
+      MDString *TypeIdStr = cast<MDString>(TypeIdMD);
       Check(TypeIdStr->getString().ends_with(".generalized"),
             "Invalid \"callee_type\" type identifier", Call);
       FoundCalleeTypeBundle = true;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 82b3543583f9b..6d6b279f41948 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -8915,7 +8915,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
   bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID &CallConv = CLI.CallConv;
   bool IsVarArg = CLI.IsVarArg;
-  const auto *CB = CLI.CB;
+  const CallBase *CB = CLI.CB;
 
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFunction::CallSiteInfo CSInfo;
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index d00d4443dfbfc..95853d9503b8b 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -2439,7 +2439,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   CallingConv::ID CallConv              = CLI.CallConv;
   bool doesNotRet                       = CLI.DoesNotReturn;
   bool isVarArg                         = CLI.IsVarArg;
-  const auto *CB = CLI.CB;
+  const CallBase *CB = CLI.CB;
 
   MachineFunction &MF = DAG.getMachineFunction();
   ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index ef9e4040d5717..2279870ebf955 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -3264,7 +3264,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   bool &IsTailCall                      = CLI.IsTailCall;
   CallingConv::ID CallConv              = CLI.CallConv;
   bool IsVarArg                         = CLI.IsVarArg;
-  const auto *CB = CLI.CB;
+  const CallBase *CB = CLI.CB;
 
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();

>From 1429f1dd47fe69300a99530c0e8ba1fa7c0478da Mon Sep 17 00:00:00 2001
From: Necip Fazil Yildiran <necip at google.com>
Date: Fri, 14 Mar 2025 04:10:20 +0000
Subject: [PATCH 12/38] Add RISC-V support. Clean up test files.

Created using spr 1.3.6-beta.1
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   | 13 ++++++++
 .../CodeGen/AArch64/call-site-info-typeid.ll  | 12 ++++----
 .../test/CodeGen/ARM/call-site-info-typeid.ll | 12 ++++----
 .../CodeGen/Mips/call-site-info-typeid.ll     | 12 ++++----
 .../CodeGen/RISCV/call-site-info-typeid.ll    | 30 +++++++++++++++++++
 .../test/CodeGen/X86/call-site-info-typeid.ll | 12 ++++----
 6 files changed, 67 insertions(+), 24 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/call-site-info-typeid.ll

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index ff44ff5249973..e21b2e615b223 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20845,8 +20845,14 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
   bool IsVarArg = CLI.IsVarArg;
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   MVT XLenVT = Subtarget.getXLenVT();
+  const CallBase *CB = CLI.CB;
 
   MachineFunction &MF = DAG.getMachineFunction();
+  MachineFunction::CallSiteInfo CSInfo;
+
+  // Set type id for call site info.
+  if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
+    CSInfo = MachineFunction::CallSiteInfo(*CB);
 
   // Analyze the operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
@@ -21104,6 +21110,9 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
     if (CLI.CFIType)
       Ret.getNode()->setCFIType(CLI.CFIType->getZExtValue());
     DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
+    if (MF.getTarget().Options.EmitCallGraphSection && CB &&
+        CB->isIndirectCall())
+      DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo));
     return Ret;
   }
 
@@ -21111,6 +21120,10 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
   Chain = DAG.getNode(CallOpc, DL, NodeTys, Ops);
   if (CLI.CFIType)
     Chain.getNode()->setCFIType(CLI.CFIType->getZExtValue());
+
+  if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
+    DAG.addCallSiteInfo(Chain.getNode(), std::move(CSInfo));
+
   DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
   Glue = Chain.getValue(1);
 
diff --git a/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll b/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
index b0d4855c72997..1bad6c25dc39a 100644
--- a/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
@@ -5,25 +5,25 @@
 ;; computed as the type id from the type operand bundle.
 ; RUN: llc --call-graph-section -mtriple aarch64-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
 
-define dso_local void @foo(i8 signext %a) !type !3 {
+define dso_local void @foo(i8 signext %a) !type !0 {
 entry:
   ret void
 }
 
 ; CHECK: name: main
-define dso_local i32 @main() !type !4 {
+define dso_local i32 @main() !type !1 {
 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
-  %0 = load ptr, ptr %fp, align 8
+  %fp_val = load ptr, ptr %fp, align 8
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
   ; CHECK-NEXT: 7854600665770582568 }
-  call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
+  call void %fp_val(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
   ret i32 0
 }
 
-!3 = !{i64 0, !"_ZTSFvcE.generalized"}
-!4 = !{i64 0, !"_ZTSFiE.generalized"}
+!0 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{i64 0, !"_ZTSFiE.generalized"}
diff --git a/llvm/test/CodeGen/ARM/call-site-info-typeid.ll b/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
index 7eb5c3e434fd5..4af6f25c7622a 100644
--- a/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
@@ -5,25 +5,25 @@
 ;; computed as the type id from the type operand bundle.
 ; RUN: llc --call-graph-section -mtriple arm-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
 
-define dso_local void @foo(i8 signext %a) !type !3 {
+define dso_local void @foo(i8 signext %a) !type !0 {
 entry:
   ret void
 }
 
 ; CHECK: name: main
-define dso_local i32 @main() !type !4 {
+define dso_local i32 @main() !type !1 {
 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
-  %0 = load ptr, ptr %fp, align 8
+  %fp_val = load ptr, ptr %fp, align 8
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
   ; CHECK-NEXT: 7854600665770582568 }
-  call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
+  call void %fp_val(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
   ret i32 0
 }
 
-!3 = !{i64 0, !"_ZTSFvcE.generalized"}
-!4 = !{i64 0, !"_ZTSFiE.generalized"}
+!0 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{i64 0, !"_ZTSFiE.generalized"}
diff --git a/llvm/test/CodeGen/Mips/call-site-info-typeid.ll b/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
index 74faa774d78de..05b7fb022eb34 100644
--- a/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
@@ -5,25 +5,25 @@
 ;; computed as the type id from the type operand bundle.
 ; RUN: llc --call-graph-section -mtriple=mips-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
 
-define dso_local void @foo(i8 signext %a) !type !3 {
+define dso_local void @foo(i8 signext %a) !type !0 {
 entry:
   ret void
 }
 
 ; CHECK: name: main
-define dso_local i32 @main() !type !4 {
+define dso_local i32 @main() !type !1 {
 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
-  %0 = load ptr, ptr %fp, align 8
+  %fp_val = load ptr, ptr %fp, align 8
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
   ; CHECK-NEXT: 7854600665770582568 }
-  call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
+  call void %fp_val(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
   ret i32 0
 }
 
-!3 = !{i64 0, !"_ZTSFvcE.generalized"}
-!4 = !{i64 0, !"_ZTSFiE.generalized"}
+!0 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{i64 0, !"_ZTSFiE.generalized"}
diff --git a/llvm/test/CodeGen/RISCV/call-site-info-typeid.ll b/llvm/test/CodeGen/RISCV/call-site-info-typeid.ll
new file mode 100644
index 0000000000000..e0dac6b40a41f
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/call-site-info-typeid.ll
@@ -0,0 +1,30 @@
+;; Tests that call site type ids can be extracted and set from type operand
+;; bundles.
+
+;; Verify the exact typeId value to ensure it is not garbage but the value
+;; computed as the type id from the type operand bundle.
+; RUN: llc --call-graph-section -mtriple riscv64 < %s -stop-before=finalize-isel -o - | FileCheck %s
+; RUN: llc --call-graph-section -mtriple riscv32 < %s -stop-before=finalize-isel -o - | FileCheck %s
+
+define dso_local void @foo(i8 signext %a) !type !0 {
+entry:
+  ret void
+}
+
+; CHECK: name: main
+define dso_local i32 @main() !type !1 {
+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
+  ; CHECK: callSites:
+  ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
+  ; CHECK-NEXT: 7854600665770582568 }
+  call void %fp_val(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
+  ret i32 0
+}
+
+!0 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{i64 0, !"_ZTSFiE.generalized"}
diff --git a/llvm/test/CodeGen/X86/call-site-info-typeid.ll b/llvm/test/CodeGen/X86/call-site-info-typeid.ll
index 0463bf8627853..57d4bc78275d3 100644
--- a/llvm/test/CodeGen/X86/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/X86/call-site-info-typeid.ll
@@ -5,25 +5,25 @@
 ;; computed as the type id from the type operand bundle.
 ; RUN: llc --call-graph-section -mtriple=x86_64-unknown-linux < %s -stop-before=finalize-isel -o - | FileCheck %s
 
-define dso_local void @foo(i8 signext %a) !type !3 {
+define dso_local void @foo(i8 signext %a) !type !0 {
 entry:
   ret void
 }
 
 ; CHECK: name: main
-define dso_local i32 @main() !type !4 {
+define dso_local i32 @main() !type !1 {
 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
-  %0 = load ptr, ptr %fp, align 8
+  %fp_val = load ptr, ptr %fp, align 8
   ; CHECK: callSites:
   ; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
   ; CHECK-NEXT: 7854600665770582568 }
-  call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
+  call void %fp_val(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
   ret i32 0
 }
 
-!3 = !{i64 0, !"_ZTSFvcE.generalized"}
-!4 = !{i64 0, !"_ZTSFiE.generalized"}
+!0 = !{i64 0, !"_ZTSFvcE.generalized"}
+!1 = !{i64 0, !"_ZTSFiE.generalized"}

>From 306e08bce8c65e8d82b556f42a8d4012339c43ff Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Sat, 15 Mar 2025 01:09:47 +0000
Subject: [PATCH 13/38] =?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]
---
 ...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 9a631483a58ed41d90d991074481785f4b625610 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 19 Mar 2025 02:54:14 +0000
Subject: [PATCH 14/38] =?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/MIRYamlMapping.h    |  4 +-
 llvm/include/llvm/CodeGen/MachineFunction.h   |  2 +-
 llvm/lib/CodeGen/MIRParser/MIRParser.cpp      | 10 ++--
 llvm/lib/CodeGen/MIRPrinter.cpp               |  4 +-
 ...te-info-ambiguous-indirect-call-typeid.mir | 48 +++----------------
 .../call-site-info-direct-calls-typeid.mir    | 28 ++---------
 .../CodeGen/MIR/X86/call-site-info-typeid.mir | 11 ++---
 llvm/test/Verifier/operand-bundles.ll         |  6 +--
 8 files changed, 28 insertions(+), 85 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index 93dcc4e09918d..0bc31e6ba084e 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -485,7 +485,7 @@ struct CallSiteInfo {
 
   /// Numeric callee type identifier used for call graph section.
   using TypeIdTy = std::optional<uint64_t>;
-  TypeIdTy TypeId;
+  TypeIdTy CalleeTypeId;
 
   bool operator==(const CallSiteInfo &Other) const {
     return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
@@ -515,7 +515,7 @@ template <> struct MappingTraits<CallSiteInfo> {
     YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
     YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
                        std::vector<CallSiteInfo::ArgRegPair>());
-    YamlIO.mapOptional("typeId", CSInfo.TypeId);
+    YamlIO.mapOptional("calleeTypeId", CSInfo.CalleeTypeId);
   }
 
   static const bool flow = true;
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index 692ce1e23d059..164cfa93b6a7a 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -498,7 +498,7 @@ class LLVM_ABI MachineFunction {
     SmallVector<ArgRegPair, 1> ArgRegPairs;
 
     /// Callee type id.
-    ConstantInt *TypeId = nullptr;
+    ConstantInt *CalleeTypeId = nullptr;
   };
 
   struct CalledGlobalInfo {
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index dbd75a8b9e7c4..e7a0444daa519 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -504,19 +504,19 @@ bool MIRParserImpl::initializeCallSiteInfo(
         return error(Error, ArgRegPair.Reg.SourceRange);
       CSInfo.ArgRegPairs.emplace_back(Reg, ArgRegPair.ArgNo);
     }
-    if (YamlCSInfo.TypeId.has_value()) {
+    if (YamlCSInfo.CalleeTypeId) {
       IntegerType *Int64Ty = Type::getInt64Ty(Context);
-      CSInfo.TypeId = ConstantInt::get(Int64Ty, YamlCSInfo.TypeId.value(),
-                                       /*isSigned=*/false);
+      CSInfo.CalleeTypeId = ConstantInt::get(Int64Ty, *YamlCSInfo.CalleeTypeId,
+                                             /*isSigned=*/false);
     }
 
     if (TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection)
       MF.addCallSiteInfo(&*CallI, std::move(CSInfo));
   }
 
-  if (YamlMF.CallSitesInfo.size() &&
+  if (!YamlMF.CallSitesInfo.empty() &&
       !(TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection))
-    return error(Twine("Call site info provided but not used"));
+    return error(Twine("call site info provided but not used"));
   return false;
 }
 
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 9bc6c7fd1e21b..90d130c150d7d 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -577,8 +577,8 @@ void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF,
       YmlCS.ArgForwardingRegs.emplace_back(YmlArgReg);
     }
     // Get type id.
-    if (CSInfo.second.TypeId)
-      YmlCS.TypeId = CSInfo.second.TypeId->getZExtValue();
+    if (CSInfo.second.CalleeTypeId)
+      YmlCS.CalleeTypeId = CSInfo.second.CalleeTypeId->getZExtValue();
     YMF.CallSitesInfo.push_back(std::move(YmlCS));
   }
 
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 18aad1813339a..afc4701a09803 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,54 +1,20 @@
 # 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.
+# for propagating 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: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeId:
 # CHECK-NEXT: 1234567890 }
 
 --- |  
-  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
-    %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
-  }
-  
-  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
-    %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
-  }
   
-  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
-    %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
+  declare !type !0 noundef i32 @_Z3addii(i32 noundef, i32 noundef)
+
+  declare !type !0 noundef i32 @_Z8multiplyii(i32 noundef, i32 noundef)
   
-  cond.end:                                         ; preds = %cond.false, %entry
-    %cond = phi ptr [ @_Z8multiplyii, %cond.false ], [ @_Z3addii, %entry ]
-    ret ptr %cond
-  }
+  declare !type !1 noundef ptr @_Z13get_operationb(i1 noundef zeroext %is_addition)
   
   define dso_local noundef i32 @main(i32 noundef %argc) !type !2 !type !2 {
   entry:
@@ -82,7 +48,7 @@
 name:            main
 callSites:
   - { bb: 0, offset: 0, fwdArgRegs: [] }
-  - { bb: 0, offset: 2, fwdArgRegs: [], typeId: 
+  - { bb: 0, offset: 2, fwdArgRegs: [], calleeTypeId: 
     1234567890 }
 body:             |
   bb.0.entry:
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 c94b20138da55..c02dfd5233eac 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,9 +1,9 @@
 # Test MIR printer and parser to NOT have `typeId` field in callSites.
-# `typeId` is used for propogating call site type identifiers for
+# `typeId` is used for propagating 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:
+# CHECK-NOT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeId:
 # CHECK: name: _Z3barii
 # CHECK: callSites:
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
@@ -13,29 +13,9 @@
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
 
 --- |  
-  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
-    %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
-  }
+  declare !type !0 noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y)
   
-  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
-    %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
-  }
+  declare !type !0 noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y)
   
   define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) !type !0 !type !0 {
   entry:
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 9342c3a70ed40..608849570e836 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -1,17 +1,14 @@
 # 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.
+# for propagating 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: [], typeId:
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeId:
 # CHECK-NEXT: 123456789 }
 
 --- |
-  define dso_local void @foo(i8 signext %a) {
-  entry:
-    ret void
-  }
+  declare void @foo(i8 signext %a)
   
   define dso_local i32 @main() {
   entry:
@@ -28,7 +25,7 @@
 ---
 name:            main
 callSites:
-  - { bb: 0, offset: 1, fwdArgRegs: [], typeId: 
+  - { bb: 0, offset: 1, fwdArgRegs: [], calleeTypeId: 
     123456789 }
 body:             |
   bb.0.entry:    
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 4a45618f608b3f01f476de8bcfa488e832bd7cf5 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Sat, 19 Apr 2025 02:16:46 +0000
Subject: [PATCH 15/38] =?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/MIRYamlMapping.h    |  8 +++----
 llvm/include/llvm/CodeGen/MachineFunction.h   |  5 ++---
 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 +++++++++++++++++++
 llvm/lib/CodeGen/MIRParser/MIRParser.cpp      | 10 +++++----
 llvm/lib/CodeGen/MIRPrinter.cpp               |  7 ++++---
 .../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 ++---
 ...te-info-ambiguous-indirect-call-typeid.mir | 15 ++++++-------
 .../call-site-info-direct-calls-typeid.mir    | 20 +++++++++---------
 .../CodeGen/MIR/X86/call-site-info-typeid.mir |  8 +++----
 llvm/test/Verifier/operand-bundles.ll         | 13 ------------
 17 files changed, 76 insertions(+), 71 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index 0bc31e6ba084e..c920505f0fc05 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -482,10 +482,8 @@ struct CallSiteInfo {
 
   MachineInstrLoc CallLocation;
   std::vector<ArgRegPair> ArgForwardingRegs;
-
-  /// Numeric callee type identifier used for call graph section.
-  using TypeIdTy = std::optional<uint64_t>;
-  TypeIdTy CalleeTypeId;
+  /// Numeric callee type identifiers for the callgraph section.
+  std::vector<uint64_t> CalleeTypeIds;
 
   bool operator==(const CallSiteInfo &Other) const {
     return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
@@ -515,7 +513,7 @@ template <> struct MappingTraits<CallSiteInfo> {
     YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
     YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
                        std::vector<CallSiteInfo::ArgRegPair>());
-    YamlIO.mapOptional("calleeTypeId", CSInfo.CalleeTypeId);
+    YamlIO.mapOptional("calleeTypeIds", CSInfo.CalleeTypeIds);
   }
 
   static const bool flow = true;
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index 164cfa93b6a7a..7f8dbf67ed1db 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -496,9 +496,8 @@ class LLVM_ABI MachineFunction {
   struct CallSiteInfo {
     /// Vector of call argument and its forwarding register.
     SmallVector<ArgRegPair, 1> ArgRegPairs;
-
-    /// Callee type id.
-    ConstantInt *CalleeTypeId = nullptr;
+    /// Callee type ids.
+    SmallVector<ConstantInt *, 4> CalleeTypeIds;
   };
 
   struct CalledGlobalInfo {
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/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index e7a0444daa519..0bee797f53331 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -504,10 +504,12 @@ bool MIRParserImpl::initializeCallSiteInfo(
         return error(Error, ArgRegPair.Reg.SourceRange);
       CSInfo.ArgRegPairs.emplace_back(Reg, ArgRegPair.ArgNo);
     }
-    if (YamlCSInfo.CalleeTypeId) {
-      IntegerType *Int64Ty = Type::getInt64Ty(Context);
-      CSInfo.CalleeTypeId = ConstantInt::get(Int64Ty, *YamlCSInfo.CalleeTypeId,
-                                             /*isSigned=*/false);
+    if (!YamlCSInfo.CalleeTypeIds.empty()) {
+      for (auto CalleeTypeId : YamlCSInfo.CalleeTypeIds) {
+        IntegerType *Int64Ty = Type::getInt64Ty(Context);
+        CSInfo.CalleeTypeIds.push_back(ConstantInt::get(Int64Ty, CalleeTypeId,
+                                                        /*isSigned=*/false));
+      }
     }
 
     if (TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection)
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 90d130c150d7d..ef0a4ccccd4cd 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -576,9 +576,10 @@ void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF,
       printRegMIR(ArgReg.Reg, YmlArgReg.Reg, TRI);
       YmlCS.ArgForwardingRegs.emplace_back(YmlArgReg);
     }
-    // Get type id.
-    if (CSInfo.second.CalleeTypeId)
-      YmlCS.CalleeTypeId = CSInfo.second.CalleeTypeId->getZExtValue();
+    // Get type ids.
+    for (auto *CalleeTypeId : CSInfo.second.CalleeTypeIds) {
+      YmlCS.CalleeTypeIds.push_back(CalleeTypeId->getZExtValue());
+    }
     YMF.CallSitesInfo.push_back(std::move(YmlCS));
   }
 
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/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 afc4701a09803..a7073cb1ca5f0 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
@@ -5,8 +5,8 @@
 # CHECK: name: main
 # CHECK: callSites:
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
-# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeId:
-# CHECK-NEXT: 1234567890 }
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
+# CHECK-NEXT: [ 1234567890 ] }
 
 --- |  
   
@@ -16,7 +16,7 @@
   
   declare !type !1 noundef ptr @_Z13get_operationb(i1 noundef zeroext %is_addition)
   
-  define dso_local noundef i32 @main(i32 noundef %argc) !type !2 !type !2 {
+  define dso_local noundef i32 @main(i32 noundef %argc) !type !2 {
   entry:
     %retval = alloca i32, align 4
     %argc.addr = alloca i32, align 4
@@ -30,26 +30,27 @@
     %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") ]
+    %call = call noundef ptr @_Z13get_operationb(i1 noundef 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"(metadata !"_ZTSFiiiE.generalized") ]
+    %call1 = call noundef i32 %op_val(i32 noundef %x_val, i32 noundef %y_val), !callee_type !3
     ret i32 %call1
   }
   
   !0 = !{i64 0, !"_ZTSFiiiE.generalized"}
   !1 = !{i64 0, !"_ZTSFPvbE.generalized"}
   !2 = !{i64 0, !"_ZTSFiiE.generalized"}
+  !3 = !{!0}
 
 ...
 ---
 name:            main
 callSites:
   - { bb: 0, offset: 0, fwdArgRegs: [] }
-  - { bb: 0, offset: 2, fwdArgRegs: [], calleeTypeId: 
-    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-direct-calls-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
index c02dfd5233eac..147d265eaac52 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,9 +1,9 @@
-# Test MIR printer and parser to NOT have `typeId` field in callSites.
-# `typeId` is used for propagating call site type identifiers for
+# Test MIR printer and parser to NOT have `CalleeTypeIds` field in callSites.
+# `CalleeTypeId` is used for propagating 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: [], calleeTypeId:
+# CHECK-NOT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
 # CHECK: name: _Z3barii
 # CHECK: callSites:
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
@@ -13,11 +13,11 @@
 # CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: []
 
 --- |  
-  declare !type !0 noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y)
+  declare noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y)
   
-  declare !type !0 noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y)
+  declare noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y)
   
-  define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) !type !0 !type !0 {
+  define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) {
   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) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %call = call noundef i32 @_Z4buzzii(i32 noundef %x_val, i32 noundef %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) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %call1 = call noundef i32 @_Z4fizzii(i32 noundef %x_val_2, i32 noundef %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 !type !0 {
+  define dso_local noundef i32 @_Z3fooii(i32 noundef %x, i32 noundef %y) {
   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) [ "callee_type"(metadata !"_ZTSFiiiE.generalized") ]
+    %call = call noundef i32 @_Z3barii(i32 noundef %x_val, i32 noundef %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 608849570e836..e2f212e52d176 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir
@@ -4,8 +4,8 @@
 # RUN: llc --call-graph-section %s -run-pass=none -o - | FileCheck %s
 # CHECK: name: main
 # CHECK: callSites:
-# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeId:
-# CHECK-NEXT: 123456789 }
+# CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
+# CHECK-NEXT: [ 123456789 ] }
 
 --- |
   declare void @foo(i8 signext %a)
@@ -25,8 +25,8 @@
 ---
 name:            main
 callSites:
-  - { bb: 0, offset: 1, fwdArgRegs: [], calleeTypeId: 
-    123456789 }
+  - { bb: 0, offset: 1, fwdArgRegs: [], calleeTypeIds: 
+    [ 123456789 ] }
 body:             |
   bb.0.entry:    
     %0:gr64 = MOV32ri64 @foo    
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 3eee130e6367b8eaa8a9c5098b56ad0cdd9e307f Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Sat, 19 Apr 2025 03:07:19 +0000
Subject: [PATCH 16/38] Address review comments.

Created using spr 1.3.6-beta.1
---
 .../CodeGen/AArch64/call-site-info-typeid.ll     |  2 +-
 llvm/test/CodeGen/ARM/call-site-info-typeid.ll   |  2 +-
 .../CodeGen/MIR/X86/call-site-info-typeid.ll     | 16 ++++++++--------
 llvm/test/CodeGen/Mips/call-site-info-typeid.ll  |  2 +-
 llvm/test/CodeGen/RISCV/call-site-info-typeid.ll |  6 +++---
 llvm/test/CodeGen/X86/call-site-info-typeid.ll   |  4 ++--
 6 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll b/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
index e72ba58328f51..48cf7268d5215 100644
--- a/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/AArch64/call-site-info-typeid.ll
@@ -3,7 +3,7 @@
 
 ;; Verify the exact calleeTypeId value to ensure it is not garbage but the value
 ;; computed as the type id from the callee_type metadata.
-; RUN: llc --call-graph-section -mtriple aarch64-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
+; RUN: llc --call-graph-section -mtriple aarch64-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck %s
 
 declare !type !0 void @foo(i8 signext %a)
 
diff --git a/llvm/test/CodeGen/ARM/call-site-info-typeid.ll b/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
index aebcf918eb1bc..0aadcdb46a4a4 100644
--- a/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/ARM/call-site-info-typeid.ll
@@ -3,7 +3,7 @@
 
 ;; Verify the exact calleeTypeId value to ensure it is not garbage but the value
 ;; computed as the type id from the callee_type metadata.
-; RUN: llc --call-graph-section -mtriple arm-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
+; RUN: llc --call-graph-section -mtriple arm-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck %s
 
 declare !type !0 void @foo(i8 signext %a)
 
diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.ll b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.ll
index fed4fc81c88b0..4823d2212df1a 100644
--- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.ll
@@ -11,7 +11,7 @@
 ;; Verify that fwdArgRegs is not set, calleeTypeIds is set.
 ;; Verify the exact calleeTypeIds value to ensure it is not garbage but the value
 ;; computed as the type id from the callee_type metadata.
-; RUN: llc --call-graph-section %s -stop-before=finalize-isel -o %t1.mir
+; RUN: llc --call-graph-section %s -stop-after=finalize-isel -o %t1.mir
 ; RUN: cat %t1.mir | FileCheck %s --check-prefix=PRINTER_CGS
 ; PRINTER_CGS: name: main
 ; PRINTER_CGS: callSites:
@@ -32,8 +32,8 @@
 ;; Test printer and parser with -emit-call-site-info only.
 
 ;; Test printer.
-;; Verify that fwdArgRegs is set, calleeTypeId is not set.
-; RUN: llc -emit-call-site-info %s -stop-before=finalize-isel -o %t2.mir
+;; Verify that fwdArgRegs is set, calleeTypeIds is not set.
+; RUN: llc -emit-call-site-info %s -stop-after=finalize-isel -o %t2.mir
 ; RUN: cat %t2.mir | FileCheck %s --check-prefix=PRINTER_CSI
 ; PRINTER_CSI: name: main
 ; PRINTER_CSI: callSites:
@@ -56,10 +56,10 @@
 ;; Test printer and parser with both -emit-call-site-info and --call-graph-section.
 
 ;; Test printer.
-;; Verify both fwdArgRegs and calleeTypeId are set.
-;; Verify the exact calleeTypeId value to ensure it is not garbage but the value
+;; Verify both fwdArgRegs and calleeTypeIds are set.
+;; Verify the exact calleeTypeIds value to ensure it is not garbage but the value
 ;; computed as the type id from the callee_type metadata.
-; RUN: llc --call-graph-section -emit-call-site-info %s -stop-before=finalize-isel -o %t2.mir
+; RUN: llc --call-graph-section -emit-call-site-info %s -stop-after=finalize-isel -o %t2.mir
 ; RUN: cat %t2.mir | FileCheck %s --check-prefix=PRINTER_CGS_CSI
 ; PRINTER_CGS_CSI: name: main
 ; PRINTER_CGS_CSI: callSites:
@@ -93,8 +93,8 @@ entry:
   %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), !callee_type !5
+  %fp_val = load ptr, ptr %fp, align 8
+  call void %fp_val(i8 signext 97), !callee_type !5
   ret i32 0
 }
 
diff --git a/llvm/test/CodeGen/Mips/call-site-info-typeid.ll b/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
index 826be8121d183..a6d1969136a85 100644
--- a/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/Mips/call-site-info-typeid.ll
@@ -3,7 +3,7 @@
 
 ;; Verify the exact calleeTypeId value to ensure it is not garbage but the value
 ;; computed as the type id from the callee_type metadata.
-; RUN: llc --call-graph-section -mtriple=mips-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
+; RUN: llc --call-graph-section -mtriple=mips-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck %s
 
 declare !type !0 void @foo(i8 signext %a)
 
diff --git a/llvm/test/CodeGen/RISCV/call-site-info-typeid.ll b/llvm/test/CodeGen/RISCV/call-site-info-typeid.ll
index 10fdd15547ec0..46cc0eaebbcee 100644
--- a/llvm/test/CodeGen/RISCV/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/RISCV/call-site-info-typeid.ll
@@ -1,10 +1,10 @@
 ;; Tests that call site callee type ids can be extracted and set from
 ;; callee_type metadata.
 
-;; Verify the exact calleeTypeId value to ensure it is not garbage but the value
+;; Verify the exact calleeTypeIds value to ensure it is not garbage but the value
 ;; computed as the type id from the callee_type operand bundle.
-; RUN: llc --call-graph-section -mtriple riscv64 < %s -stop-before=finalize-isel -o - | FileCheck %s
-; RUN: llc --call-graph-section -mtriple riscv32 < %s -stop-before=finalize-isel -o - | FileCheck %s
+; RUN: llc --call-graph-section -mtriple riscv64 < %s -stop-after=finalize-isel -o - | FileCheck %s
+; RUN: llc --call-graph-section -mtriple riscv32 < %s -stop-after=finalize-isel -o - | FileCheck %s
 
 declare !type !0 void @foo(i8 signext %a)
 
diff --git a/llvm/test/CodeGen/X86/call-site-info-typeid.ll b/llvm/test/CodeGen/X86/call-site-info-typeid.ll
index c785cd636732a..6f0890de3ed37 100644
--- a/llvm/test/CodeGen/X86/call-site-info-typeid.ll
+++ b/llvm/test/CodeGen/X86/call-site-info-typeid.ll
@@ -1,9 +1,9 @@
 ;; Tests that call site callee type ids can be extracted and set from
 ;; callee_type metadata.
 
-;; Verify the exact calleeTypeId value to ensure it is not garbage but the value
+;; Verify the exact calleeTypeIds value to ensure it is not garbage but the value
 ;; computed as the type id from the callee_type metadata.
-; RUN: llc --call-graph-section -mtriple=x86_64-unknown-linux < %s -stop-before=finalize-isel -o - | FileCheck %s
+; RUN: llc --call-graph-section -mtriple=x86_64-unknown-linux < %s -stop-after=finalize-isel -o - | FileCheck %s
 
 declare !type !0 void @foo(i8 signext %a)
 

>From 9ceb54cb69142bdce14cfb91aa2312bd71557eb4 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 23 Apr 2025 01:02:06 +0000
Subject: [PATCH 17/38] =?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 ++++
 .../call-site-info-direct-calls-typeid.mir    | 12 ++++-----
 .../InstCombine/callee-type-metadata.ll       | 25 +++++++++++++++++++
 3 files changed, 36 insertions(+), 6 deletions(-)
 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/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-direct-calls-typeid.mir
index 147d265eaac52..4c1007da3095d 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 noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y)
-  
-  declare noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y)
-  
-  define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) {
+  declare !type !0 noundef i32 @_Z4fizzii(i32 noundef %x, i32 noundef %y)
+
+  declare !type !0 noundef i32 @_Z4buzzii(i32 noundef %x, i32 noundef %y)
+
+  define dso_local noundef i32 @_Z3barii(i32 noundef %x, i32 noundef %y) !type !0 {
   entry:
     %x.addr = alloca i32, align 4
     %y.addr = alloca i32, align 4
@@ -33,7 +33,7 @@
     ret i32 %sub
   }
   
-  define dso_local noundef i32 @_Z3fooii(i32 noundef %x, i32 noundef %y) {
+  define dso_local noundef i32 @_Z3fooii(i32 noundef %x, i32 noundef %y) !type !0 {
   entry:
     %x.addr = alloca i32, align 4
     %y.addr = alloca i32, align 4
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 175b5f165671344daa75dca805dc90b8f6ea8c00 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 23 Apr 2025 03:52:23 +0000
Subject: [PATCH 18/38] =?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 721cb8b0a09f7c084778ce9b9cf844a3783c7169 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 23 Apr 2025 23:39:13 +0000
Subject: [PATCH 19/38] =?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 7a32b7ec1f0aa637d1ff51e7c1b7f8dcb50d7d0d Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 24 Apr 2025 02:24:49 +0000
Subject: [PATCH 20/38] =?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/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 484ad23e3e24628d7d24eeb7f9e64e12b635482e Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 24 Apr 2025 20:39:32 +0000
Subject: [PATCH 21/38] =?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]
---
 .../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 11b6b2fb495f06d2d941f1d778908212fcf55d6c Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Thu, 24 Apr 2025 23:50:27 +0000
Subject: [PATCH 22/38] =?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/CodeGen/MIRPrinter.cpp            |  7 +++---
 llvm/lib/IR/Verifier.cpp                   |  5 +++-
 llvm/test/Verifier/callee-type-metadata.ll | 28 ++++++++++++++++++++++
 3 files changed, 35 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/Verifier/callee-type-metadata.ll

diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index e9fe4ab09c9bd..93c77cfefaec0 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -558,20 +558,19 @@ void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF,
                                         const MachineFunction &MF,
                                         ModuleSlotTracker &MST) {
   const auto *TRI = MF.getSubtarget().getRegisterInfo();
-  for (auto CSInfoMap : MF.getCallSitesInfo()) {
+  for (auto [MI, CallSiteInfo] : MF.getCallSitesInfo()) {
     yaml::CallSiteInfo YmlCS;
     yaml::MachineInstrLoc CallLocation;
 
     // Prepare instruction position.
-    MachineBasicBlock::const_instr_iterator CallI =
-        CSInfoMap.first->getIterator();
+    MachineBasicBlock::const_instr_iterator CallI = MI->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;
+    auto [ArgRegPairs, CalleeTypeIds] = CallSiteInfo;
     // Construct call arguments and theirs forwarding register info.
     for (auto ArgReg : ArgRegPairs) {
       yaml::CallSiteInfo::ArgRegPair YmlArgReg;
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 dd2c0b8aa20eb336536f41bb359c9a51411b8f66 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Mon, 28 Apr 2025 22:48:48 +0000
Subject: [PATCH 23/38] =?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 35ef409aa23676c0eae5e064107f93f4d8d289cc Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Mon, 5 May 2025 23:13:05 +0000
Subject: [PATCH 24/38] =?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 07b7f6ca0d9025a8f97f0921d8de3a3bdc0b4b12 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Sat, 10 May 2025 00:33:07 +0000
Subject: [PATCH 25/38] =?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 d7e68436d35bbf33417fc2c90ebf73f55c55c2ac Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 13 May 2025 17:24:46 +0000
Subject: [PATCH 26/38] =?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/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 29cc917039edc4f2c412110fd297601936833370 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 13 May 2025 20:49:50 +0000
Subject: [PATCH 27/38] Test direct call sites.

Created using spr 1.3.6-beta.1
---
 .../calleetypeid-directcall-mismatched.ll     | 42 ++++++++++++++++++
 .../ARM/calleetypeid-directcall-mismatched.ll | 42 ++++++++++++++++++
 .../calleetypeid-directcall-mismatched.ll     | 42 ++++++++++++++++++
 .../calleetypeid-directcall-mismatched.ll     | 43 +++++++++++++++++++
 .../X86/calleetypeid-directcall-mismatched.ll | 42 ++++++++++++++++++
 5 files changed, 211 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
 create mode 100644 llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
 create mode 100644 llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
 create mode 100644 llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
 create mode 100644 llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll

diff --git a/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
new file mode 100644
index 0000000000000..8f882362d30f9
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
@@ -0,0 +1,42 @@
+;; Tests that callee_type metadata attached to direct call sites are safely ignored.
+
+; RUN: llc --call-graph-section -mtriple aarch64-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck %s
+
+; Function Attrs: mustprogress noinline optnone uwtable
+define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
+entry:
+  ; CHECK: callSites:
+  ; CHECK-NOT: calleeTypeIds:  
+  %x.addr = alloca i32, align 4
+  %y.addr = alloca i32, align 4
+  %z.addr = alloca i32, align 4
+  store i32 %x, ptr %x.addr, align 4
+  store i32 %y, ptr %y.addr, align 4
+  store i32 %z, ptr %z.addr, align 4
+  %zval = load i32, ptr %z.addr, align 4
+  %yval = load i32, ptr %y.addr, align 4    
+  ;; This direct call has a callee_type metadata node which matches the
+  ;; callee type accurately.
+  %call = call i32 @_Z4fizzii(i32 %zval, i32 %yval), !callee_type !0
+  %xval = load i32, ptr %x.addr, align 4
+  %yval2 = load i32, ptr %y.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call1 = call i32 @_Z4fizzii(i32 %xval, i32 %yval2), !callee_type !1
+  %add = add nsw i32 %call, %call1
+  %xval2 = load i32, ptr %x.addr, align 4
+  %zval2 = load i32, ptr %z.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call2 = call i32 @_Z4fizzii(i32 %xval2, i32 %zval2), !callee_type !1
+  %sub = sub nsw i32 %add, %call2
+  ret i32 %sub
+}
+
+declare !type !4 i32 @_Z4fizzii(i32, i32)
+
+!0 = !{!4}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!4 = !{i64 0, !"_ZTSFiiiE.generalized"}
diff --git a/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
new file mode 100644
index 0000000000000..c3100ebcb1e3a
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
@@ -0,0 +1,42 @@
+;; Tests that callee_type metadata attached to direct call sites are safely ignored.
+
+; RUN: llc --call-graph-section -mtriple arm-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck %s
+
+; Function Attrs: mustprogress noinline optnone uwtable
+define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
+entry:
+  ; CHECK: callSites:
+  ; CHECK-NOT: calleeTypeIds:  
+  %x.addr = alloca i32, align 4
+  %y.addr = alloca i32, align 4
+  %z.addr = alloca i32, align 4
+  store i32 %x, ptr %x.addr, align 4
+  store i32 %y, ptr %y.addr, align 4
+  store i32 %z, ptr %z.addr, align 4
+  %zval = load i32, ptr %z.addr, align 4
+  %yval = load i32, ptr %y.addr, align 4    
+  ;; This direct call has a callee_type metadata node which matches the
+  ;; callee type accurately.
+  %call = call i32 @_Z4fizzii(i32 %zval, i32 %yval), !callee_type !0
+  %xval = load i32, ptr %x.addr, align 4
+  %yval2 = load i32, ptr %y.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call1 = call i32 @_Z4fizzii(i32 %xval, i32 %yval2), !callee_type !1
+  %add = add nsw i32 %call, %call1
+  %xval2 = load i32, ptr %x.addr, align 4
+  %zval2 = load i32, ptr %z.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call2 = call i32 @_Z4fizzii(i32 %xval2, i32 %zval2), !callee_type !1
+  %sub = sub nsw i32 %add, %call2
+  ret i32 %sub
+}
+
+declare !type !4 i32 @_Z4fizzii(i32, i32)
+
+!0 = !{!4}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!4 = !{i64 0, !"_ZTSFiiiE.generalized"}
diff --git a/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
new file mode 100644
index 0000000000000..4fa0b15058b5f
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
@@ -0,0 +1,42 @@
+;; Tests that callee_type metadata attached to direct call sites are safely ignored.
+
+; RUN: llc --call-graph-section -mtriple mips-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck %s
+
+; Function Attrs: mustprogress noinline optnone uwtable
+define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
+entry:
+  ; CHECK: callSites:
+  ; CHECK-NOT: calleeTypeIds:  
+  %x.addr = alloca i32, align 4
+  %y.addr = alloca i32, align 4
+  %z.addr = alloca i32, align 4
+  store i32 %x, ptr %x.addr, align 4
+  store i32 %y, ptr %y.addr, align 4
+  store i32 %z, ptr %z.addr, align 4
+  %zval = load i32, ptr %z.addr, align 4
+  %yval = load i32, ptr %y.addr, align 4    
+  ;; This direct call has a callee_type metadata node which matches the
+  ;; callee type accurately.
+  %call = call i32 @_Z4fizzii(i32 %zval, i32 %yval), !callee_type !0
+  %xval = load i32, ptr %x.addr, align 4
+  %yval2 = load i32, ptr %y.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call1 = call i32 @_Z4fizzii(i32 %xval, i32 %yval2), !callee_type !1
+  %add = add nsw i32 %call, %call1
+  %xval2 = load i32, ptr %x.addr, align 4
+  %zval2 = load i32, ptr %z.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call2 = call i32 @_Z4fizzii(i32 %xval2, i32 %zval2), !callee_type !1
+  %sub = sub nsw i32 %add, %call2
+  ret i32 %sub
+}
+
+declare !type !4 i32 @_Z4fizzii(i32, i32)
+
+!0 = !{!4}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!4 = !{i64 0, !"_ZTSFiiiE.generalized"}
diff --git a/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
new file mode 100644
index 0000000000000..102a7adb8270d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
@@ -0,0 +1,43 @@
+;; Tests that callee_type metadata attached to direct call sites are safely ignored.
+
+; RUN: llc --call-graph-section -mtriple riscv64 < %s -stop-after=finalize-isel -o - | FileCheck %s
+; RUN: llc --call-graph-section -mtriple riscv32 < %s -stop-after=finalize-isel -o - | FileCheck %s
+
+; Function Attrs: mustprogress noinline optnone uwtable
+define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
+entry:
+  ; CHECK: callSites:
+  ; CHECK-NOT: calleeTypeIds:  
+  %x.addr = alloca i32, align 4
+  %y.addr = alloca i32, align 4
+  %z.addr = alloca i32, align 4
+  store i32 %x, ptr %x.addr, align 4
+  store i32 %y, ptr %y.addr, align 4
+  store i32 %z, ptr %z.addr, align 4
+  %zval = load i32, ptr %z.addr, align 4
+  %yval = load i32, ptr %y.addr, align 4    
+  ;; This direct call has a callee_type metadata node which matches the
+  ;; callee type accurately.
+  %call = call i32 @_Z4fizzii(i32 %zval, i32 %yval), !callee_type !0
+  %xval = load i32, ptr %x.addr, align 4
+  %yval2 = load i32, ptr %y.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call1 = call i32 @_Z4fizzii(i32 %xval, i32 %yval2), !callee_type !1
+  %add = add nsw i32 %call, %call1
+  %xval2 = load i32, ptr %x.addr, align 4
+  %zval2 = load i32, ptr %z.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call2 = call i32 @_Z4fizzii(i32 %xval2, i32 %zval2), !callee_type !1
+  %sub = sub nsw i32 %add, %call2
+  ret i32 %sub
+}
+
+declare !type !4 i32 @_Z4fizzii(i32, i32)
+
+!0 = !{!4}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!4 = !{i64 0, !"_ZTSFiiiE.generalized"}
diff --git a/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
new file mode 100644
index 0000000000000..02ddac672acc8
--- /dev/null
+++ b/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
@@ -0,0 +1,42 @@
+;; Tests that callee_type metadata attached to direct call sites are safely ignored.
+
+; RUN: llc --call-graph-section -mtriple x86_64-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck %s
+
+; Function Attrs: mustprogress noinline optnone uwtable
+define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
+entry:
+  ; CHECK: callSites:
+  ; CHECK-NOT: calleeTypeIds:  
+  %x.addr = alloca i32, align 4
+  %y.addr = alloca i32, align 4
+  %z.addr = alloca i32, align 4
+  store i32 %x, ptr %x.addr, align 4
+  store i32 %y, ptr %y.addr, align 4
+  store i32 %z, ptr %z.addr, align 4
+  %zval = load i32, ptr %z.addr, align 4
+  %yval = load i32, ptr %y.addr, align 4    
+  ;; This direct call has a callee_type metadata node which matches the
+  ;; callee type accurately.
+  %call = call i32 @_Z4fizzii(i32 %zval, i32 %yval), !callee_type !0
+  %xval = load i32, ptr %x.addr, align 4
+  %yval2 = load i32, ptr %y.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call1 = call i32 @_Z4fizzii(i32 %xval, i32 %yval2), !callee_type !1
+  %add = add nsw i32 %call, %call1
+  %xval2 = load i32, ptr %x.addr, align 4
+  %zval2 = load i32, ptr %z.addr, align 4
+  ;; This direct call has a callee_type metadata node which points to a
+  ;; mismatched callee type id.
+  %call2 = call i32 @_Z4fizzii(i32 %xval2, i32 %zval2), !callee_type !1
+  %sub = sub nsw i32 %add, %call2
+  ret i32 %sub
+}
+
+declare !type !4 i32 @_Z4fizzii(i32, i32)
+
+!0 = !{!4}
+!1 = !{!2}
+!2 = !{i64 0, !"_ZTSFicE.generalized"}
+!3 = !{i64 0, !"_ZTSFiiiiE.generalized"}
+!4 = !{i64 0, !"_ZTSFiiiE.generalized"}

>From 7e133e537a461174e252f80b45248ff366f32669 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 14 May 2025 02:06:57 +0000
Subject: [PATCH 28/38] =?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 5ec5e7a3e02b9b6ea9cece22d82e69b7798df3f9 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 14 May 2025 02:11:19 +0000
Subject: [PATCH 29/38] =?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 f1154ce698db49ab43035037e274f782227c2ff3 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 27 May 2025 18:29:16 +0000
Subject: [PATCH 30/38] =?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 24fd769b54e4eeee7fe8a42e41956dd5e0029df7 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Tue, 27 May 2025 20:58:02 +0000
Subject: [PATCH 31/38] Replace not check with positive checks.

Created using spr 1.3.6-beta.1
---
 .../CodeGen/AArch64/calleetypeid-directcall-mismatched.ll  | 7 +++++--
 .../test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll | 7 +++++--
 .../CodeGen/Mips/calleetypeid-directcall-mismatched.ll     | 7 +++++--
 .../CodeGen/RISCV/calleetypeid-directcall-mismatched.ll    | 7 +++++--
 .../test/CodeGen/X86/calleetypeid-directcall-mismatched.ll | 7 +++++--
 5 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
index 8f882362d30f9..e98dfd8a3b4b7 100644
--- a/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll
@@ -5,8 +5,11 @@
 ; Function Attrs: mustprogress noinline optnone uwtable
 define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
 entry:
-  ; CHECK: callSites:
-  ; CHECK-NOT: calleeTypeIds:  
+  ;; Test that `calleeTypeIds` field is not present in `callSites`
+  ; CHECK-LABEL: callSites:
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
   %x.addr = alloca i32, align 4
   %y.addr = alloca i32, align 4
   %z.addr = alloca i32, align 4
diff --git a/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
index c3100ebcb1e3a..8e79cc22e87bc 100644
--- a/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll
@@ -5,8 +5,11 @@
 ; Function Attrs: mustprogress noinline optnone uwtable
 define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
 entry:
-  ; CHECK: callSites:
-  ; CHECK-NOT: calleeTypeIds:  
+  ;; Test that `calleeTypeIds` field is not present in `callSites`
+  ; CHECK-LABEL: callSites:
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
   %x.addr = alloca i32, align 4
   %y.addr = alloca i32, align 4
   %z.addr = alloca i32, align 4
diff --git a/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
index 4fa0b15058b5f..cdf733151b1eb 100644
--- a/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/Mips/calleetypeid-directcall-mismatched.ll
@@ -5,8 +5,11 @@
 ; Function Attrs: mustprogress noinline optnone uwtable
 define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
 entry:
-  ; CHECK: callSites:
-  ; CHECK-NOT: calleeTypeIds:  
+  ;; Test that `calleeTypeIds` field is not present in `callSites`
+  ; CHECK-LABEL: callSites:
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
   %x.addr = alloca i32, align 4
   %y.addr = alloca i32, align 4
   %z.addr = alloca i32, align 4
diff --git a/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
index 102a7adb8270d..b22111384a9e1 100644
--- a/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll
@@ -6,8 +6,11 @@
 ; Function Attrs: mustprogress noinline optnone uwtable
 define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
 entry:
-  ; CHECK: callSites:
-  ; CHECK-NOT: calleeTypeIds:  
+  ;; Test that `calleeTypeIds` field is not present in `callSites`
+  ; CHECK-LABEL: callSites:
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
   %x.addr = alloca i32, align 4
   %y.addr = alloca i32, align 4
   %z.addr = alloca i32, align 4
diff --git a/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
index 02ddac672acc8..9537e12401f25 100644
--- a/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
+++ b/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll
@@ -5,8 +5,11 @@
 ; Function Attrs: mustprogress noinline optnone uwtable
 define i32 @_Z3fooiii(i32 %x, i32 %y, i32 %z) !type !3 {
 entry:
-  ; CHECK: callSites:
-  ; CHECK-NOT: calleeTypeIds:  
+  ;; Test that `calleeTypeIds` field is not present in `callSites`
+  ; CHECK-LABEL: callSites:
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
+  ; CHECK-NEXT: - { bb: {{[0-9]+}}, offset: {{[0-9]+}}, fwdArgRegs: [] }
   %x.addr = alloca i32, align 4
   %y.addr = alloca i32, align 4
   %z.addr = alloca i32, align 4

>From b8f1934eed4a7b2487c9f5f28afbef096e5d57dc Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 11 Jun 2025 00:16:32 +0000
Subject: [PATCH 32/38] =?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 37faf58424674e88e63f0be2842a442a06b65d7d Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 11 Jun 2025 00:32:41 +0000
Subject: [PATCH 33/38] =?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 3c53c182dbf9fe5b2537c1501da2965dea30ed87 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 18 Jul 2025 15:33:57 +0000
Subject: [PATCH 34/38] =?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 11dc6bf1fbfcf3cfe718497cf3b732baefc5a686 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 18 Jul 2025 17:35:44 +0000
Subject: [PATCH 35/38] =?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 ac406a54f52264aa0992519e1b40c1c7254012f1 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 18 Jul 2025 21:01:14 +0000
Subject: [PATCH 36/38] =?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 67756fcdc81668837c1bc54c66894db5d2a0dc53 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 18 Jul 2025 21:35:08 +0000
Subject: [PATCH 37/38] =?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 4f76066368deae67b4f64d35562a333f607de572 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 23 Jul 2025 02:51:13 +0000
Subject: [PATCH 38/38] =?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]
---
 ...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