[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