Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions llvm/include/llvm/Transforms/IPO/Instrumentor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1072,8 +1072,6 @@ struct CastIO final
InstrumentorIRBuilderTy &IIRB);
static Value *getResultSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB);
static Value *getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB);

static void populate(InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB) {
Expand All @@ -1086,6 +1084,55 @@ struct CastIO final
}
};

/// Instrumentation opportunity for numeric operations. This includes Add, FAdd,
/// Sub, FSub, Mul, FMul, UDiv, FDiv, SDiv, URem, SRem, FRem, Shl, LShr, AShr,
/// And, Or, Xor, and FNeg.
struct NumericIO : public InstructionIO<
Instruction::Add, Instruction::FAdd, Instruction::Sub,
Instruction::FSub, Instruction::Mul, Instruction::FMul,
Instruction::UDiv, Instruction::FDiv, Instruction::SDiv,
Instruction::URem, Instruction::SRem, Instruction::FRem,
Instruction::Shl, Instruction::LShr, Instruction::AShr,
Instruction::And, Instruction::Or, Instruction::Xor,
Instruction::FNeg> {
NumericIO(InstrumentationLocation::KindTy Kind) : InstructionIO(Kind) {}

enum ConfigKind {
PassTypeId,
PassSize,
PassOpcode,
PassResult,
ReplaceResult,
PassLeft,
PassRight,
PassId,
NumConfig,
};

using ConfigTy = BaseConfigTy<ConfigKind>;
ConfigTy Config;

StringRef getName() const override { return "numeric"; }

void init(InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB,
ConfigTy *UserConfig = nullptr);

static Value *getLeft(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB);
static Value *getRight(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB);

static void populate(InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB) {
auto *PreIO =
IConf.allocate<NumericIO>(InstrumentationLocation::INSTRUCTION_PRE);
PreIO->init(IConf, IIRB);
auto *PostIO =
IConf.allocate<NumericIO>(InstrumentationLocation::INSTRUCTION_POST);
PostIO->init(IConf, IIRB);
}
};

} // namespace instrumentor

/// The Instrumentor pass.
Expand Down
72 changes: 67 additions & 5 deletions llvm/lib/Transforms/IPO/Instrumentor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ void InstrumentationConfig::populate(InstrumentorIRBuilderTy &IIRB) {
LoadIO::populate(*this, IIRB);
StoreIO::populate(*this, IIRB);
CastIO::populate(*this, IIRB);
NumericIO::populate(*this, IIRB);
}

void InstrumentationConfig::addChoice(InstrumentationOpportunity &IO,
Expand Down Expand Up @@ -998,7 +999,23 @@ Value *FunctionIO::isMainFunction(Value &V, Type &Ty,
return getCI(&Ty, Fn.getName() == "main");
}

///}
static Value *getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB) {
auto &I = cast<Instruction>(V);
return getCI(&Ty, I.getOpcode());
}

static Value *getTypeId(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB) {
return getCI(&Ty, V.getType()->getTypeID());
}

static Value *getSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB) {
auto &I = cast<Instruction>(V);
auto &DL = I.getDataLayout();
return getCI(&Ty, DL.getTypeStoreSize(V.getType()));
}

/// UnreachableIO
///{
Expand Down Expand Up @@ -1670,10 +1687,55 @@ Value *CastIO::getResultSize(Value &V, Type &Ty, InstrumentationConfig &IConf,
auto &DL = CI.getDataLayout();
return getCI(&Ty, DL.getTypeStoreSize(CI.getDestTy()));
}
///}

Value *CastIO::getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB) {
Value *NumericIO::getLeft(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB) {
auto &I = cast<Instruction>(V);
return getCI(&Ty, I.getOpcode());
return I.getOperand(0);
}

Value *NumericIO::getRight(Value &V, Type &Ty, InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB) {
auto &I = cast<Instruction>(V);
if (I.getNumOperands() > 1)
return I.getOperand(1);
else
return PoisonValue::get(&Ty);
}

void NumericIO::init(InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
if (UserConfig)
Config = UserConfig;
bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
const auto ValArgOpts =
IRTArg::POTENTIALLY_INDIRECT |
(Config.has(PassSize) ? IRTArg::INDIRECT_HAS_SIZE : IRTArg::NONE);
if (Config.has(PassTypeId))
IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "type_id",
"The operation's type id.", IRTArg::NONE,
getTypeId));
if (Config.has(PassSize))
IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "size", "The operation's type size.",
IRTArg::NONE, getSize));
if (Config.has(PassOpcode))
IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "opcode", "The instruction opcode.",
IRTArg::NONE, getOpcode));
if (Config.has(PassLeft))
IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "left",
"The operation's left operand.", ValArgOpts,
getLeft));
if (Config.has(PassRight))
IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "right",
"The operation's right operand. This value is "
"poison for unary operations.",
ValArgOpts, getRight));
if (!IsPRE && Config.has(PassResult))
IRTArgs.push_back(
IRTArg(IIRB.Int64Ty, "result", "Result of the operation.",
IRTArg::REPLACABLE | ValArgOpts, getValue,
Config.has(ReplaceResult) ? replaceValue : nullptr));
addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
IConf.addChoice(*this, IIRB.Ctx);
}
///}
37 changes: 37 additions & 0 deletions llvm/test/Instrumentation/Instrumentor/default_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,23 @@
"opcode.description": "The opcode of the cast instruction.",
"id": true,
"id.description": "A unique ID associated with the given instrumentor call"
},
"numeric": {
"enabled": true,
"filter": "",
"filter.description": "Static property filter to exclude instrumentation.",
"type_id": true,
"type_id.description": "The operation's type id.",
"size": true,
"size.description": "The operation's type size.",
"opcode": true,
"opcode.description": "The instruction opcode.",
"left": true,
"left.description": "The operation's left operand.",
"right": true,
"right.description": "The operation's right operand. This value is poison for unary operations.",
"id": true,
"id.description": "A unique ID associated with the given instrumentor call"
}
},
"instruction_post": {
Expand Down Expand Up @@ -316,6 +333,26 @@
"opcode.description": "The opcode of the cast instruction.",
"id": true,
"id.description": "A unique ID associated with the given instrumentor call"
},
"numeric": {
"enabled": true,
"filter": "",
"filter.description": "Static property filter to exclude instrumentation.",
"type_id": true,
"type_id.description": "The operation's type id.",
"size": true,
"size.description": "The operation's type size.",
"opcode": true,
"opcode.description": "The instruction opcode.",
"left": true,
"left.description": "The operation's left operand.",
"right": true,
"right.description": "The operation's right operand. This value is poison for unary operations.",
"result": true,
"result.replace": true,
"result.description": "Result of the operation.",
"id": true,
"id.description": "A unique ID associated with the given instrumentor call"
}
},
"special_value": {
Expand Down
38 changes: 25 additions & 13 deletions llvm/test/Instrumentation/Instrumentor/module_and_globals.ll
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ entry:
;.
; CHECK-LABEL: define i32 @foo() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: call void @__instrumentor_pre_function(ptr @foo, ptr @__instrumentor_.str.5, i32 0, ptr null, i8 0, i32 12) #[[ATTR0:[0-9]+]]
; CHECK-NEXT: call void @__instrumentor_pre_function(ptr @foo, ptr @__instrumentor_.str.5, i32 0, ptr null, i8 0, i32 14) #[[ATTR0:[0-9]+]]
; CHECK-NEXT: [[Z_SHADOW_LOAD:%.*]] = load ptr, ptr @__instrumentor_shadow.Z, align 8
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @__instrumentor_post_base_pointer_info(ptr [[Z_SHADOW_LOAD]], i32 2, i32 -11) #[[ATTR0]]
; CHECK-NEXT: [[Y_SHADOW_LOAD:%.*]] = load ptr, ptr @__instrumentor_shadow.Y, align 8
Expand All @@ -45,18 +45,30 @@ entry:
; CHECK-NEXT: [[TMP13:%.*]] = call i64 @__instrumentor_post_load(ptr [[X_SHADOW_LOAD]], i32 0, ptr [[TMP2]], i64 [[TMP12]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0, i32 -9) #[[ATTR0]]
; CHECK-NEXT: [[TMP14:%.*]] = trunc i64 [[TMP13]] to i32
; CHECK-NEXT: [[TMP8:%.*]] = call ptr @__instrumentor_pre_load(ptr [[Y_SHADOW_LOAD]], i32 0, ptr [[TMP1]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0, i32 10) #[[ATTR0]]
; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
; CHECK-NEXT: [[TMP18:%.*]] = zext i32 [[TMP9]] to i64
; CHECK-NEXT: [[TMP19:%.*]] = call i64 @__instrumentor_post_load(ptr [[Y_SHADOW_LOAD]], i32 0, ptr [[TMP1]], i64 [[TMP18]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0, i32 -10) #[[ATTR0]]
; CHECK-NEXT: [[TMP20:%.*]] = trunc i64 [[TMP19]] to i32
; CHECK-NEXT: [[TMP21:%.*]] = call ptr @__instrumentor_pre_load(ptr [[Z_SHADOW_LOAD]], i32 0, ptr [[TMP0]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0, i32 11) #[[ATTR0]]
; CHECK-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
; CHECK-NEXT: [[TMP15:%.*]] = zext i32 [[TMP22]] to i64
; CHECK-NEXT: [[TMP16:%.*]] = call i64 @__instrumentor_post_load(ptr [[Z_SHADOW_LOAD]], i32 0, ptr [[TMP0]], i64 [[TMP15]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0, i32 -11) #[[ATTR0]]
; CHECK-NEXT: [[TMP17:%.*]] = trunc i64 [[TMP16]] to i32
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[TMP14]], [[TMP20]]
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[ADD1]], [[TMP17]]
; CHECK-NEXT: call void @__instrumentor_post_function(ptr @foo, ptr @__instrumentor_.str.5, i32 0, ptr null, i8 0, i32 -13) #[[ATTR0]]
; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP8]], align 4
; CHECK-NEXT: [[TMP15:%.*]] = zext i32 [[TMP4]] to i64
; CHECK-NEXT: [[TMP21:%.*]] = call i64 @__instrumentor_post_load(ptr [[Y_SHADOW_LOAD]], i32 0, ptr [[TMP1]], i64 [[TMP15]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0, i32 -10) #[[ATTR0]]
; CHECK-NEXT: [[TMP25:%.*]] = trunc i64 [[TMP21]] to i32
; CHECK-NEXT: [[TMP26:%.*]] = call ptr @__instrumentor_pre_load(ptr [[Z_SHADOW_LOAD]], i32 0, ptr [[TMP0]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0, i32 11) #[[ATTR0]]
; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP26]], align 4
; CHECK-NEXT: [[TMP16:%.*]] = zext i32 [[TMP9]] to i64
; CHECK-NEXT: [[TMP27:%.*]] = call i64 @__instrumentor_post_load(ptr [[Z_SHADOW_LOAD]], i32 0, ptr [[TMP0]], i64 [[TMP16]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0, i32 -11) #[[ATTR0]]
; CHECK-NEXT: [[TMP28:%.*]] = trunc i64 [[TMP27]] to i32
; CHECK-NEXT: [[TMP29:%.*]] = zext i32 [[TMP14]] to i64
; CHECK-NEXT: [[TMP30:%.*]] = zext i32 [[TMP25]] to i64
; CHECK-NEXT: call void @__instrumentor_pre_numeric(i64 12, i32 4, i32 14, i64 [[TMP29]], i64 [[TMP30]], i32 12) #[[ATTR0]]
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP14]], [[TMP25]]
; CHECK-NEXT: [[TMP17:%.*]] = zext i32 [[ADD]] to i64
; CHECK-NEXT: [[TMP18:%.*]] = call i64 @__instrumentor_post_numeric(i64 12, i32 4, i32 14, i64 [[TMP29]], i64 [[TMP30]], i64 [[TMP17]], i32 -12) #[[ATTR0]]
; CHECK-NEXT: [[TMP19:%.*]] = trunc i64 [[TMP18]] to i32
; CHECK-NEXT: [[TMP20:%.*]] = zext i32 [[TMP19]] to i64
; CHECK-NEXT: [[TMP24:%.*]] = zext i32 [[TMP28]] to i64
; CHECK-NEXT: call void @__instrumentor_pre_numeric(i64 12, i32 4, i32 14, i64 [[TMP20]], i64 [[TMP24]], i32 13) #[[ATTR0]]
; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[TMP19]], [[TMP28]]
; CHECK-NEXT: [[TMP22:%.*]] = zext i32 [[ADD3]] to i64
; CHECK-NEXT: [[TMP23:%.*]] = call i64 @__instrumentor_post_numeric(i64 12, i32 4, i32 14, i64 [[TMP20]], i64 [[TMP24]], i64 [[TMP22]], i32 -13) #[[ATTR0]]
; CHECK-NEXT: [[ADD2:%.*]] = trunc i64 [[TMP23]] to i32
; CHECK-NEXT: call void @__instrumentor_post_function(ptr @foo, ptr @__instrumentor_.str.5, i32 0, ptr null, i8 0, i32 -15) #[[ATTR0]]
; CHECK-NEXT: ret i32 [[ADD2]]
;
;
Expand Down
28 changes: 28 additions & 0 deletions llvm/test/Instrumentation/Instrumentor/operations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"configuration": {
"runtime_prefix": "__instrumentor_"
},
"instruction_pre": {
"numeric": {
"enabled": true,
"type_id": true,
"size": true,
"opcode": true,
"left": true,
"right": true,
"id": true
}
},
"instruction_post": {
"numeric": {
"enabled": true,
"type_id": true,
"size": true,
"opcode": true,
"left": true,
"right": true,
"result": true,
"id": true
}
}
}
Loading