Skip to content

Commit 21c9acc

Browse files
necipfazilPrabhuk
authored andcommitted
[llvm] Extract and propagate indirect call type id
Extract numeric type ids for indirect calls, and carry them to the back-end with CallSiteInfo. The numeric type ids will be used at the back-end to emit the call graph section. Pull Request: llvm#87575
1 parent 919f0cd commit 21c9acc

13 files changed

+286
-2
lines changed

llvm/include/llvm/CodeGen/MachineFunction.h

+34
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@
2626
#include "llvm/CodeGen/MachineBasicBlock.h"
2727
#include "llvm/CodeGen/MachineInstr.h"
2828
#include "llvm/CodeGen/MachineMemOperand.h"
29+
#include "llvm/IR/Constants.h"
2930
#include "llvm/IR/EHPersonalities.h"
31+
#include "llvm/IR/Instructions.h"
3032
#include "llvm/Support/Allocator.h"
3133
#include "llvm/Support/ArrayRecycler.h"
3234
#include "llvm/Support/AtomicOrdering.h"
3335
#include "llvm/Support/Compiler.h"
36+
#include "llvm/Support/MD5.h"
3437
#include "llvm/Support/Recycler.h"
3538
#include "llvm/Target/TargetOptions.h"
3639
#include <bitset>
@@ -499,6 +502,37 @@ class LLVM_ABI MachineFunction {
499502

500503
/// Callee type id.
501504
ConstantInt *TypeId = nullptr;
505+
506+
CallSiteInfo() = default;
507+
508+
/// Extracts the numeric type id from the CallBase's type operand bundle,
509+
/// and sets TypeId. This is used as type id for the indirect call in the
510+
/// call graph section.
511+
CallSiteInfo(const CallBase &CB) {
512+
// Call graph section needs numeric type id only for indirect calls.
513+
if (!CB.isIndirectCall())
514+
return;
515+
516+
std::optional<OperandBundleUse> Opt =
517+
CB.getOperandBundle(LLVMContext::OB_callee_type);
518+
// Return if the operand bundle for call graph section cannot be found.
519+
if (!Opt)
520+
return;
521+
522+
// Get generalized type id string
523+
auto OB = *Opt;
524+
assert(OB.Inputs.size() == 1 && "invalid input size");
525+
auto *OBVal = OB.Inputs.front().get();
526+
auto *TypeIdMD = cast<MetadataAsValue>(OBVal)->getMetadata();
527+
auto *TypeIdStr = cast<MDString>(TypeIdMD);
528+
assert(TypeIdStr->getString().ends_with(".generalized") &&
529+
"invalid type identifier");
530+
531+
// Compute numeric type id from generalized type id string
532+
uint64_t TypeIdVal = MD5Hash(TypeIdStr->getString());
533+
IntegerType *Int64Ty = Type::getInt64Ty(CB.getContext());
534+
TypeId = ConstantInt::get(Int64Ty, TypeIdVal, /*IsSigned=*/false);
535+
}
502536
};
503537

504538
struct CalledGlobalInfo {

llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,8 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
889889
}
890890

891891
if (MI->isCandidateForAdditionalCallInfo()) {
892-
if (DAG->getTarget().Options.EmitCallSiteInfo)
892+
if (DAG->getTarget().Options.EmitCallSiteInfo ||
893+
DAG->getTarget().Options.EmitCallGraphSection)
893894
MF.addCallSiteInfo(MI, DAG->getCallSiteInfo(Node));
894895

895896
if (auto CalledGlobal = DAG->getCalledGlobal(Node))

llvm/lib/IR/Verifier.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -3794,6 +3794,11 @@ void Verifier::visitCallBase(CallBase &Call) {
37943794
} else if (Tag == LLVMContext::OB_callee_type) {
37953795
Check(!FoundCalleeTypeBundle, "Multiple \"callee_type\" operand bundles",
37963796
Call);
3797+
auto *OBVal = BU.Inputs.front().get();
3798+
auto *TypeIdMD = cast<MetadataAsValue>(OBVal)->getMetadata();
3799+
auto *TypeIdStr = cast<MDString>(TypeIdMD);
3800+
Check(TypeIdStr->getString().ends_with(".generalized"),
3801+
"Invalid \"callee_type\" type identifier", Call);
37973802
FoundCalleeTypeBundle = true;
37983803
}
37993804
}

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -8915,6 +8915,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
89158915
bool &IsTailCall = CLI.IsTailCall;
89168916
CallingConv::ID &CallConv = CLI.CallConv;
89178917
bool IsVarArg = CLI.IsVarArg;
8918+
const auto *CB = CLI.CB;
89188919

89198920
MachineFunction &MF = DAG.getMachineFunction();
89208921
MachineFunction::CallSiteInfo CSInfo;
@@ -8954,6 +8955,10 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
89548955
*DAG.getContext());
89558956
RetCCInfo.AnalyzeCallResult(Ins, RetCC);
89568957

8958+
// Set type id for call site info.
8959+
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
8960+
CSInfo = MachineFunction::CallSiteInfo(*CB);
8961+
89578962
// Check callee args/returns for SVE registers and set calling convention
89588963
// accordingly.
89598964
if (CallConv == CallingConv::C || CallConv == CallingConv::Fast) {

llvm/lib/Target/ARM/ARMISelLowering.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24392439
CallingConv::ID CallConv = CLI.CallConv;
24402440
bool doesNotRet = CLI.DoesNotReturn;
24412441
bool isVarArg = CLI.IsVarArg;
2442+
const auto *CB = CLI.CB;
24422443

24432444
MachineFunction &MF = DAG.getMachineFunction();
24442445
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
@@ -2462,6 +2463,10 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24622463
!Subtarget->noBTIAtReturnTwice())
24632464
GuardWithBTI = AFI->branchTargetEnforcement();
24642465

2466+
// Set type id for call site info.
2467+
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
2468+
CSInfo = MachineFunction::CallSiteInfo(*CB);
2469+
24652470
// Determine whether this is a non-secure function call.
24662471
if (CLI.CB && CLI.CB->getAttributes().hasFnAttr("cmse_nonsecure_call"))
24672472
isCmseNSCall = true;

llvm/lib/Target/Mips/MipsISelLowering.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -3264,6 +3264,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
32643264
bool &IsTailCall = CLI.IsTailCall;
32653265
CallingConv::ID CallConv = CLI.CallConv;
32663266
bool IsVarArg = CLI.IsVarArg;
3267+
const auto *CB = CLI.CB;
32673268

32683269
MachineFunction &MF = DAG.getMachineFunction();
32693270
MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -3320,8 +3321,11 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
33203321
// Get a count of how many bytes are to be pushed on the stack.
33213322
unsigned StackSize = CCInfo.getStackSize();
33223323

3323-
// Call site info for function parameters tracking.
3324+
// Call site info for function parameters tracking and call base type info.
33243325
MachineFunction::CallSiteInfo CSInfo;
3326+
// Set type id for call site info.
3327+
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
3328+
CSInfo = MachineFunction::CallSiteInfo(*CB);
33253329

33263330
// Check if it's really possible to do a tail call. Restrict it to functions
33273331
// that are part of this compilation unit.

llvm/lib/Target/X86/X86FastISel.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -3631,6 +3631,12 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
36313631
CLI.NumResultRegs = RVLocs.size();
36323632
CLI.Call = MIB;
36333633

3634+
// Add call site info for call graph section.
3635+
if (TM.Options.EmitCallGraphSection && CB && CB->isIndirectCall()) {
3636+
MachineFunction::CallSiteInfo CSInfo(*CB);
3637+
MF->addCallSiteInfo(CLI.Call, std::move(CSInfo));
3638+
}
3639+
36343640
return true;
36353641
}
36363642

@@ -4026,6 +4032,8 @@ bool X86FastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
40264032
MO.setReg(IndexReg);
40274033
}
40284034

4035+
if (MI->isCall())
4036+
FuncInfo.MF->moveAdditionalCallInfo(MI, Result);
40294037
Result->addMemOperand(*FuncInfo.MF, createMachineMemOperandFor(LI));
40304038
Result->cloneInstrSymbols(*FuncInfo.MF, *MI);
40314039
MachineBasicBlock::iterator I(MI);

llvm/lib/Target/X86/X86ISelLoweringCall.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,10 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
20312031
if (CallConv == CallingConv::X86_INTR)
20322032
report_fatal_error("X86 interrupts may not be called directly");
20332033

2034+
// Set type id for call site info.
2035+
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
2036+
CSInfo = MachineFunction::CallSiteInfo(*CB);
2037+
20342038
// Analyze operands of the call, assigning locations to each operand.
20352039
SmallVector<CCValAssign, 16> ArgLocs;
20362040
CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
;; Tests that call site type ids can be extracted and set from type operand
2+
;; bundles.
3+
4+
;; Verify the exact typeId value to ensure it is not garbage but the value
5+
;; computed as the type id from the type operand bundle.
6+
; RUN: llc --call-graph-section -mtriple aarch64-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
7+
8+
define dso_local void @foo(i8 signext %a) !type !3 {
9+
entry:
10+
ret void
11+
}
12+
13+
; CHECK: name: main
14+
define dso_local i32 @main() !type !4 {
15+
entry:
16+
%retval = alloca i32, align 4
17+
%fp = alloca ptr, align 8
18+
store i32 0, ptr %retval, align 4
19+
store ptr @foo, ptr %fp, align 8
20+
%0 = load ptr, ptr %fp, align 8
21+
; CHECK: callSites:
22+
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
23+
; CHECK-NEXT: 7854600665770582568 }
24+
call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
25+
ret i32 0
26+
}
27+
28+
!3 = !{i64 0, !"_ZTSFvcE.generalized"}
29+
!4 = !{i64 0, !"_ZTSFiE.generalized"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
;; Tests that call site type ids can be extracted and set from type operand
2+
;; bundles.
3+
4+
;; Verify the exact typeId value to ensure it is not garbage but the value
5+
;; computed as the type id from the type operand bundle.
6+
; RUN: llc --call-graph-section -mtriple arm-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
7+
8+
define dso_local void @foo(i8 signext %a) !type !3 {
9+
entry:
10+
ret void
11+
}
12+
13+
; CHECK: name: main
14+
define dso_local i32 @main() !type !4 {
15+
entry:
16+
%retval = alloca i32, align 4
17+
%fp = alloca ptr, align 8
18+
store i32 0, ptr %retval, align 4
19+
store ptr @foo, ptr %fp, align 8
20+
%0 = load ptr, ptr %fp, align 8
21+
; CHECK: callSites:
22+
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
23+
; CHECK-NEXT: 7854600665770582568 }
24+
call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
25+
ret i32 0
26+
}
27+
28+
!3 = !{i64 0, !"_ZTSFvcE.generalized"}
29+
!4 = !{i64 0, !"_ZTSFiE.generalized"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
;; Test MIR printer and parser for type id field in call site info. Test that
2+
;; it works well with/without --emit-call-site-info.
3+
4+
;; Multiplex --call-graph-section and -emit-call-site-info as both utilize
5+
;; CallSiteInfo and callSites.
6+
7+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8+
;; Test printer and parser with --call-graph-section only.
9+
10+
;; Test printer.
11+
;; Verify that fwdArgRegs is not set, typeId is set.
12+
;; Verify the exact typeId value to ensure it is not garbage but the value
13+
;; computed as the type id from the type operand bundle.
14+
; RUN: llc --call-graph-section %s -stop-before=finalize-isel -o %t1.mir
15+
; RUN: cat %t1.mir | FileCheck %s --check-prefix=PRINTER_CGS
16+
; PRINTER_CGS: name: main
17+
; PRINTER_CGS: callSites:
18+
; PRINTER_CGS-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
19+
; PRINTER_CGS-NEXT: 7854600665770582568 }
20+
21+
22+
;; Test parser.
23+
;; Verify that we get the same result.
24+
; RUN: llc --call-graph-section %t1.mir -run-pass=finalize-isel -o - \
25+
; RUN: | FileCheck %s --check-prefix=PARSER_CGS
26+
; PARSER_CGS: name: main
27+
; PARSER_CGS: callSites:
28+
; PARSER_CGS-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
29+
; PARSER_CGS-NEXT: 7854600665770582568 }
30+
31+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32+
;; Test printer and parser with -emit-call-site-info only.
33+
34+
;; Test printer.
35+
;; Verify that fwdArgRegs is set, typeId is not set.
36+
; RUN: llc -emit-call-site-info %s -stop-before=finalize-isel -o %t2.mir
37+
; RUN: cat %t2.mir | FileCheck %s --check-prefix=PRINTER_CSI
38+
; PRINTER_CSI: name: main
39+
; PRINTER_CSI: callSites:
40+
; PRINTER_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs:
41+
; PRINTER_CSI-NEXT: { arg: 0, reg: '$edi' }
42+
; PRINTER_CSI-NOT: typeId:
43+
44+
45+
;; Test parser.
46+
;; Verify that we get the same result.
47+
; RUN: llc -emit-call-site-info %t2.mir -run-pass=finalize-isel -o - \
48+
; RUN: | FileCheck %s --check-prefix=PARSER_CSI
49+
; PARSER_CSI: name: main
50+
; PARSER_CSI: callSites:
51+
; PARSER_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs:
52+
; PARSER_CSI-NEXT: { arg: 0, reg: '$edi' }
53+
; PARSER_CSI-NOT: typeId:
54+
55+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56+
;; Test printer and parser with both -emit-call-site-info and --call-graph-section.
57+
58+
;; Test printer.
59+
;; Verify both fwdArgRegs and typeId are set.
60+
;; Verify the exact typeId value to ensure it is not garbage but the value
61+
;; computed as the type id from the type operand bundle.
62+
; RUN: llc --call-graph-section -emit-call-site-info %s -stop-before=finalize-isel -o %t2.mir
63+
; RUN: cat %t2.mir | FileCheck %s --check-prefix=PRINTER_CGS_CSI
64+
; PRINTER_CGS_CSI: name: main
65+
; PRINTER_CGS_CSI: callSites:
66+
; PRINTER_CGS_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs:
67+
; PRINTER_CGS_CSI-NEXT: { arg: 0, reg: '$edi' }, typeId:
68+
; PRINTER_CGS_CSI-NEXT: 7854600665770582568 }
69+
70+
71+
;; Test parser.
72+
;; Verify that we get the same result.
73+
; RUN: llc --call-graph-section -emit-call-site-info %t2.mir -run-pass=finalize-isel -o - \
74+
; RUN: | FileCheck %s --check-prefix=PARSER_CGS_CSI
75+
; PARSER_CGS_CSI: name: main
76+
; PARSER_CGS_CSI: callSites:
77+
; PARSER_CGS_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs:
78+
; PARSER_CGS_CSI-NEXT: { arg: 0, reg: '$edi' }, typeId:
79+
; PARSER_CGS_CSI-NEXT: 7854600665770582568 }
80+
81+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
82+
83+
; Function Attrs: noinline nounwind optnone uwtable
84+
define dso_local void @foo(i8 signext %a) !type !3 {
85+
entry:
86+
ret void
87+
}
88+
89+
; Function Attrs: noinline nounwind optnone uwtable
90+
define dso_local i32 @main() !type !4 {
91+
entry:
92+
%retval = alloca i32, align 4
93+
%fp = alloca ptr, align 8
94+
store i32 0, ptr %retval, align 4
95+
store ptr @foo, ptr %fp, align 8
96+
%0 = load ptr, ptr %fp, align 8
97+
call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
98+
ret i32 0
99+
}
100+
101+
!3 = !{i64 0, !"_ZTSFvcE.generalized"}
102+
!4 = !{i64 0, !"_ZTSFiE.generalized"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
;; Tests that call site type ids can be extracted and set from type operand
2+
;; bundles.
3+
4+
;; Verify the exact typeId value to ensure it is not garbage but the value
5+
;; computed as the type id from the type operand bundle.
6+
; RUN: llc --call-graph-section -mtriple=mips-linux-gnu < %s -stop-before=finalize-isel -o - | FileCheck %s
7+
8+
define dso_local void @foo(i8 signext %a) !type !3 {
9+
entry:
10+
ret void
11+
}
12+
13+
; CHECK: name: main
14+
define dso_local i32 @main() !type !4 {
15+
entry:
16+
%retval = alloca i32, align 4
17+
%fp = alloca ptr, align 8
18+
store i32 0, ptr %retval, align 4
19+
store ptr @foo, ptr %fp, align 8
20+
%0 = load ptr, ptr %fp, align 8
21+
; CHECK: callSites:
22+
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
23+
; CHECK-NEXT: 7854600665770582568 }
24+
call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
25+
ret i32 0
26+
}
27+
28+
!3 = !{i64 0, !"_ZTSFvcE.generalized"}
29+
!4 = !{i64 0, !"_ZTSFiE.generalized"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
;; Tests that call site type ids can be extracted and set from type operand
2+
;; bundles.
3+
4+
;; Verify the exact typeId value to ensure it is not garbage but the value
5+
;; computed as the type id from the type operand bundle.
6+
; RUN: llc --call-graph-section -mtriple=x86_64-unknown-linux < %s -stop-before=finalize-isel -o - | FileCheck %s
7+
8+
define dso_local void @foo(i8 signext %a) !type !3 {
9+
entry:
10+
ret void
11+
}
12+
13+
; CHECK: name: main
14+
define dso_local i32 @main() !type !4 {
15+
entry:
16+
%retval = alloca i32, align 4
17+
%fp = alloca ptr, align 8
18+
store i32 0, ptr %retval, align 4
19+
store ptr @foo, ptr %fp, align 8
20+
%0 = load ptr, ptr %fp, align 8
21+
; CHECK: callSites:
22+
; CHECK-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: [], typeId:
23+
; CHECK-NEXT: 7854600665770582568 }
24+
call void %0(i8 signext 97) [ "callee_type"(metadata !"_ZTSFvcE.generalized") ]
25+
ret i32 0
26+
}
27+
28+
!3 = !{i64 0, !"_ZTSFvcE.generalized"}
29+
!4 = !{i64 0, !"_ZTSFiE.generalized"}

0 commit comments

Comments
 (0)