[llvm] [Instrumentor] Add atomicrmw instrumentation opportunity (PR #229369)
Ethan Luis McDonough via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 6 03:17:54 PDT 2026
https://github.com/EthanLuisMcDonough updated https://github.com/llvm/llvm-project/pull/229369
>From a5801be4d964976f83c5376f1fcfe9072d56f362 Mon Sep 17 00:00:00 2001
From: Ethan Luis McDonough <ethanluismcdonough at gmail.com>
Date: Tue, 6 Oct 2026 03:17:33 -0700
Subject: [PATCH] Add atomicrmw IO
---
.../llvm/Transforms/IPO/Instrumentor.h | 100 ++++++++++
llvm/lib/Transforms/IPO/Instrumentor.cpp | 185 ++++++++++++++++++
.../Instrumentation/Instrumentor/atomicrmw.ll | 40 ++++
.../Instrumentor/atomicrmw_config.json | 54 +++++
.../Instrumentor/atomicrmw_simple_config.json | 41 ++++
.../Instrumentor/default_config.json | 66 +++++++
.../Instrumentation/Instrumentor/default_rt.c | 19 ++
.../Instrumentor/rt_config.json | 66 +++++++
8 files changed, 571 insertions(+)
create mode 100644 llvm/test/Instrumentation/Instrumentor/atomicrmw.ll
create mode 100644 llvm/test/Instrumentation/Instrumentor/atomicrmw_config.json
create mode 100644 llvm/test/Instrumentation/Instrumentor/atomicrmw_simple_config.json
diff --git a/llvm/include/llvm/Transforms/IPO/Instrumentor.h b/llvm/include/llvm/Transforms/IPO/Instrumentor.h
index 5da53ac0ada15b8..7a2d3f19cd43806 100644
--- a/llvm/include/llvm/Transforms/IPO/Instrumentor.h
+++ b/llvm/include/llvm/Transforms/IPO/Instrumentor.h
@@ -1119,6 +1119,106 @@ struct LoadIO : public InstructionIO<Instruction::Load> {
}
};
+/// The instrumentation opportunity for atomic RMW instructions.
+struct AtomicRMWIO final : public InstructionIO<Instruction::AtomicRMW> {
+ AtomicRMWIO(InstrumentationLocation::KindTy Kind) : InstructionIO(Kind) {}
+
+ /// The selector of arguments for atomic RMW opportunities.
+ ///{
+ enum ConfigKind {
+ PassPointer = 0,
+ ReplacePointer,
+ PassPointerAS,
+ PassBasePointerInfo,
+ PassValOperand,
+ PassPrevValue,
+ ReplacePrevValue,
+ PassValueSize,
+ PassAlignment,
+ PassValueTypeId,
+ PassValueSubTypeId,
+ PassAtomicityOrdering,
+ PassSyncScopeId,
+ PassIsVolatile,
+ PassOperation,
+ PassId,
+ NumConfig,
+ };
+
+ using ConfigTy = BaseConfigTy<ConfigKind>;
+ ConfigTy Config;
+ ///}
+
+ /// Get the type of the modified value.
+ Type *getValueType(InstrumentorIRBuilderTy &IIRB) const {
+ return IIRB.Int64Ty;
+ }
+
+ /// Initialize the atomic RMW opportunity using the instrumentation config \p
+ /// IConf and the user config \p UserConfig.
+ LLVM_ABI void init(InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB,
+ ConfigTy *UserConfig = nullptr);
+
+ /// Getters and setters for the arguments of the instrumentation function for
+ /// the atomic RMW opportunity.
+ ///{
+ LLVM_ABI static Value *getPointer(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *setPointer(Value &V, Value &NewV,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getPointerAS(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getBasePointerInfo(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getValue(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getValueSize(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getAlignment(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getValueTypeId(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getValueSubTypeId(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getAtomicityOrdering(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getSyncScopeId(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getValOperand(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *getOperation(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ LLVM_ABI static Value *isVolatile(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB);
+ ///}
+
+ /// Create the atomic RMW opportunities for PRE and POST positions.
+ static void populate(InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto *PreIO =
+ IConf.allocate<AtomicRMWIO>(InstrumentationLocation::INSTRUCTION_PRE);
+ PreIO->init(IConf, IIRB);
+ auto *PostIO =
+ IConf.allocate<AtomicRMWIO>(InstrumentationLocation::INSTRUCTION_POST);
+ PostIO->init(IConf, IIRB);
+ }
+};
+
/// The instrumentation opportunity for type cast instructions.
/// This includes PtrToInt, IntToPtr, Trunc, ZExt, SExt, FPToUI, FPToSI,
/// UIToFP, SIToFP, FPTrunc, FPExt, AddrSpaceCast, and BitCast.
diff --git a/llvm/lib/Transforms/IPO/Instrumentor.cpp b/llvm/lib/Transforms/IPO/Instrumentor.cpp
index 393e90fdf7d0273..27b730f6be664f2 100644
--- a/llvm/lib/Transforms/IPO/Instrumentor.cpp
+++ b/llvm/lib/Transforms/IPO/Instrumentor.cpp
@@ -638,6 +638,7 @@ void InstrumentationConfig::populate(InstrumentorIRBuilderTy &IIRB) {
UnreachableIO::populate(*this, IIRB);
LoadIO::populate(*this, IIRB);
StoreIO::populate(*this, IIRB);
+ AtomicRMWIO::populate(*this, IIRB);
CastIO::populate(*this, IIRB);
NumericIO::populate(*this, IIRB);
CompareIO::populate(*this, IIRB);
@@ -1505,6 +1506,190 @@ Value *LoadIO::isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf,
return getCI(&Ty, LI.isVolatile());
}
+void AtomicRMWIO::init(InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
+ bool IsPRE = getLocationKind() == InstrumentationLocation::INSTRUCTION_PRE;
+ if (UserConfig)
+ Config = *UserConfig;
+ if (Config.has(PassPointer)) {
+ IRTArgs.push_back(
+ IRTArg(IIRB.PtrTy, "pointer", "The accessed pointer.",
+ ((IsPRE && Config.has(ReplacePointer)) ? IRTArg::REPLACABLE
+ : IRTArg::NONE),
+ getPointer, setPointer));
+ }
+ if (Config.has(PassPointerAS)) {
+ IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "pointer_as",
+ "The address space of the accessed pointer.",
+ IRTArg::NONE, getPointerAS));
+ }
+ if (Config.has(PassBasePointerInfo)) {
+ IRTArgs.push_back(IRTArg(IIRB.PtrTy, "base_pointer_info",
+ "The runtime provided base pointer info.",
+ IRTArg::NONE, getBasePointerInfo));
+ }
+ if (Config.has(PassValOperand)) {
+ IRTArgs.push_back(
+ IRTArg(IIRB.Int64Ty, "val_operand",
+ "The operand being atomically applied to the stored value.",
+ IRTArg::POTENTIALLY_INDIRECT |
+ (Config.has(PassValueSize) ? IRTArg::INDIRECT_HAS_SIZE
+ : IRTArg::NONE),
+ getValOperand));
+ }
+ if (!IsPRE && Config.has(PassPrevValue)) {
+ IRTArgs.push_back(IRTArg(
+ getValueType(IIRB), "prev_value", "The unmodified old value.",
+ Config.has(ReplacePrevValue)
+ ? IRTArg::REPLACABLE | IRTArg::POTENTIALLY_INDIRECT |
+ (Config.has(PassValueSize) ? IRTArg::INDIRECT_HAS_SIZE
+ : IRTArg::NONE)
+ : IRTArg::NONE,
+ getValue, Config.has(ReplacePrevValue) ? replaceValue : nullptr));
+ }
+ if (Config.has(PassValueSize)) {
+ IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "value_size",
+ "The size of the modified value.", IRTArg::NONE,
+ getValueSize));
+ }
+ if (Config.has(PassAlignment)) {
+ IRTArgs.push_back(IRTArg(IIRB.Int64Ty, "alignment",
+ "The known access alignment.", IRTArg::NONE,
+ getAlignment));
+ }
+ if (Config.has(PassValueTypeId)) {
+ IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_type_id",
+ "The type id of the modified value.",
+ IRTArg::TYPEID, getValueTypeId));
+ }
+ if (Config.has(PassValueSubTypeId)) {
+ IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "value_sub_type_id",
+ "The sub type id of the modified value (for "
+ "arrays and vectors, or -1).",
+ IRTArg::TYPEID, getValueSubTypeId));
+ }
+ if (Config.has(PassAtomicityOrdering)) {
+ IRTArgs.push_back(
+ IRTArg(IIRB.Int32Ty, "atomicity_ordering",
+ "The atomicity ordering of the atomic RMW instruction.",
+ IRTArg::NONE, getAtomicityOrdering));
+ }
+ if (Config.has(PassSyncScopeId)) {
+ IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "sync_scope_id",
+ "The sync scope id of the operation.",
+ IRTArg::NONE, getSyncScopeId));
+ }
+ if (Config.has(PassOperation)) {
+ IRTArgs.push_back(IRTArg(IIRB.Int32Ty, "operation",
+ "The atomic RMW instruction's operation id.",
+ IRTArg::NONE, getOperation));
+ }
+ if (Config.has(PassIsVolatile)) {
+ IRTArgs.push_back(IRTArg(IIRB.Int8Ty, "is_volatile",
+ "Flag indicating a volatile operation.",
+ IRTArg::NONE, isVolatile));
+ }
+
+ addCommonArgs(IConf, IIRB.Ctx, Config.has(PassId));
+ IConf.addChoice(*this, IIRB.Ctx);
+}
+
+Value *AtomicRMWIO::getPointer(Value &V, Type &Ty, InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return AI.getPointerOperand();
+}
+
+Value *AtomicRMWIO::setPointer(Value &V, Value &NewV,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ AI.setOperand(AI.getPointerOperandIndex(), &NewV);
+ return &AI;
+}
+
+Value *AtomicRMWIO::getPointerAS(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return getCI(&Ty, AI.getPointerAddressSpace());
+}
+
+Value *AtomicRMWIO::getBasePointerInfo(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return IConf.getBasePointerInfo(*AI.getPointerOperand(), IIRB);
+}
+
+Value *AtomicRMWIO::getValue(Value &V, Type &Ty, InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ return &V;
+}
+
+Value *AtomicRMWIO::getValueSize(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ auto &DL = AI.getDataLayout();
+ return getCI(&Ty, DL.getTypeStoreSize(AI.getType()));
+}
+
+Value *AtomicRMWIO::getAlignment(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return getCI(&Ty, AI.getAlign().value());
+}
+
+Value *AtomicRMWIO::getValueTypeId(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return getCI(&Ty, AI.getType()->getTypeID());
+}
+
+Value *AtomicRMWIO::getValueSubTypeId(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return getSubTypeID(*AI.getType(), Ty);
+}
+
+Value *AtomicRMWIO::getAtomicityOrdering(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return getCI(&Ty, uint64_t(AI.getOrdering()));
+}
+
+Value *AtomicRMWIO::getSyncScopeId(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return getCI(&Ty, uint64_t(AI.getSyncScopeID()));
+}
+
+Value *AtomicRMWIO::getValOperand(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return AI.getValOperand();
+}
+
+Value *AtomicRMWIO::getOperation(Value &V, Type &Ty,
+ InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return getCI(&Ty, AI.getOperation());
+}
+
+Value *AtomicRMWIO::isVolatile(Value &V, Type &Ty, InstrumentationConfig &IConf,
+ InstrumentorIRBuilderTy &IIRB) {
+ auto &AI = cast<AtomicRMWInst>(V);
+ return getCI(&Ty, AI.isVolatile());
+}
+
void BasePointerIO::init(InstrumentationConfig &IConf,
InstrumentorIRBuilderTy &IIRB, ConfigTy *UserConfig) {
if (UserConfig)
diff --git a/llvm/test/Instrumentation/Instrumentor/atomicrmw.ll b/llvm/test/Instrumentation/Instrumentor/atomicrmw.ll
new file mode 100644
index 000000000000000..a74ca2b7c40762f
--- /dev/null
+++ b/llvm/test/Instrumentation/Instrumentor/atomicrmw.ll
@@ -0,0 +1,40 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=instrumentor -instrumentor-read-config-files=%S/atomicrmw_config.json -S 2>&1 | FileCheck %s
+; RUN: opt < %s -passes=instrumentor -instrumentor-read-config-files=%S/atomicrmw_simple_config.json -S 2>&1 | FileCheck %s --check-prefix=SIMPLE
+
+define i64 @foo(ptr %p, i64 %val) {
+; CHECK-LABEL: define i64 @foo(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[VAL:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = call ptr @__instrumentor_post_base_pointer_info(ptr [[P]], i32 0, i32 -1) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT: [[TMP1:%.*]] = call ptr @__instrumentor_pre_atomicrmw(ptr [[P]], i32 0, ptr [[TMP0]], i64 [[VAL]], i64 8, i64 8, i32 12, i32 -1, i32 2, i8 1, i32 3, i8 0, i32 1) #[[ATTR0]]
+; CHECK-NEXT: [[RMW_OLD1:%.*]] = atomicrmw and ptr [[TMP1]], i64 [[VAL]] monotonic, align 8
+; CHECK-NEXT: [[TMP2:%.*]] = call i64 @__instrumentor_post_atomicrmw(ptr [[P]], i32 0, ptr [[TMP0]], i64 [[VAL]], i64 [[RMW_OLD1]], i64 8, i64 8, i32 12, i32 -1, i32 2, i8 1, i32 3, i8 0, i32 -1) #[[ATTR0]]
+; CHECK-NEXT: [[TMP3:%.*]] = call ptr @__instrumentor_pre_atomicrmw(ptr [[P]], i32 0, ptr [[TMP0]], i64 [[TMP2]], i64 8, i64 8, i32 12, i32 -1, i32 7, i8 1, i32 1, i8 1, i32 2) #[[ATTR0]]
+; CHECK-NEXT: [[RMW_OLD2:%.*]] = atomicrmw volatile add ptr [[TMP3]], i64 [[TMP2]] seq_cst, align 8
+; CHECK-NEXT: [[TMP4:%.*]] = call i64 @__instrumentor_post_atomicrmw(ptr [[P]], i32 0, ptr [[TMP0]], i64 [[TMP2]], i64 [[RMW_OLD2]], i64 8, i64 8, i32 12, i32 -1, i32 7, i8 1, i32 1, i8 1, i32 -2) #[[ATTR0]]
+; CHECK-NEXT: [[TMP5:%.*]] = call ptr @__instrumentor_pre_atomicrmw(ptr [[P]], i32 0, ptr [[TMP0]], i64 [[TMP4]], i64 8, i64 8, i32 12, i32 -1, i32 4, i8 1, i32 5, i8 0, i32 3) #[[ATTR0]]
+; CHECK-NEXT: [[RMW_OLD3:%.*]] = atomicrmw or ptr [[TMP5]], i64 [[TMP4]] acquire, align 8
+; CHECK-NEXT: [[TMP6:%.*]] = call i64 @__instrumentor_post_atomicrmw(ptr [[P]], i32 0, ptr [[TMP0]], i64 [[TMP4]], i64 [[RMW_OLD3]], i64 8, i64 8, i32 12, i32 -1, i32 4, i8 1, i32 5, i8 0, i32 -3) #[[ATTR0]]
+; CHECK-NEXT: ret i64 [[TMP6]]
+;
+; SIMPLE-LABEL: define i64 @foo(
+; SIMPLE-SAME: ptr [[P:%.*]], i64 [[VAL:%.*]]) {
+; SIMPLE-NEXT: [[ENTRY:.*:]]
+; SIMPLE-NEXT: call void @__instrumentor_pre_atomicrmw(ptr [[P]], i32 0, i64 [[VAL]], i64 8, i64 8, i32 12, i32 -1, i32 2, i8 1, i32 3, i8 0, i32 1) #[[ATTR0:[0-9]+]]
+; SIMPLE-NEXT: [[RMW_OLD1:%.*]] = atomicrmw and ptr [[P]], i64 [[VAL]] monotonic, align 8
+; SIMPLE-NEXT: call void @__instrumentor_post_atomicrmw(ptr [[P]], i32 0, i64 [[VAL]], i64 8, i64 8, i32 12, i32 -1, i32 2, i8 1, i32 3, i8 0, i32 -1) #[[ATTR0]]
+; SIMPLE-NEXT: call void @__instrumentor_pre_atomicrmw(ptr [[P]], i32 0, i64 [[RMW_OLD1]], i64 8, i64 8, i32 12, i32 -1, i32 7, i8 1, i32 1, i8 1, i32 2) #[[ATTR0]]
+; SIMPLE-NEXT: [[RMW_OLD2:%.*]] = atomicrmw volatile add ptr [[P]], i64 [[RMW_OLD1]] seq_cst, align 8
+; SIMPLE-NEXT: call void @__instrumentor_post_atomicrmw(ptr [[P]], i32 0, i64 [[RMW_OLD1]], i64 8, i64 8, i32 12, i32 -1, i32 7, i8 1, i32 1, i8 1, i32 -2) #[[ATTR0]]
+; SIMPLE-NEXT: call void @__instrumentor_pre_atomicrmw(ptr [[P]], i32 0, i64 [[RMW_OLD2]], i64 8, i64 8, i32 12, i32 -1, i32 4, i8 1, i32 5, i8 0, i32 3) #[[ATTR0]]
+; SIMPLE-NEXT: [[RMW_OLD3:%.*]] = atomicrmw or ptr [[P]], i64 [[RMW_OLD2]] acquire, align 8
+; SIMPLE-NEXT: call void @__instrumentor_post_atomicrmw(ptr [[P]], i32 0, i64 [[RMW_OLD2]], i64 8, i64 8, i32 12, i32 -1, i32 4, i8 1, i32 5, i8 0, i32 -3) #[[ATTR0]]
+; SIMPLE-NEXT: ret i64 [[RMW_OLD3]]
+;
+entry:
+ %rmw.old1 = atomicrmw and ptr %p, i64 %val monotonic, align 8
+ %rmw.old2 = atomicrmw volatile add ptr %p, i64 %rmw.old1 seq_cst
+ %rmw.old3 = atomicrmw or ptr %p, i64 %rmw.old2 acquire
+ ret i64 %rmw.old3
+}
diff --git a/llvm/test/Instrumentation/Instrumentor/atomicrmw_config.json b/llvm/test/Instrumentation/Instrumentor/atomicrmw_config.json
new file mode 100644
index 000000000000000..b1c6fb9e632ec2b
--- /dev/null
+++ b/llvm/test/Instrumentation/Instrumentor/atomicrmw_config.json
@@ -0,0 +1,54 @@
+{
+ "configuration": {
+ "runtime_prefix": "__instrumentor_",
+ "demangle_function_names": true
+ },
+ "instruction_pre": {
+ "atomicrmw": {
+ "enabled": true,
+ "pointer": true,
+ "pointer.replace": true,
+ "pointer_as": true,
+ "base_pointer_info": true,
+ "val_operand": true,
+ "value_size": true,
+ "alignment": true,
+ "value_type_id": true,
+ "value_sub_type_id": true,
+ "atomicity_ordering": true,
+ "sync_scope_id": true,
+ "operation": true,
+ "is_volatile": true,
+ "id": true
+ }
+ },
+ "instruction_post": {
+ "atomicrmw": {
+ "enabled": true,
+ "pointer": true,
+ "pointer_as": true,
+ "base_pointer_info": true,
+ "val_operand": true,
+ "prev_value": true,
+ "prev_value.replace": true,
+ "value_size": true,
+ "alignment": true,
+ "value_type_id": true,
+ "value_sub_type_id": true,
+ "atomicity_ordering": true,
+ "sync_scope_id": true,
+ "operation": true,
+ "is_volatile": true,
+ "id": true
+ }
+ },
+ "special_value": {
+ "base_pointer_info": {
+ "enabled": true,
+ "base_pointer": true,
+ "base_pointer.replace": true,
+ "base_pointer_kind": true,
+ "id": true
+ }
+ }
+}
diff --git a/llvm/test/Instrumentation/Instrumentor/atomicrmw_simple_config.json b/llvm/test/Instrumentation/Instrumentor/atomicrmw_simple_config.json
new file mode 100644
index 000000000000000..65e9cd451246da4
--- /dev/null
+++ b/llvm/test/Instrumentation/Instrumentor/atomicrmw_simple_config.json
@@ -0,0 +1,41 @@
+{
+ "configuration": {
+ "runtime_prefix": "__instrumentor_",
+ "demangle_function_names": true
+ },
+ "instruction_pre": {
+ "atomicrmw": {
+ "enabled": true,
+ "pointer": true,
+ "pointer_as": true,
+ "val_operand": true,
+ "value_size": true,
+ "alignment": true,
+ "value_type_id": true,
+ "value_sub_type_id": true,
+ "atomicity_ordering": true,
+ "sync_scope_id": true,
+ "operation": true,
+ "is_volatile": true,
+ "id": true
+ }
+ },
+ "instruction_post": {
+ "atomicrmw": {
+ "enabled": true,
+ "pointer": true,
+ "pointer_as": true,
+ "val_operand": true,
+ "value": true,
+ "value_size": true,
+ "alignment": true,
+ "value_type_id": true,
+ "value_sub_type_id": true,
+ "atomicity_ordering": true,
+ "sync_scope_id": true,
+ "operation": true,
+ "is_volatile": true,
+ "id": true
+ }
+ }
+}
diff --git a/llvm/test/Instrumentation/Instrumentor/default_config.json b/llvm/test/Instrumentation/Instrumentor/default_config.json
index fc712537e5e224c..220f67c15836c01 100644
--- a/llvm/test/Instrumentation/Instrumentor/default_config.json
+++ b/llvm/test/Instrumentation/Instrumentor/default_config.json
@@ -213,6 +213,38 @@
"id": true,
"id.description": "A unique ID associated with the given instrumentor call"
},
+ "atomicrmw": {
+ "enabled": true,
+ "filter": "",
+ "filter.description": "Static property filter to exclude instrumentation.",
+ "pointer": true,
+ "pointer.replace": true,
+ "pointer.description": "The accessed pointer.",
+ "pointer_as": true,
+ "pointer_as.description": "The address space of the accessed pointer.",
+ "base_pointer_info": true,
+ "base_pointer_info.description": "The runtime provided base pointer info.",
+ "val_operand": true,
+ "val_operand.description": "The operand being atomically applied to the stored value.",
+ "value_size": true,
+ "value_size.description": "The size of the modified value.",
+ "alignment": true,
+ "alignment.description": "The known access alignment.",
+ "value_type_id": true,
+ "value_type_id.description": "The type id of the modified value.",
+ "value_sub_type_id": true,
+ "value_sub_type_id.description": "The sub type id of the modified value (for arrays and vectors, or -1).",
+ "atomicity_ordering": true,
+ "atomicity_ordering.description": "The atomicity ordering of the atomic RMW instruction.",
+ "sync_scope_id": true,
+ "sync_scope_id.description": "The sync scope id of the operation.",
+ "operation": true,
+ "operation.description": "The atomic RMW instruction's operation id.",
+ "is_volatile": true,
+ "is_volatile.description": "Flag indicating a volatile operation.",
+ "id": true,
+ "id.description": "A unique ID associated with the given instrumentor call"
+ },
"cast": {
"enabled": true,
"filter": "",
@@ -353,6 +385,40 @@
"id": true,
"id.description": "A unique ID associated with the given instrumentor call"
},
+ "atomicrmw": {
+ "enabled": true,
+ "filter": "",
+ "filter.description": "Static property filter to exclude instrumentation.",
+ "pointer": true,
+ "pointer.description": "The accessed pointer.",
+ "pointer_as": true,
+ "pointer_as.description": "The address space of the accessed pointer.",
+ "base_pointer_info": true,
+ "base_pointer_info.description": "The runtime provided base pointer info.",
+ "val_operand": true,
+ "val_operand.description": "The operand being atomically applied to the stored value.",
+ "prev_value": true,
+ "prev_value.replace": true,
+ "prev_value.description": "The unmodified old value.",
+ "value_size": true,
+ "value_size.description": "The size of the modified value.",
+ "alignment": true,
+ "alignment.description": "The known access alignment.",
+ "value_type_id": true,
+ "value_type_id.description": "The type id of the modified value.",
+ "value_sub_type_id": true,
+ "value_sub_type_id.description": "The sub type id of the modified value (for arrays and vectors, or -1).",
+ "atomicity_ordering": true,
+ "atomicity_ordering.description": "The atomicity ordering of the atomic RMW instruction.",
+ "sync_scope_id": true,
+ "sync_scope_id.description": "The sync scope id of the operation.",
+ "operation": true,
+ "operation.description": "The atomic RMW instruction's operation id.",
+ "is_volatile": true,
+ "is_volatile.description": "Flag indicating a volatile operation.",
+ "id": true,
+ "id.description": "A unique ID associated with the given instrumentor call"
+ },
"cast": {
"enabled": true,
"filter": "",
diff --git a/llvm/test/Instrumentation/Instrumentor/default_rt.c b/llvm/test/Instrumentation/Instrumentor/default_rt.c
index bce5fa9c63a1e18..3d3caf28f815b77 100644
--- a/llvm/test/Instrumentation/Instrumentor/default_rt.c
+++ b/llvm/test/Instrumentation/Instrumentor/default_rt.c
@@ -97,6 +97,16 @@ void *__instrumentor_pre_store_ind(void *pointer, int32_t pointer_as, void *base
return pointer;
}
+void *__instrumentor_pre_atomicrmw(void *pointer, int32_t pointer_as, void *base_pointer_info, int64_t val_operand, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t value_sub_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int32_t operation, int8_t is_volatile, int32_t id) {
+ printf("atomicrmw pre -- pointer: %p, pointer_as: %" PRId32 ", base_pointer_info: %p, val_operand: %" PRId64 ", value_size: %" PRId64 ", alignment: %" PRId64 ", value_type_id: %s, value_sub_type_id: %s, atomicity_ordering: %" PRId32 ", sync_scope_id: %" PRId32 ", operation: %" PRId32 ", is_volatile: %" PRId32 ", id: %" PRId32 "\n", pointer, pointer_as, base_pointer_info, val_operand, value_size, alignment, getLLVMTypeIDName(value_type_id), getLLVMTypeIDName(value_sub_type_id), atomicity_ordering, sync_scope_id, operation, is_volatile, id);
+ return pointer;
+}
+
+void *__instrumentor_pre_atomicrmw_ind(void *pointer, int32_t pointer_as, void *base_pointer_info, int64_t *val_operand_ptr, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t value_sub_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int32_t operation, int8_t is_volatile, int32_t id) {
+ printf("atomicrmw pre -- pointer: %p, pointer_as: %" PRId32 ", base_pointer_info: %p, val_operand: %p, value_size: %" PRId64 ", alignment: %" PRId64 ", value_type_id: %s, value_sub_type_id: %s, atomicity_ordering: %" PRId32 ", sync_scope_id: %" PRId32 ", operation: %" PRId32 ", is_volatile: %" PRId32 ", id: %" PRId32 "\n", pointer, pointer_as, base_pointer_info, val_operand_ptr, value_size, alignment, getLLVMTypeIDName(value_type_id), getLLVMTypeIDName(value_sub_type_id), atomicity_ordering, sync_scope_id, operation, is_volatile, id);
+ return pointer;
+}
+
void __instrumentor_pre_cast(int64_t input, int32_t input_type_id, int32_t input_sub_type_id, int32_t input_size, int32_t result_type_id, int32_t result_sub_type_id, int32_t result_size, int32_t opcode, int32_t id) {
printf("cast pre -- input: %" PRId64 ", input_type_id: %s, input_sub_type_id: %s, input_size: %" PRId32 ", result_type_id: %s, result_sub_type_id: %s, result_size: %" PRId32 ", opcode: %" PRId32 ", id: %" PRId32 "\n", input, getLLVMTypeIDName(input_type_id), getLLVMTypeIDName(input_sub_type_id), input_size, getLLVMTypeIDName(result_type_id), getLLVMTypeIDName(result_sub_type_id), result_size, opcode, id);
}
@@ -127,6 +137,15 @@ void __instrumentor_post_store_ind(void *pointer, int32_t pointer_as, void *base
printf("store post -- pointer: %p, pointer_as: %" PRId32 ", base_pointer_info: %p, value: %p, value_size: %" PRId64 ", alignment: %" PRId64 ", value_type_id: %s, value_sub_type_id: %s, atomicity_ordering: %" PRId32 ", sync_scope_id: %" PRId32 ", is_volatile: %" PRId32 ", id: %" PRId32 "\n", pointer, pointer_as, base_pointer_info, value_ptr, value_size, alignment, getLLVMTypeIDName(value_type_id), getLLVMTypeIDName(value_sub_type_id), atomicity_ordering, sync_scope_id, is_volatile, id);
}
+int64_t __instrumentor_post_atomicrmw(void *pointer, int32_t pointer_as, void *base_pointer_info, int64_t val_operand, int64_t prev_value, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t value_sub_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int32_t operation, int8_t is_volatile, int32_t id) {
+ printf("atomicrmw post -- pointer: %p, pointer_as: %" PRId32 ", base_pointer_info: %p, val_operand: %" PRId64 ", prev_value: %" PRId64 ", value_size: %" PRId64 ", alignment: %" PRId64 ", value_type_id: %s, value_sub_type_id: %s, atomicity_ordering: %" PRId32 ", sync_scope_id: %" PRId32 ", operation: %" PRId32 ", is_volatile: %" PRId32 ", id: %" PRId32 "\n", pointer, pointer_as, base_pointer_info, val_operand, prev_value, value_size, alignment, getLLVMTypeIDName(value_type_id), getLLVMTypeIDName(value_sub_type_id), atomicity_ordering, sync_scope_id, operation, is_volatile, id);
+ return prev_value;
+}
+
+void __instrumentor_post_atomicrmw_ind(void *pointer, int32_t pointer_as, void *base_pointer_info, int64_t *val_operand_ptr, int64_t *prev_value_ptr, int64_t value_size, int64_t alignment, int32_t value_type_id, int32_t value_sub_type_id, int32_t atomicity_ordering, int8_t sync_scope_id, int32_t operation, int8_t is_volatile, int32_t id) {
+ printf("atomicrmw post -- pointer: %p, pointer_as: %" PRId32 ", base_pointer_info: %p, val_operand: %p, prev_value: %p, value_size: %" PRId64 ", alignment: %" PRId64 ", value_type_id: %s, value_sub_type_id: %s, atomicity_ordering: %" PRId32 ", sync_scope_id: %" PRId32 ", operation: %" PRId32 ", is_volatile: %" PRId32 ", id: %" PRId32 "\n", pointer, pointer_as, base_pointer_info, val_operand_ptr, prev_value_ptr, value_size, alignment, getLLVMTypeIDName(value_type_id), getLLVMTypeIDName(value_sub_type_id), atomicity_ordering, sync_scope_id, operation, is_volatile, id);
+}
+
int64_t __instrumentor_post_cast(int64_t input, int32_t input_type_id, int32_t input_sub_type_id, int32_t input_size, int64_t result, int32_t result_type_id, int32_t result_sub_type_id, int32_t result_size, int32_t opcode, int32_t id) {
printf("cast post -- input: %" PRId64 ", input_type_id: %s, input_sub_type_id: %s, input_size: %" PRId32 ", result: %" PRId64 ", result_type_id: %s, result_sub_type_id: %s, result_size: %" PRId32 ", opcode: %" PRId32 ", id: %" PRId32 "\n", input, getLLVMTypeIDName(input_type_id), getLLVMTypeIDName(input_sub_type_id), input_size, result, getLLVMTypeIDName(result_type_id), getLLVMTypeIDName(result_sub_type_id), result_size, opcode, id);
return result;
diff --git a/llvm/test/Instrumentation/Instrumentor/rt_config.json b/llvm/test/Instrumentation/Instrumentor/rt_config.json
index 42d0f0b047309fa..563e1754834cd84 100644
--- a/llvm/test/Instrumentation/Instrumentor/rt_config.json
+++ b/llvm/test/Instrumentation/Instrumentor/rt_config.json
@@ -209,6 +209,38 @@
"id": true,
"id.description": "A unique ID associated with the given instrumentor call"
},
+ "atomicrmw": {
+ "enabled": true,
+ "filter": "",
+ "filter.description": "Static property filter to exclude instrumentation.",
+ "pointer": true,
+ "pointer.replace": true,
+ "pointer.description": "The accessed pointer.",
+ "pointer_as": true,
+ "pointer_as.description": "The address space of the accessed pointer.",
+ "base_pointer_info": true,
+ "base_pointer_info.description": "The runtime provided base pointer info.",
+ "val_operand": true,
+ "val_operand.description": "The operand being atomically applied to the stored value.",
+ "value_size": true,
+ "value_size.description": "The size of the modified value.",
+ "alignment": true,
+ "alignment.description": "The known access alignment.",
+ "value_type_id": true,
+ "value_type_id.description": "The type id of the modified value.",
+ "value_sub_type_id": true,
+ "value_sub_type_id.description": "The sub type id of the modified value (for arrays and vectors, or -1).",
+ "atomicity_ordering": true,
+ "atomicity_ordering.description": "The atomicity ordering of the atomic RMW instruction.",
+ "sync_scope_id": true,
+ "sync_scope_id.description": "The sync scope id of the operation.",
+ "operation": true,
+ "operation.description": "The atomic RMW instruction's operation id.",
+ "is_volatile": true,
+ "is_volatile.description": "Flag indicating a volatile operation.",
+ "id": true,
+ "id.description": "A unique ID associated with the given instrumentor call"
+ },
"cast": {
"enabled": true,
"filter": "",
@@ -307,6 +339,40 @@
"id": true,
"id.description": "A unique ID associated with the given instrumentor call"
},
+ "atomicrmw": {
+ "enabled": true,
+ "filter": "",
+ "filter.description": "Static property filter to exclude instrumentation.",
+ "pointer": true,
+ "pointer.description": "The accessed pointer.",
+ "pointer_as": true,
+ "pointer_as.description": "The address space of the accessed pointer.",
+ "base_pointer_info": true,
+ "base_pointer_info.description": "The runtime provided base pointer info.",
+ "val_operand": true,
+ "val_operand.description": "The operand being atomically applied to the stored value.",
+ "prev_value": true,
+ "prev_value.replace": true,
+ "prev_value.description": "The unmodified old value.",
+ "value_size": true,
+ "value_size.description": "The size of the modified value.",
+ "alignment": true,
+ "alignment.description": "The known access alignment.",
+ "value_type_id": true,
+ "value_type_id.description": "The type id of the modified value.",
+ "value_sub_type_id": true,
+ "value_sub_type_id.description": "The sub type id of the modified value (for arrays and vectors, or -1).",
+ "atomicity_ordering": true,
+ "atomicity_ordering.description": "The atomicity ordering of the atomic RMW instruction.",
+ "sync_scope_id": true,
+ "sync_scope_id.description": "The sync scope id of the operation.",
+ "operation": true,
+ "operation.description": "The atomic RMW instruction's operation id.",
+ "is_volatile": true,
+ "is_volatile.description": "Flag indicating a volatile operation.",
+ "id": true,
+ "id.description": "A unique ID associated with the given instrumentor call"
+ },
"cast": {
"enabled": true,
"filter": "",
More information about the llvm-commits
mailing list