Files
vporpo 0beb9f45f2 [SandboxVec] SandboxVectorizerIR Boilerplate (#189515)
This patch introduces a new specialization of SandboxIR named
SandboxVectorizerIR that contains the new Pack instruction (though it is
just a placeholder for now). It also implements the necessary
boilerplate in SandboxIR to support adding such specializations.

Each specialization requires its own *Values.def file defining its new
instructions. The new .def file also needs to be added to
ValuesDefFilesList.def which allows SandboxIR to include entries from
all specializations and populate structures like the Opcode enum,
ClassID and others.

Given that we need to include both .def files in several places, I had
to (i) change the .def file to undefine its locally defined macros so
that they won't get redefined in the next #include .def, and (ii) add
the DEF_DISABLE_AUTO_UNDEF option to disable undefining the macros at
the end because otherwise the user-specified DEF_ macros would be
undefined by the time we reach the second .def file.
2026-05-05 11:09:39 -07:00

123 lines
4.1 KiB
C++

//===- User.cpp - The User class of Sandbox IR ----------------------------===//
//
// 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 "llvm/SandboxIR/User.h"
#include "llvm/SandboxIR/Context.h"
namespace llvm::sandboxir {
Use OperandUseIterator::operator*() const { return Use; }
OperandUseIterator &OperandUseIterator::operator++() {
assert(Use.LLVMUse != nullptr && "Already at end!");
User *User = Use.getUser();
Use = User->getOperandUseInternal(Use.getOperandNo() + 1, /*Verify=*/false);
return *this;
}
UserUseIterator &UserUseIterator::operator++() {
// Get the corresponding llvm::Use, get the next in the list, and update the
// sandboxir::Use.
llvm::Use *&LLVMUse = Use.LLVMUse;
assert(LLVMUse != nullptr && "Already at end!");
LLVMUse = LLVMUse->getNext();
if (LLVMUse == nullptr) {
Use.Usr = nullptr;
return *this;
}
auto *Ctx = Use.Ctx;
auto *LLVMUser = LLVMUse->getUser();
Use.Usr = cast_or_null<sandboxir::User>(Ctx->getValue(LLVMUser));
return *this;
}
OperandUseIterator OperandUseIterator::operator+(unsigned Num) const {
sandboxir::Use U = Use.getUser()->getOperandUseInternal(
Use.getOperandNo() + Num, /*Verify=*/true);
return OperandUseIterator(U);
}
OperandUseIterator OperandUseIterator::operator-(unsigned Num) const {
assert(Use.getOperandNo() >= Num && "Out of bounds!");
sandboxir::Use U = Use.getUser()->getOperandUseInternal(
Use.getOperandNo() - Num, /*Verify=*/true);
return OperandUseIterator(U);
}
int OperandUseIterator::operator-(const OperandUseIterator &Other) const {
int ThisOpNo = Use.getOperandNo();
int OtherOpNo = Other.Use.getOperandNo();
return ThisOpNo - OtherOpNo;
}
Use User::getOperandUseDefault(unsigned OpIdx, bool Verify) const {
assert((!Verify || OpIdx < getNumOperands()) && "Out of bounds!");
assert(isa<llvm::User>(Val) && "Non-users have no operands!");
llvm::Use *LLVMUse;
if (OpIdx != getNumOperands())
LLVMUse = &cast<llvm::User>(Val)->getOperandUse(OpIdx);
else
LLVMUse = cast<llvm::User>(Val)->op_end();
return Use(LLVMUse, const_cast<User *>(this), Ctx);
}
#ifndef NDEBUG
void User::verifyUserOfLLVMUse(const llvm::Use &Use) const {
assert(Ctx.getValue(Use.getUser()) == this &&
"Use not found in this SBUser's operands!");
}
#endif
bool User::classof(const Value *From) {
switch (From->getSubclassID()) {
#define DEF_VALUE(ID, CLASS)
#define DEF_USER(ID, CLASS) \
case ClassID::ID: \
return true;
#define DEF_INSTR(ID, OPC, CLASS) \
case ClassID::ID: \
return true;
#define DEF_DISABLE_AUTO_UNDEF // ValuesDefFilesList.def includes multiple .def
#include "llvm/SandboxIR/ValuesDefFilesList.def"
default:
return false;
}
}
void User::setOperand(unsigned OperandIdx, Value *Operand) {
assert(isa<llvm::User>(Val) && "No operands!");
const auto &U = getOperandUse(OperandIdx);
Ctx.getTracker().emplaceIfTracking<UseSet>(U);
Ctx.runSetUseCallbacks(U, Operand);
// We are delegating to llvm::User::setOperand().
cast<llvm::User>(Val)->setOperand(OperandIdx, Operand->Val);
}
bool User::replaceUsesOfWith(Value *FromV, Value *ToV) {
auto &Tracker = Ctx.getTracker();
for (auto OpIdx : seq<unsigned>(0, getNumOperands())) {
auto Use = getOperandUse(OpIdx);
if (Use.get() == FromV) {
Ctx.runSetUseCallbacks(Use, ToV);
if (Tracker.isTracking())
Tracker.emplaceIfTracking<UseSet>(Use);
}
}
// We are delegating RUOW to LLVM IR's RUOW.
return cast<llvm::User>(Val)->replaceUsesOfWith(FromV->Val, ToV->Val);
}
#ifndef NDEBUG
void User::dumpCommonHeader(raw_ostream &OS) const {
Value::dumpCommonHeader(OS);
// TODO: This is incomplete
}
#endif // NDEBUG
} // namespace llvm::sandboxir