From d2d56f463c746ec312fb8f9d1b15fd582274106f Mon Sep 17 00:00:00 2001 From: Necip Fazil Yildiran Date: Wed, 3 Apr 2024 15:48:01 -0700 Subject: [PATCH 01/39] =?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, NegFlag>; +defm call_graph_section : BoolFOption<"call-graph-section", + CodeGenOpts<"CallGraphSection">, DefaultFalse, + PosFlag, + NegFlag>; defm stack_size_section : BoolFOption<"stack-size-section", CodeGenOpts<"StackSizeSection">, DefaultFalse, PosFlaggetFunctionType() || + 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() && !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(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 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 +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 is checked above within the template description. + Cls2 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 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::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 *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@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@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@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@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@Z.generalized") ] + St2.m.fp(0, 0, 0); + + // ITANIUM: call void {{.*}} [ "type"(metadata !"_ZTSFv3st2PvE.generalized") ] + // MS: call void {{.*}} [ "type"(metadata !"?6AXUst2@@PEAX@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@Z.generalized"} + +// ITANIUM-DAG: [[F_TPRIMITIVE]] = !{i64 0, !"_ZTSFicfdE.generalized"} +// MS-DAG: [[F_TPRIMITIVE]] = !{i64 0, !"?6AHDMN@Z.generalized"} + +// ITANIUM-DAG: [[F_TPTR]] = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"} +// MS-DAG: [[F_TPTR]] = !{i64 0, !"?6APEAXPEAX00@Z.generalized"} + +// ITANIUM-DAG: [[F_TSTRUCT]] = !{i64 0, !"_ZTSFv3st2PvE.generalized"} +// MS-DAG: [[F_TSTRUCT]] = !{i64 0, !"?6AXUst2@@PEAX@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 ArgForwardingRegs; + /// Numeric callee type identifier used for call graph section. + using TypeIdTy = std::optional; + 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 { YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset); YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs, std::vector()); + 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 ArgRegPairs; + + /// Callee type id. + ConstantInt *TypeId = nullptr; }; private: @@ -492,7 +495,7 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction { GISelChangeObserver *Observer = nullptr; using CallSiteInfoMap = DenseMap; - /// 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 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 EnableCallGraphSection( + "call-graph-section", cl::desc("Emit a call graph section"), + cl::init(false)); + CGBINDOPT(EnableCallGraphSection); + static cl::opt 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: Date: Mon, 29 Apr 2024 11:53:52 -0700 Subject: [PATCH 02/39] =?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(TargetDecl)) { // Type id metadata is set only for C/C++ contexts. - if (dyn_cast(FD) || dyn_cast(FD) || - dyn_cast(FD)) { + if (isa(FD) || isa(FD) || + isa(FD)) { CGM.CreateFunctionTypeMetadataForIcall(FD->getType(), *callOrInvoke); } } From 966ac5afb9a1bcb1d14481dd93a6268f87c7e06c Mon Sep 17 00:00:00 2001 From: Necip Fazil Yildiran Date: Wed, 13 Nov 2024 17:20:14 -0800 Subject: [PATCH 03/39] =?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 Date: Tue, 19 Nov 2024 15:25:34 -0800 Subject: [PATCH 04/39] 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 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 Date: Wed, 20 Nov 2024 11:52:58 -0800 Subject: [PATCH 05/39] =?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, NegFlag>; -defm call_graph_section : BoolFOption<"call-graph-section", - CodeGenOpts<"CallGraphSection">, DefaultFalse, - PosFlag, - NegFlag>; defm stack_size_section : BoolFOption<"stack-size-section", CodeGenOpts<"StackSizeSection">, DefaultFalse, PosFlaggetValue()); } - 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 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 EnableCallGraphSection( - "call-graph-section", cl::desc("Emit a call graph section"), - cl::init(false)); - CGBINDOPT(EnableCallGraphSection); - static cl::opt 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 Date: Tue, 10 Dec 2024 14:54:55 -0800 Subject: [PATCH 06/39] =?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(FD) || isa(FD) || - isa(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(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() && !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(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 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 -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 is checked above within the template description. - Cls2 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 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::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 *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@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@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@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@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@Z.generalized") ] - St2.m.fp(0, 0, 0); - - // ITANIUM: call void {{.*}} [ "type"(metadata !"_ZTSFv3st2PvE.generalized") ] - // MS: call void {{.*}} [ "type"(metadata !"?6AXUst2@@PEAX@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@Z.generalized"} - -// ITANIUM-DAG: [[F_TPRIMITIVE]] = !{i64 0, !"_ZTSFicfdE.generalized"} -// MS-DAG: [[F_TPRIMITIVE]] = !{i64 0, !"?6AHDMN@Z.generalized"} - -// ITANIUM-DAG: [[F_TPTR]] = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"} -// MS-DAG: [[F_TPTR]] = !{i64 0, !"?6APEAXPEAX00@Z.generalized"} - -// ITANIUM-DAG: [[F_TSTRUCT]] = !{i64 0, !"_ZTSFv3st2PvE.generalized"} -// MS-DAG: [[F_TSTRUCT]] = !{i64 0, !"?6AXUst2@@PEAX@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; - /// 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 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 EnableCallGraphSection( + "call-graph-section", cl::desc("Emit a call graph section"), + cl::init(false)); + CGBINDOPT(EnableCallGraphSection); + static cl::opt 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 Date: Wed, 5 Feb 2025 23:07:19 +0000 Subject: [PATCH 07/39] =?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 Date: Tue, 11 Feb 2025 22:34:05 +0000 Subject: [PATCH 08/39] 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(OBVal)->getMetadata(); + auto *TypeIdStr = cast(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 Date: Thu, 13 Mar 2025 01:03:42 +0000 Subject: [PATCH 09/39] =?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 Date: Thu, 13 Mar 2025 01:21:29 +0000 Subject: [PATCH 10/39] =?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 Date: Thu, 13 Mar 2025 17:34:26 +0000 Subject: [PATCH 11/39] 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 Opt = + std::optional 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(OBVal)->getMetadata(); - auto *TypeIdStr = cast(TypeIdMD); - assert(TypeIdStr->getString().ends_with(".generalized") && - "invalid type identifier"); + Value *CalleeTypeOBVal = CalleeTypeOB->Inputs.front().get(); + Metadata *TypeIdMD = + cast(CalleeTypeOBVal)->getMetadata(); + MDString *TypeIdStr = cast(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(OBVal)->getMetadata(); - auto *TypeIdStr = cast(TypeIdMD); + Value *CalleeTypeOBVal = BU.Inputs.front().get(); + Metadata *TypeIdMD = + cast(CalleeTypeOBVal)->getMetadata(); + MDString *TypeIdStr = cast(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(); 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 Date: Fri, 14 Mar 2025 04:10:20 +0000 Subject: [PATCH 12/39] 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 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 Date: Sat, 15 Mar 2025 01:09:47 +0000 Subject: [PATCH 13/39] =?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 Date: Wed, 19 Mar 2025 02:54:14 +0000 Subject: [PATCH 14/39] =?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; - TypeIdTy TypeId; + TypeIdTy CalleeTypeId; bool operator==(const CallSiteInfo &Other) const { return CallLocation.BlockNum == Other.CallLocation.BlockNum && @@ -515,7 +515,7 @@ template <> struct MappingTraits { YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset); YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs, std::vector()); - 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 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 Date: Sat, 19 Apr 2025 02:16:46 +0000 Subject: [PATCH 15/39] =?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 ArgForwardingRegs; - - /// Numeric callee type identifier used for call graph section. - using TypeIdTy = std::optional; - TypeIdTy CalleeTypeId; + /// Numeric callee type identifiers for the callgraph section. + std::vector CalleeTypeIds; bool operator==(const CallSiteInfo &Other) const { return CallLocation.BlockNum == Other.CallLocation.BlockNum && @@ -515,7 +513,7 @@ template <> struct MappingTraits { YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset); YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs, std::vector()); - 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 ArgRegPairs; - - /// Callee type id. - ConstantInt *CalleeTypeId = nullptr; + /// Callee type ids. + SmallVector 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 AB; + SmallSet 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: Date: Sat, 19 Apr 2025 03:07:19 +0000 Subject: [PATCH 16/39] 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 Date: Wed, 23 Apr 2025 01:02:06 +0000 Subject: [PATCH 17/39] =?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 Date: Wed, 23 Apr 2025 03:52:23 +0000 Subject: [PATCH 18/39] =?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(getOperand(1))) + return false; + return cast(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, 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(I), "!callee_type metadata should only exist on calls", + &I); + CallBase *CB = cast(&I); + Check(CB->isIndirectCall(), + "!callee_type metadata should only exist on indirect function calls", + &I); + for (const auto &Op : MD->operands()) { + auto *TypeMD = cast(Op.get()); + Check(TypeMD->hasGeneralizedMDString(), + "Invalid \"callee_type\" type identifier", &I); + } +} + void Verifier::visitAnnotationMetadata(MDNode *Annotation) { Check(isa(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 Date: Wed, 23 Apr 2025 23:39:13 +0000 Subject: [PATCH 19/39] =?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 Date: Thu, 24 Apr 2025 02:24:49 +0000 Subject: [PATCH 20/39] =?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 Date: Thu, 24 Apr 2025 20:39:32 +0000 Subject: [PATCH 21/39] =?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 Date: Thu, 24 Apr 2025 23:50:27 +0000 Subject: [PATCH 22/39] =?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(Op.get()), + "The callee_type metadata must be a list of type metadata nodes"); auto *TypeMD = cast(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 Date: Mon, 28 Apr 2025 22:48:48 +0000 Subject: [PATCH 23/39] =?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(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(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 Date: Mon, 5 May 2025 23:13:05 +0000 Subject: [PATCH 24/39] =?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 AB; SmallSet 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(I), "!callee_type metadata should only exist on calls", &I); - CallBase *CB = cast(&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(Op.get()), "The callee_type metadata must be a list of type metadata nodes"); auto *TypeMD = cast(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 Date: Sat, 10 May 2025 00:33:07 +0000 Subject: [PATCH 25/39] =?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: + +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 Date: Tue, 13 May 2025 17:24:46 +0000 Subject: [PATCH 26/39] =?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 Date: Tue, 13 May 2025 20:49:50 +0000 Subject: [PATCH 27/39] 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 Date: Wed, 14 May 2025 02:06:57 +0000 Subject: [PATCH 28/39] =?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 -`. +pointing to a callee's :ref:`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 Date: Wed, 14 May 2025 02:11:19 +0000 Subject: [PATCH 29/39] =?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 `. -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 Date: Tue, 27 May 2025 18:29:16 +0000 Subject: [PATCH 30/39] =?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 Date: Tue, 27 May 2025 20:58:02 +0000 Subject: [PATCH 31/39] 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 Date: Wed, 11 Jun 2025 00:16:32 +0000 Subject: [PATCH 32/39] =?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 `. +list of one or more generalized ``!type`` metadata objects (See :doc:`TypeMetadata`) with each ``!type`` +metadata pointing to a callee's :ref:`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 AB; SmallSet 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 Date: Wed, 11 Jun 2025 00:32:41 +0000 Subject: [PATCH 33/39] =?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 &EndPoints, MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A, MDNode *B) { SmallVector AB; - SmallSet MergedCallees; + SmallPtrSet 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 Date: Fri, 18 Jul 2025 15:33:57 +0000 Subject: [PATCH 34/39] =?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(MD)) { + if (auto *VAL = dyn_cast(MD)) return isa(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 Date: Fri, 18 Jul 2025 17:35:44 +0000 Subject: [PATCH 35/39] =?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 Date: Fri, 18 Jul 2025 21:01:14 +0000 Subject: [PATCH 36/39] =?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 &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 AB; SmallPtrSet 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 Date: Fri, 18 Jul 2025 21:35:08 +0000 Subject: [PATCH 37/39] =?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 &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 AB; SmallPtrSet 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 Date: Wed, 23 Jul 2025 02:51:13 +0000 Subject: [PATCH 38/39] =?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`) ... From 858480fd235f6211e7d9e6bca1b55fbaf16fafa7 Mon Sep 17 00:00:00 2001 From: prabhukr Date: Wed, 23 Jul 2025 17:46:59 +0000 Subject: [PATCH 39/39] Change test var name. Created using spr 1.3.6-beta.1 --- llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll | 4 ++-- llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll | 4 ++-- llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll | 4 ++-- llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll | 4 ++-- llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll | 4 ++-- llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll index 108946685529c..94b657c6ea908 100644 --- a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll @@ -11,8 +11,8 @@ ; CHECK-NEXT: [ 7854600665770582568 ] } define i32 @main() { entry: - %0 = load ptr, ptr null, align 8 - call void %0(i8 0), !callee_type !0 + %fn = load ptr, ptr null, align 8 + call void %fn(i8 0), !callee_type !0 ret i32 0 } diff --git a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll index 68f476ce8a730..a65e5c5f8c015 100644 --- a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll @@ -11,8 +11,8 @@ ; CHECK-NEXT: [ 7854600665770582568 ] } define i32 @main() { entry: - %0 = load ptr, ptr null, align 8 - call void %0(i8 0), !callee_type !0 + %fn = load ptr, ptr null, align 8 + call void %fn(i8 0), !callee_type !0 ret i32 0 } diff --git a/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll index 367632ee6857c..b2a386bc8abe3 100644 --- a/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll @@ -82,8 +82,8 @@ define i32 @main() { entry: - %0 = load ptr, ptr null, align 8 - call void %0(i8 0), !callee_type !0 + %fn = load ptr, ptr null, align 8 + call void %fn(i8 0), !callee_type !0 ret i32 0 } diff --git a/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll index 65c8d6b906233..9f5e858412ed6 100644 --- a/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/Mips/callsite-emit-calleetypeid.ll @@ -11,8 +11,8 @@ ; CHECK-NEXT: [ 7854600665770582568 ] } define i32 @main() { entry: - %0 = load ptr, ptr null, align 8 - call void %0(i8 0), !callee_type !0 + %fn = load ptr, ptr null, align 8 + call void %fn(i8 0), !callee_type !0 ret i32 0 } diff --git a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll index 8189cf74e47df..1f91f4103abbb 100644 --- a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll @@ -12,8 +12,8 @@ ; CHECK-NEXT: [ 7854600665770582568 ] } define i32 @main() { entry: - %0 = load ptr, ptr null, align 8 - call void %0(i8 0), !callee_type !0 + %fn = load ptr, ptr null, align 8 + call void %fn(i8 0), !callee_type !0 ret i32 0 } diff --git a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll index d8fab32ec0b99..e97a6ac75e111 100644 --- a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll @@ -11,8 +11,8 @@ ; CHECK-NEXT: [ 7854600665770582568 ] } define i32 @main() { entry: - %0 = load ptr, ptr null, align 8 - call void %0(i8 0), !callee_type !0 + %fn = load ptr, ptr null, align 8 + call void %fn(i8 0), !callee_type !0 ret i32 0 }