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.
123 lines
4.1 KiB
C++
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
|