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
58 changes: 58 additions & 0 deletions llvm/include/llvm/Support/AllocToken.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//===- llvm/Support/AllocToken.h - Allocation Token Calculation -----*- C++ -*//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Definition of AllocToken modes and shared calculation of stateless token IDs.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_ALLOCTOKEN_H
#define LLVM_SUPPORT_ALLOCTOKEN_H

#include "llvm/ADT/SmallString.h"
#include <cstdint>
#include <optional>

namespace llvm {

/// Modes for generating allocation token IDs.
enum class AllocTokenMode {
/// Incrementally increasing token ID.
Increment,

/// Simple mode that returns a statically-assigned random token ID.
Random,

/// Token ID based on allocated type hash.
TypeHash,

/// Token ID based on allocated type hash, where the top half ID-space is
/// reserved for types that contain pointers and the bottom half for types
/// that do not contain pointers.
TypeHashPointerSplit,
};

/// Metadata about an allocation used to generate a token ID.
struct AllocTokenMetadata {
SmallString<64> TypeName;
bool ContainsPointer;
};

/// Calculates stable allocation token ID. Returns std::nullopt for stateful
/// modes that are only available in the AllocToken pass.
///
/// \param Mode The token generation mode.
/// \param Metadata The metadata about the allocation.
/// \param MaxTokens The maximum number of tokens (must not be 0)
/// \return The calculated allocation token ID, or std::nullopt.
LLVM_ABI std::optional<uint64_t>
getAllocToken(AllocTokenMode Mode, const AllocTokenMetadata &Metadata,
uint64_t MaxTokens);

} // end namespace llvm

#endif // LLVM_SUPPORT_ALLOCTOKEN_H
50 changes: 50 additions & 0 deletions llvm/lib/Support/AllocToken.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//===- AllocToken.cpp - Allocation Token Calculation ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Definition of AllocToken modes and shared calculation of stateless token IDs.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/AllocToken.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SipHash.h"

using namespace llvm;

static uint64_t getStableHash(const AllocTokenMetadata &Metadata,
uint64_t MaxTokens) {
return getStableSipHash(Metadata.TypeName) % MaxTokens;
}

std::optional<uint64_t> llvm::getAllocToken(AllocTokenMode Mode,
const AllocTokenMetadata &Metadata,
uint64_t MaxTokens) {
assert(MaxTokens && "Must provide non-zero max tokens");

switch (Mode) {
case AllocTokenMode::Increment:
case AllocTokenMode::Random:
// Stateful modes cannot be implemented as a pure function.
return std::nullopt;

case AllocTokenMode::TypeHash:
return getStableHash(Metadata, MaxTokens);

case AllocTokenMode::TypeHashPointerSplit: {
if (MaxTokens == 1)
return 0;
const uint64_t HalfTokens = MaxTokens / 2;
uint64_t Hash = getStableHash(Metadata, HalfTokens);
if (Metadata.ContainsPointer)
Hash += HalfTokens;
return Hash;
}
}

llvm_unreachable("");
}
1 change: 1 addition & 0 deletions llvm/lib/Support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ add_llvm_component_library(LLVMSupport
AArch64BuildAttributes.cpp
ARMAttributeParser.cpp
ARMWinEH.cpp
AllocToken.cpp
Allocator.cpp
AutoConvert.cpp
Base64.cpp
Expand Down
57 changes: 18 additions & 39 deletions llvm/lib/Transforms/Instrumentation/AllocToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/AllocToken.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
Expand All @@ -54,29 +55,12 @@
#include <variant>

using namespace llvm;
using TokenMode = AllocTokenMode;

#define DEBUG_TYPE "alloc-token"

namespace {

//===--- Constants --------------------------------------------------------===//

enum class TokenMode : unsigned {
/// Incrementally increasing token ID.
Increment = 0,

/// Simple mode that returns a statically-assigned random token ID.
Random = 1,

/// Token ID based on allocated type hash.
TypeHash = 2,

/// Token ID based on allocated type hash, where the top half ID-space is
/// reserved for types that contain pointers and the bottom half for types
/// that do not contain pointers.
TypeHashPointerSplit = 3,
};

//===--- Command-line options ---------------------------------------------===//

cl::opt<TokenMode> ClMode(
Expand Down Expand Up @@ -217,22 +201,19 @@ class TypeHashMode : public ModeBase {
using ModeBase::ModeBase;

uint64_t operator()(const CallBase &CB, OptimizationRemarkEmitter &ORE) {
const auto [N, H] = getHash(CB, ORE);
return N ? boundedToken(H) : H;
}

protected:
std::pair<MDNode *, uint64_t> getHash(const CallBase &CB,
OptimizationRemarkEmitter &ORE) {
if (MDNode *N = getAllocTokenMetadata(CB)) {
MDString *S = cast<MDString>(N->getOperand(0));
return {N, getStableSipHash(S->getString())};
AllocTokenMetadata Metadata{S->getString(), containsPointer(N)};
if (auto Token = getAllocToken(TokenMode::TypeHash, Metadata, MaxTokens))
return *Token;
}
// Fallback.
remarkNoMetadata(CB, ORE);
return {nullptr, ClFallbackToken};
return ClFallbackToken;
}

protected:
/// Remark that there was no precise type information.
static void remarkNoMetadata(const CallBase &CB,
OptimizationRemarkEmitter &ORE) {
Expand All @@ -253,20 +234,18 @@ class TypeHashPointerSplitMode : public TypeHashMode {
using TypeHashMode::TypeHashMode;

uint64_t operator()(const CallBase &CB, OptimizationRemarkEmitter &ORE) {
if (MaxTokens == 1)
return 0;
const uint64_t HalfTokens = MaxTokens / 2;
const auto [N, H] = getHash(CB, ORE);
if (!N) {
// Pick the fallback token (ClFallbackToken), which by default is 0,
// meaning it'll fall into the pointer-less bucket. Override by setting
// -alloc-token-fallback if that is the wrong choice.
return H;
if (MDNode *N = getAllocTokenMetadata(CB)) {
MDString *S = cast<MDString>(N->getOperand(0));
AllocTokenMetadata Metadata{S->getString(), containsPointer(N)};
if (auto Token = getAllocToken(TokenMode::TypeHashPointerSplit, Metadata,
MaxTokens))
return *Token;
}
uint64_t Hash = H % HalfTokens; // base hash
if (containsPointer(N))
Hash += HalfTokens;
return Hash;
// Pick the fallback token (ClFallbackToken), which by default is 0, meaning
// it'll fall into the pointer-less bucket. Override by setting
// -alloc-token-fallback if that is the wrong choice.
remarkNoMetadata(CB, ORE);
return ClFallbackToken;
}
};

Expand Down
1 change: 1 addition & 0 deletions llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ static_library("Support") {
"ARMAttributeParser.cpp",
"ARMBuildAttributes.cpp",
"ARMWinEH.cpp",
"AllocToken.cpp",
"Allocator.cpp",
"AutoConvert.cpp",
"BalancedPartitioning.cpp",
Expand Down