Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

165 lines
6.2 KiB
C++

//===-- MemorySlotInterfaces.cpp - MemorySlot interfaces --------*- 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
//
//===----------------------------------------------------------------------===//
#include "mlir/Interfaces/MemorySlotInterfaces.h"
#include "llvm/ADT/SmallVector.h"
#include "mlir/Interfaces/MemorySlotOpInterfaces.cpp.inc"
#include "mlir/Interfaces/MemorySlotTypeInterfaces.cpp.inc"
using namespace mlir;
/// Returns the slot describing `aliasPtr`: `rootSlot` if it is the root,
/// the entry in `aliasMap` if it's a known alias, or `nullopt` otherwise.
static std::optional<MemorySlot>
getParentSlot(Value aliasPtr, const MemorySlot &rootSlot,
const PromotableAliasMap &aliasMap) {
if (aliasPtr == rootSlot.ptr)
return rootSlot;
auto it = aliasMap.find(aliasPtr);
if (it == aliasMap.end())
return std::nullopt;
return it->second.slot;
}
void mlir::populatePromotableAliasMap(PromotableAliaserInterface aliaser,
const MemorySlot &rootSlot,
PromotableAliasMap &aliasMap) {
for (OpOperand &operand : aliaser->getOpOperands()) {
std::optional<MemorySlot> parentSlot =
getParentSlot(operand.get(), rootSlot, aliasMap);
if (!parentSlot)
continue;
SmallVector<MemorySlot, 2> newSlots;
aliaser.getPromotableSlotAliases(operand, *parentSlot, newSlots);
for (const MemorySlot &alias : newSlots)
aliasMap.try_emplace(alias.ptr, PromotableSlotAliasInfo{alias, &operand});
}
}
std::optional<MemorySlot>
mlir::getOpAliasSlot(Operation *op, const MemorySlot &rootSlot,
const PromotableAliasMap &aliasMap) {
for (Value operand : op->getOperands())
if (std::optional<MemorySlot> slot =
getParentSlot(operand, rootSlot, aliasMap))
return slot;
return std::nullopt;
}
bool mlir::referencesAtMostOneAliasOfSlot(Operation *op,
const MemorySlot &rootSlot,
const PromotableAliasMap &aliasMap) {
Value uniqueAliasPtr;
for (Value operand : op->getOperands()) {
std::optional<MemorySlot> slot = getParentSlot(operand, rootSlot, aliasMap);
if (!slot)
continue;
if (uniqueAliasPtr && uniqueAliasPtr != slot->ptr)
return false;
uniqueAliasPtr = slot->ptr;
}
return true;
}
namespace {
/// A step in an alias chain, from leaf to root. `parentSlot` is one step
/// closer to the root; `aliasSlot` is the slot exposed at this step.
struct ChainStep {
PromotableAliaserInterface aliaser;
OpOperand *aliasedSlotPointerOperand;
MemorySlot parentSlot;
MemorySlot aliasSlot;
};
} // namespace
/// Walks from `aliasSlot` back to `rootSlot` via `aliasMap`. Returns the
/// leaf-to-root chain, or `nullopt` if `aliasSlot` is not a known alias.
static std::optional<SmallVector<ChainStep>>
buildAliasChain(const MemorySlot &aliasSlot, const MemorySlot &rootSlot,
const PromotableAliasMap &aliasMap) {
SmallVector<ChainStep> chain;
Value current = aliasSlot.ptr;
while (current != rootSlot.ptr) {
auto it = aliasMap.find(current);
if (it == aliasMap.end())
return std::nullopt;
OpOperand *operand = it->second.aliasedSlotPointerOperand;
auto aliaser = cast<PromotableAliaserInterface>(operand->getOwner());
std::optional<MemorySlot> parent =
getParentSlot(operand->get(), rootSlot, aliasMap);
if (!parent)
return std::nullopt;
chain.push_back(ChainStep{aliaser, operand, *parent, it->second.slot});
current = operand->get();
}
return chain;
}
Value mlir::convertSlotValueToAliasValue(Value slotValue,
const MemorySlot &aliasSlot,
const MemorySlot &rootSlot,
const PromotableAliasMap &aliasMap,
OpBuilder &builder) {
std::optional<SmallVector<ChainStep>> chain =
buildAliasChain(aliasSlot, rootSlot, aliasMap);
if (!chain)
return {};
Value current = slotValue;
// Root-to-leaf walk: reverse the leaf-first chain.
for (ChainStep &step : llvm::reverse(*chain)) {
current = step.aliaser.projectSlotValueToAliasValue(
*step.aliasedSlotPointerOperand, step.parentSlot, step.aliasSlot,
current, builder);
if (!current)
return {};
}
return current;
}
Value mlir::convertAliasValueToSlotValue(Value aliasValue,
const MemorySlot &aliasSlot,
Value rootReachingDef,
const MemorySlot &rootSlot,
const PromotableAliasMap &aliasMap,
OpBuilder &builder) {
std::optional<SmallVector<ChainStep>> chainOpt =
buildAliasChain(aliasSlot, rootSlot, aliasMap);
if (!chainOpt)
return {};
SmallVector<ChainStep> &chain = *chainOpt;
// Project `rootReachingDef` down to each step's parent level so the
// per-step projector can use it (needed for partial sub-aliases; full
// aliases ignore it). The chain is leaf-first, so `chain.back()` is the
// root-most step (parent = rootSlot) and `chain.front()` is the leaf.
SmallVector<Value> perStepReachingDef(chain.size());
Value current = rootReachingDef;
for (int i = static_cast<int>(chain.size()) - 1; i >= 0; --i) {
perStepReachingDef[i] = current;
current = chain[i].aliaser.projectSlotValueToAliasValue(
*chain[i].aliasedSlotPointerOperand, chain[i].parentSlot,
chain[i].aliasSlot, current, builder);
if (!current)
return {};
}
// Walk leaf-to-root, combining `aliasValue` with the projected reaching
// definition at each step.
current = aliasValue;
for (size_t i = 0; i < chain.size(); ++i) {
current = chain[i].aliaser.projectAliasValueToSlotValue(
*chain[i].aliasedSlotPointerOperand, chain[i].parentSlot,
chain[i].aliasSlot, current, perStepReachingDef[i], builder);
if (!current)
return {};
}
return current;
}