[llvm] Extract and propagate callee_type metadata

Update MachineFunction::CallSiteInfo to extract numeric CalleeTypeIds
from callee_type metadata attached to indirect call instructions.

Reviewers: nikic, ilovepi

Reviewed By: ilovepi

Pull Request: https://github.com/llvm/llvm-project/pull/87575
This commit is contained in:
Prabhu Rajasekaran 2025-07-30 14:56:39 -07:00 committed by GitHub
parent 254b90fa95
commit 17ccb849f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 520 additions and 2 deletions

View File

@ -26,11 +26,14 @@
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ArrayRecycler.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Recycler.h"
#include "llvm/Target/TargetOptions.h"
#include <bitset>
@ -517,6 +520,32 @@ public:
SmallVector<ArgRegPair, 1> ArgRegPairs;
/// Callee type ids.
SmallVector<ConstantInt *, 4> CalleeTypeIds;
CallSiteInfo() = default;
/// Extracts the numeric type id from the CallBase's callee_type Metadata,
/// and sets CalleeTypeIds. This is used as type id for the indirect call in
/// the call graph section.
CallSiteInfo(const CallBase &CB) {
// Call graph section needs numeric callee_type id only for indirect
// calls.
if (!CB.isIndirectCall())
return;
MDNode *CalleeTypeList = CB.getMetadata(LLVMContext::MD_callee_type);
if (!CalleeTypeList)
return;
for (const MDOperand &Op : CalleeTypeList->operands()) {
MDNode *TypeMD = cast<MDNode>(Op);
MDString *TypeIdStr = cast<MDString>(TypeMD->getOperand(1));
// Compute numeric type id from generalized type id string
uint64_t TypeIdVal = MD5Hash(TypeIdStr->getString());
IntegerType *Int64Ty = Type::getInt64Ty(CB.getContext());
CalleeTypeIds.push_back(
ConstantInt::get(Int64Ty, TypeIdVal, /*IsSigned=*/false));
}
}
};
struct CalledGlobalInfo {

View File

@ -888,7 +888,8 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
}
if (MI->isCandidateForAdditionalCallInfo()) {
if (DAG->getTarget().Options.EmitCallSiteInfo)
if (DAG->getTarget().Options.EmitCallSiteInfo ||
DAG->getTarget().Options.EmitCallGraphSection)
MF.addCallSiteInfo(MI, DAG->getCallSiteInfo(Node));
if (auto CalledGlobal = DAG->getCalledGlobal(Node))

View File

@ -8952,6 +8952,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
bool &IsTailCall = CLI.IsTailCall;
CallingConv::ID &CallConv = CLI.CallConv;
bool IsVarArg = CLI.IsVarArg;
const CallBase *CB = CLI.CB;
MachineFunction &MF = DAG.getMachineFunction();
MachineFunction::CallSiteInfo CSInfo;
@ -8991,6 +8992,10 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
*DAG.getContext());
RetCCInfo.AnalyzeCallResult(Ins, RetCC);
// Set type id for call site info.
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
CSInfo = MachineFunction::CallSiteInfo(*CB);
// Check callee args/returns for SVE registers and set calling convention
// accordingly.
if (CallConv == CallingConv::C || CallConv == CallingConv::Fast) {

View File

@ -2423,6 +2423,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
CallingConv::ID CallConv = CLI.CallConv;
bool doesNotRet = CLI.DoesNotReturn;
bool isVarArg = CLI.IsVarArg;
const CallBase *CB = CLI.CB;
MachineFunction &MF = DAG.getMachineFunction();
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
@ -2446,6 +2447,10 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
!Subtarget->noBTIAtReturnTwice())
GuardWithBTI = AFI->branchTargetEnforcement();
// Set type id for call site info.
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
CSInfo = MachineFunction::CallSiteInfo(*CB);
// Determine whether this is a non-secure function call.
if (CLI.CB && CLI.CB->getAttributes().hasFnAttr("cmse_nonsecure_call"))
isCmseNSCall = true;

View File

@ -3341,6 +3341,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
bool &IsTailCall = CLI.IsTailCall;
CallingConv::ID CallConv = CLI.CallConv;
bool IsVarArg = CLI.IsVarArg;
const CallBase *CB = CLI.CB;
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo &MFI = MF.getFrameInfo();
@ -3397,8 +3398,11 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// Get a count of how many bytes are to be pushed on the stack.
unsigned StackSize = CCInfo.getStackSize();
// Call site info for function parameters tracking.
// Call site info for function parameters tracking and call base type info.
MachineFunction::CallSiteInfo CSInfo;
// Set type id for call site info.
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
CSInfo = MachineFunction::CallSiteInfo(*CB);
// Check if it's really possible to do a tail call. Restrict it to functions
// that are part of this compilation unit.

View File

@ -22725,8 +22725,14 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
bool IsVarArg = CLI.IsVarArg;
EVT PtrVT = getPointerTy(DAG.getDataLayout());
MVT XLenVT = Subtarget.getXLenVT();
const CallBase *CB = CLI.CB;
MachineFunction &MF = DAG.getMachineFunction();
MachineFunction::CallSiteInfo CSInfo;
// Set type id for call site info.
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
CSInfo = MachineFunction::CallSiteInfo(*CB);
// Analyze the operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
@ -22984,6 +22990,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;
}
@ -22991,6 +23000,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);

View File

@ -3673,6 +3673,12 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
CLI.NumResultRegs = RVLocs.size();
CLI.Call = MIB;
// Add call site info for call graph section.
if (TM.Options.EmitCallGraphSection && CB && CB->isIndirectCall()) {
MachineFunction::CallSiteInfo CSInfo(*CB);
MF->addCallSiteInfo(CLI.Call, std::move(CSInfo));
}
return true;
}
@ -4042,6 +4048,8 @@ bool X86FastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
MO.setReg(IndexReg);
}
if (MI->isCall())
FuncInfo.MF->moveAdditionalCallInfo(MI, Result);
Result->addMemOperand(*FuncInfo.MF, createMachineMemOperandFor(LI));
Result->cloneInstrSymbols(*FuncInfo.MF, *MI);
MachineBasicBlock::iterator I(MI);

View File

@ -2060,6 +2060,10 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
if (CallConv == CallingConv::X86_INTR)
report_fatal_error("X86 interrupts may not be called directly");
// Set type id for call site info.
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
CSInfo = MachineFunction::CallSiteInfo(*CB);
if (IsIndirectCall && !IsWin64 &&
M->getModuleFlag("import-call-optimization"))
errorUnsupported(DAG, dl,

View File

@ -0,0 +1,32 @@
;; 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 --match-full-lines %s
;; 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: [] }
define i32 @foo(i32 %x, i32 %y) !type !0 {
entry:
;; Call instruction with accurate callee_type.
;; callee_type should be dropped seemlessly.
%call = call i32 @fizz(i32 %x, i32 %y), !callee_type !1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call1 = call i32 @fizz(i32 %x, i32 %y), !callee_type !3
%add = add nsw i32 %call, %call1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call2 = call i32 @fizz(i32 %add, i32 %y), !callee_type !3
%sub = sub nsw i32 %add, %call2
ret i32 %sub
}
declare !type !2 i32 @fizz(i32, i32)
!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
!3 = !{!4}
!4 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,19 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata for indirect tail calls.
;; 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-after=finalize-isel -o - | FileCheck --match-full-lines %s
define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
entry:
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 3498816979441845844 ] }
%call = tail call i32 %func(i8 signext %x), !callee_type !1
ret i32 %call
}
!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,20 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata.
;; 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 aarch64-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
; CHECK: name: main
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 7854600665770582568 ] }
define i32 @main() {
entry:
%fn = load ptr, ptr null, align 8
call void %fn(i8 0), !callee_type !0
ret i32 0
}
!0 = !{!1}
!1 = !{i64 0, !"_ZTSFvcE.generalized"}

View File

@ -0,0 +1,32 @@
;; 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 --match-full-lines %s
;; 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: [] }
define i32 @foo(i32 %x, i32 %y) !type !0 {
entry:
;; Call instruction with accurate callee_type.
;; callee_type should be dropped seemlessly.
%call = call i32 @fizz(i32 %x, i32 %y), !callee_type !1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call1 = call i32 @fizz(i32 %x, i32 %y), !callee_type !3
%add = add nsw i32 %call, %call1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call2 = call i32 @fizz(i32 %add, i32 %y), !callee_type !3
%sub = sub nsw i32 %add, %call2
ret i32 %sub
}
declare !type !2 i32 @fizz(i32, i32)
!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
!3 = !{!4}
!4 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,19 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata for indirect tail calls.
;; 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-after=finalize-isel -o - | FileCheck --match-full-lines %s
define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
entry:
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 3498816979441845844 ] }
%call = tail call i32 %func(i8 signext %x), !callee_type !1
ret i32 %call
}
!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,20 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata.
;; 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 arm-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
; CHECK: name: main
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 7854600665770582568 ] }
define i32 @main() {
entry:
%fn = load ptr, ptr null, align 8
call void %fn(i8 0), !callee_type !0
ret i32 0
}
!0 = !{!1}
!1 = !{i64 0, !"_ZTSFvcE.generalized"}

View File

@ -0,0 +1,91 @@
;; 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.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test printer and parser with --call-graph-section only.
;; Test printer.
;; 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 -mtriple=x86_64 --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:
; PRINTER_CGS-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; PRINTER_CGS-NEXT: [ 7854600665770582568 ] }
;; Test parser.
;; Verify that we get the same result.
; RUN: llc -mtriple=x86_64 --call-graph-section %t1.mir -run-pass=finalize-isel -o - \
; RUN: | FileCheck %s --check-prefix=PARSER_CGS
; PARSER_CGS: name: main
; PARSER_CGS: callSites:
; PARSER_CGS-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; PARSER_CGS-NEXT: [ 7854600665770582568 ] }
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test printer and parser with -emit-call-site-info only.
;; Test printer.
;; Verify that fwdArgRegs is set, calleeTypeIds is not set.
; RUN: llc -mtriple=x86_64 -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:
; PRINTER_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs:
; PRINTER_CSI-NEXT: { arg: 0, reg: {{.*}} }
; PRINTER_CSI-NOT: calleeTypeIds:
;; Test parser.
;; Verify that we get the same result.
; RUN: llc -mtriple=x86_64 -emit-call-site-info %t2.mir -run-pass=finalize-isel -o - \
; RUN: | FileCheck %s --check-prefix=PARSER_CSI
; PARSER_CSI: name: main
; PARSER_CSI: callSites:
; PARSER_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs:
; PARSER_CSI-NEXT: { arg: 0, reg: {{.*}} }
; PARSER_CSI-NOT: calleeTypeIds:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test printer and parser with both -emit-call-site-info and --call-graph-section.
;; Test printer.
;; 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 -mtriple=x86_64 --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:
; PRINTER_CGS_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs:
; PRINTER_CGS_CSI-NEXT: { arg: 0, reg: {{.*}} }, calleeTypeIds:
; PRINTER_CGS_CSI-NEXT: [ 7854600665770582568 ] }
;; Test parser.
;; Verify that we get the same result.
; RUN: llc -mtriple=x86_64 --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
; PARSER_CGS_CSI: callSites:
; PARSER_CGS_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs:
; PARSER_CGS_CSI-NEXT: { arg: 0, reg: {{.*}} }, calleeTypeIds:
; PARSER_CGS_CSI-NEXT: [ 7854600665770582568 ] }
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
define i32 @main() {
entry:
%fn = load ptr, ptr null, align 8
call void %fn(i8 0), !callee_type !0
ret i32 0
}
!0 = !{!1}
!1 = !{i64 0, !"_ZTSFvcE.generalized"}

View File

@ -0,0 +1,32 @@
;; 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 --match-full-lines %s
;; 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: [] }
define i32 @foo(i32 %x, i32 %y) !type !0 {
entry:
;; Call instruction with accurate callee_type.
;; callee_type should be dropped seemlessly.
%call = call i32 @fizz(i32 %x, i32 %y), !callee_type !1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call1 = call i32 @fizz(i32 %x, i32 %y), !callee_type !3
%add = add nsw i32 %call, %call1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call2 = call i32 @fizz(i32 %add, i32 %y), !callee_type !3
%sub = sub nsw i32 %add, %call2
ret i32 %sub
}
declare !type !2 i32 @fizz(i32, i32)
!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
!3 = !{!4}
!4 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,19 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata for indirect tail calls.
;; 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-after=finalize-isel -o - | FileCheck --match-full-lines %s
define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
entry:
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 3498816979441845844 ] }
%call = tail call i32 %func(i8 signext %x), !callee_type !1
ret i32 %call
}
!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,20 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata.
;; 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=mips-linux-gnu < %s -stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
; CHECK: name: main
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 7854600665770582568 ] }
define i32 @main() {
entry:
%fn = load ptr, ptr null, align 8
call void %fn(i8 0), !callee_type !0
ret i32 0
}
!0 = !{!1}
!1 = !{i64 0, !"_ZTSFvcE.generalized"}

View File

@ -0,0 +1,33 @@
;; 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 --match-full-lines %s
; RUN: llc --call-graph-section -mtriple riscv32 < %s -stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
;; 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: [] }
define i32 @foo(i32 %x, i32 %y) !type !0 {
entry:
;; Call instruction with accurate callee_type.
;; callee_type should be dropped seemlessly.
%call = call i32 @fizz(i32 %x, i32 %y), !callee_type !1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call1 = call i32 @fizz(i32 %x, i32 %y), !callee_type !3
%add = add nsw i32 %call, %call1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call2 = call i32 @fizz(i32 %add, i32 %y), !callee_type !3
%sub = sub nsw i32 %add, %call2
ret i32 %sub
}
declare !type !2 i32 @fizz(i32, i32)
!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
!3 = !{!4}
!4 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,20 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata for indirect tail calls.
;; 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-after=finalize-isel -o - | FileCheck --match-full-lines %s
; RUN: llc --call-graph-section -mtriple riscv32 < %s -stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
entry:
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 3498816979441845844 ] }
%call = tail call i32 %func(i8 signext %x), !callee_type !1
ret i32 %call
}
!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,21 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata.
;; 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-after=finalize-isel -o - | FileCheck --match-full-lines %s
; RUN: llc --call-graph-section -mtriple riscv32 < %s -stop-after=finalize-isel -o - | FileCheck --match-full-lines %s
; CHECK: name: main
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 7854600665770582568 ] }
define i32 @main() {
entry:
%fn = load ptr, ptr null, align 8
call void %fn(i8 0), !callee_type !0
ret i32 0
}
!0 = !{!1}
!1 = !{i64 0, !"_ZTSFvcE.generalized"}

View File

@ -0,0 +1,32 @@
;; 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 --match-full-lines %s
;; 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: [] }
define i32 @foo(i32 %x, i32 %y) !type !0 {
entry:
;; Call instruction with accurate callee_type.
;; callee_type should be dropped seemlessly.
%call = call i32 @fizz(i32 %x, i32 %y), !callee_type !1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call1 = call i32 @fizz(i32 %x, i32 %y), !callee_type !3
%add = add nsw i32 %call, %call1
;; Call instruction with mismatched callee_type.
;; callee_type should be dropped seemlessly without errors.
%call2 = call i32 @fizz(i32 %add, i32 %y), !callee_type !3
%sub = sub nsw i32 %add, %call2
ret i32 %sub
}
declare !type !2 i32 @fizz(i32, i32)
!0 = !{i64 0, !"_ZTSFiiiiE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFiiiE.generalized"}
!3 = !{!4}
!4 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,19 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata for indirect tail calls.
;; 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-after=finalize-isel -o - | FileCheck --match-full-lines %s
define i32 @check_tailcall(ptr %func, i8 %x) !type !0 {
entry:
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 3498816979441845844 ] }
%call = tail call i32 %func(i8 signext %x), !callee_type !1
ret i32 %call
}
!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFicE.generalized"}

View File

@ -0,0 +1,20 @@
;; Tests that call site callee type ids can be extracted and set from
;; callee_type metadata.
;; 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-after=finalize-isel -o - | FileCheck --match-full-lines %s
; CHECK: name: main
; CHECK: callSites:
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], calleeTypeIds:
; CHECK-NEXT: [ 7854600665770582568 ] }
define i32 @main() {
entry:
%fn = load ptr, ptr null, align 8
call void %fn(i8 0), !callee_type !0
ret i32 0
}
!0 = !{!1}
!1 = !{i64 0, !"_ZTSFvcE.generalized"}