Skip to content

Commit e4a0fc1

Browse files
committed
Machine IR Profile
Inject instrumentation code into machine functions to implement machine function coverage and machine basic block coverage. Add a pass in `MIRInstrumentationPass.cpp` that injects pseudo instructions that will be lowered to assembly code. * `MIP_FUNCTION_INSTRUMENTATION_MARKER` * `MIP_FUNCTION_COVERAGE_INSTRUMENTATION` * `MIP_BASIC_BLOCK_COVERAGE_INSTRUMENTATION` Add `MIPSectionEmitter.cpp` to emits two custom sections. * `__llvm_mipraw` * The injected instrumentation code will write profile data to this section. * `__llvm_mipmap` * This section holds function info necessary to parse the profile data we get from runtime. Supported target: ELF, Mach-O, x86_64, arm64, armv7, thumb, thumb2 Differential Revision: https://reviews.llvm.org/D104060
1 parent ecb68f1 commit e4a0fc1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1900
-1
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ADT/SmallVector.h"
2020
#include "llvm/CodeGen/AsmPrinterHandler.h"
2121
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
22+
#include "llvm/CodeGen/MIPSectionEmitter.h"
2223
#include "llvm/CodeGen/MachineFunctionPass.h"
2324
#include "llvm/IR/InlineAsm.h"
2425
#include "llvm/IR/LLVMContext.h"
@@ -96,6 +97,9 @@ class AsmPrinter : public MachineFunctionPass {
9697
/// generating (such as the current section etc).
9798
std::unique_ptr<MCStreamer> OutStreamer;
9899

100+
/// Used to emit special sections for machine instrumentation.
101+
MIPSectionEmitter MIPEmitter;
102+
99103
/// The current machine function.
100104
MachineFunction *MF = nullptr;
101105

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===- MIPSectionEmitter.h --------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CODEGEN_MIPSECTIONEMITTER_H
10+
#define LLVM_CODEGEN_MIPSECTIONEMITTER_H
11+
12+
#include "MachineFunction.h"
13+
#include "MachineOperand.h"
14+
#include "llvm/CodeGen/MachineModuleInfo.h"
15+
#include "llvm/IR/Module.h"
16+
#include "llvm/MC/MCSymbol.h"
17+
#include "llvm/MIP/MIP.h"
18+
#include "llvm/Support/Endian.h"
19+
#include <map>
20+
21+
namespace llvm {
22+
23+
class AsmPrinter;
24+
25+
class MIPSectionEmitter {
26+
public:
27+
explicit MIPSectionEmitter(AsmPrinter &AP);
28+
29+
void runOnMachineFunctionStart(MachineFunction &MF);
30+
void runOnMachineFunctionEnd(MachineFunction &MF);
31+
void runOnFunctionInstrumentationMarker(const MachineInstr &MI);
32+
void runOnBasicBlockInstrumentationMarker(const MachineInstr &MI);
33+
void serializeToMIPRawSection();
34+
void serializeToMIPMapSection();
35+
36+
MCSymbol *getRawProfileSymbol(const MachineFunction &MF);
37+
uint64_t getOffsetToRawBlockProfileSymbol(uint32_t BlockID);
38+
39+
private:
40+
struct MBBInfo {
41+
const MCSymbol *StartSymbol;
42+
};
43+
44+
struct MFInfo {
45+
const Function *Func;
46+
const MCSymbol *StartSymbol;
47+
const MCSymbol *EndSymbol;
48+
MCSymbol *RawProfileSymbol;
49+
uint32_t ControlFlowGraphSignature;
50+
uint32_t NonEntryBasicBlockCount;
51+
52+
// A map from Machine Basic Block IDs to MBBInfo.
53+
DenseMap<uint32_t, MBBInfo> BasicBlockInfos;
54+
};
55+
56+
void emitMIPHeader(MachineProfile::MIPFileType FileType);
57+
void emitMIPFunctionData(const MFInfo &Info);
58+
void emitMIPFunctionInfo(MFInfo &Info);
59+
MCSymbol *getMIPSectionBeginSymbol(Twine MIPSectionName);
60+
61+
AsmPrinter &AP;
62+
MCSymbol *CurrentFunctionEndSymbol;
63+
64+
// A map from a function symbol to its function info.
65+
std::map<const MCSymbol *, MFInfo> FunctionInfos;
66+
};
67+
68+
} // end namespace llvm
69+
70+
#endif // LLVM_CODEGEN_MIPSECTIONEMITTER_H
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===-------------- MIRInstrumentationPass.h ------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CODEGEN_MIRINSTRUMENTATIONPASS_H
10+
#define LLVM_CODEGEN_MIRINSTRUMENTATIONPASS_H
11+
12+
#include "llvm/CodeGen/MachineFunctionPass.h"
13+
#include "llvm/Support/CommandLine.h"
14+
15+
namespace llvm {
16+
17+
class MIRInstrumentation : public MachineFunctionPass {
18+
public:
19+
static char ID;
20+
MIRInstrumentation() : MachineFunctionPass(ID) {}
21+
22+
static cl::opt<bool> EnableMachineInstrumentation;
23+
static cl::opt<bool> EnableMachineFunctionCoverage;
24+
static cl::opt<bool> EnableMachineBasicBlockCoverage;
25+
static cl::opt<bool> EnableMachineCallGraph;
26+
static cl::opt<unsigned> MachineProfileRuntimeBufferSize;
27+
static cl::opt<unsigned> MachineProfileFunctionGroupCount;
28+
static cl::opt<unsigned> MachineProfileSelectedFunctionGroup;
29+
static cl::opt<unsigned> MachineProfileMinInstructionSize;
30+
static std::string LinkUnitName;
31+
static cl::opt<std::string, true> LinkUnitNameOption;
32+
33+
private:
34+
StringRef getPassName() const override {
35+
return "Add instrumentation code to machine functions.";
36+
}
37+
38+
void getAnalysisUsage(AnalysisUsage &AU) const override {
39+
AU.setPreservesCFG();
40+
MachineFunctionPass::getAnalysisUsage(AU);
41+
}
42+
43+
bool doInitialization(Module &M) override;
44+
bool shouldInstrumentMachineFunction(const MachineFunction &MF) const;
45+
bool runOnMachineFunction(MachineFunction &MF) override;
46+
uint32_t getControlFlowGraphSignature(
47+
SmallVectorImpl<MachineBasicBlock *> &MBBs) const;
48+
void getMachineBasicBlocks(MachineFunction &MF,
49+
SmallVectorImpl<MachineBasicBlock *> &MBBs) const;
50+
void runOnMachineBasicBlock(MachineBasicBlock &MBB, uint32_t BlockID);
51+
};
52+
} // namespace llvm
53+
54+
#endif // LLVM_CODEGEN_MIRINSTRUMENTATIONPASS_H

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,7 @@ class MachineInstr
13201320
case TargetOpcode::LIFETIME_START:
13211321
case TargetOpcode::LIFETIME_END:
13221322
case TargetOpcode::PSEUDO_PROBE:
1323+
case TargetOpcode::MIP_FUNCTION_INSTRUMENTATION_MARKER:
13231324
return true;
13241325
}
13251326
}

llvm/include/llvm/CodeGen/Passes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ namespace llvm {
329329
/// the target platform.
330330
extern char &XRayInstrumentationID;
331331

332+
/// This pass injects instrumentation code into machine functions.
333+
extern char &MIRInstrumentationID;
334+
332335
/// This pass inserts FEntry calls
333336
extern char &FEntryInserterID;
334337

llvm/include/llvm/CodeGen/TargetInstrInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,14 @@ class TargetInstrInfo : public MCInstrInfo {
19801980
return MI.getOperand(0);
19811981
}
19821982

1983+
/// Returns a target-specific temporary register that is dead at the
1984+
/// beginning of the given machine basic block for machine profile
1985+
/// instrumentation.
1986+
virtual Register
1987+
getTemporaryMachineProfileRegister(const MachineBasicBlock &MBB) const {
1988+
return MCRegister::NoRegister;
1989+
}
1990+
19831991
private:
19841992
mutable std::unique_ptr<MIRFormatter> Formatter;
19851993
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ void initializeLowerMatrixIntrinsicsLegacyPassPass(PassRegistry &);
278278
void initializeLowerMatrixIntrinsicsMinimalLegacyPassPass(PassRegistry &);
279279
void initializeMIRAddFSDiscriminatorsPass(PassRegistry &);
280280
void initializeMIRCanonicalizerPass(PassRegistry &);
281+
void initializeMIRInstrumentationPass(PassRegistry &);
281282
void initializeMIRNamerPass(PassRegistry &);
282283
void initializeMIRPrintingPassPass(PassRegistry&);
283284
void initializeMachineBlockFrequencyInfoPass(PassRegistry&);

llvm/include/llvm/MC/MCObjectFileInfo.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,15 @@ class MCObjectFileInfo {
163163
/// FaultMap section.
164164
MCSection *FaultMapSection = nullptr;
165165

166+
/// Specials sections for machine instrumentation.
167+
MCSection *MIPRawSection = nullptr;
168+
MCSection *MIPMapSection = nullptr;
169+
170+
/// Special COMDAT sections for machine instrumentation. Only used on ELF
171+
/// targets.
172+
MCSection *MIPRawHeaderComdatSection = nullptr;
173+
MCSection *MIPMapHeaderComdatSection = nullptr;
174+
166175
/// Remarks section.
167176
MCSection *RemarksSection = nullptr;
168177

@@ -340,6 +349,16 @@ class MCObjectFileInfo {
340349

341350
MCSection *getStackMapSection() const { return StackMapSection; }
342351
MCSection *getFaultMapSection() const { return FaultMapSection; }
352+
353+
MCSection *getMIPRawSection() const { return MIPRawSection; }
354+
MCSection *getMIPMapSection() const { return MIPMapSection; }
355+
MCSection *getMIPRawHeaderComdatSection() const {
356+
return MIPRawHeaderComdatSection;
357+
}
358+
MCSection *getMIPMapHeaderComdatSection() const {
359+
return MIPMapHeaderComdatSection;
360+
}
361+
343362
MCSection *getRemarksSection() const { return RemarksSection; }
344363

345364
MCSection *getStackSizesSection(const MCSection &TextSec) const;

llvm/include/llvm/MIP/MIP.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===- MIP.h - Machine IR Profile -------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_MIP_MIP_H
10+
#define LLVM_MIP_MIP_H
11+
12+
namespace llvm {
13+
namespace MachineProfile {
14+
15+
#include "llvm/MIP/MIPData.inc"
16+
17+
} // namespace MachineProfile
18+
} // namespace llvm
19+
20+
#endif // LLVM_MIP_MIP_H

llvm/include/llvm/MIP/MIPData.inc

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===-- MIPData.inc - machine ir profile runtime structures -------*- C -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains definitions and data structures that are shared between
10+
// the runtime and the compiler. It lives in two locations that need to stay in
11+
// sync.
12+
// + llvm/include/llvm/MIP/MIPData.inc
13+
// + compiler-rt/include/mip/MIPData.inc
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef MIP_DATA_DEFINED
18+
19+
#include <stdint.h>
20+
21+
#ifndef MIP_DATA_INC
22+
#define MIP_DATA_INC
23+
24+
#define MIP_SIMPLE_QUOTE(x) #x
25+
#define MIP_QUOTE(x) MIP_SIMPLE_QUOTE(x)
26+
#define MIP_SIMPLE_CONCAT(x,y) x ## y
27+
#define MIP_CONCAT(x,y) MIP_SIMPLE_CONCAT(x,y)
28+
29+
#define MIP_RAW_SECTION __llvm_mipraw
30+
#define MIP_MAP_SECTION __llvm_mipmap
31+
#define MIP_RUNTIME_SYMBOL __llvm_mip_runtime
32+
33+
#define MIP_RAW_SECTION_NAME MIP_QUOTE(MIP_RAW_SECTION)
34+
#define MIP_MAP_SECTION_NAME MIP_QUOTE(MIP_MAP_SECTION)
35+
#define MIP_RUNTIME_SYMBOL_NAME MIP_QUOTE(MIP_RUNTIME_SYMBOL)
36+
37+
// MIP magic value in little endian format.
38+
// \251 M I P
39+
// 0xFB 0x4D 0x49 0x50
40+
#define MIP_MAGIC_VALUE (0x50494DFB)
41+
#define MIP_VERSION (8)
42+
43+
typedef enum {
44+
MIP_FILE_TYPE_RAW = 0x0001, // .mipraw
45+
MIP_FILE_TYPE_MAP = 0x0002, // .mipmap
46+
MIP_FILE_TYPE_PROFILE = 0x0003, // .mip
47+
MIP_FILE_TYPE_CALL_EDGE_SAMPLES = 0x0004, // .mipret
48+
} MIPFileType;
49+
50+
typedef enum {
51+
MIP_PROFILE_TYPE_FUNCTION_COVERAGE = 1 << 0,
52+
MIP_PROFILE_TYPE_BLOCK_COVERAGE = 1 << 1,
53+
MIP_PROFILE_TYPE_FUNCTION_TIMESTAMP = 1 << 2,
54+
MIP_PROFILE_TYPE_FUNCTION_CALL_COUNT = 1 << 3,
55+
MIP_PROFILE_TYPE_RETURN_ADDRESS = 1 << 4,
56+
} MIPProfileType;
57+
58+
typedef struct {
59+
uint32_t Magic;
60+
uint16_t Version;
61+
uint16_t FileType;
62+
uint32_t ProfileType;
63+
uint32_t ModuleHash;
64+
uint32_t Reserved;
65+
uint32_t OffsetToData;
66+
} MIPHeader;
67+
68+
typedef struct {
69+
uint32_t CalleeProfileDataOffset;
70+
uint32_t SectionRelativeReturnAddress;
71+
} CallEdge_t;
72+
73+
#endif // MIP_DATA_INC
74+
75+
#else // MIP_DATA_INC
76+
#undef MIP_DATA_DEFINED
77+
#endif // MIP_DATA_DEFINED

0 commit comments

Comments
 (0)