Path: blob/main/contrib/llvm-project/llvm/lib/SandboxIR/Tracker.cpp
35260 views
//===- Tracker.cpp --------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/SandboxIR/Tracker.h"9#include "llvm/ADT/STLExtras.h"10#include "llvm/IR/BasicBlock.h"11#include "llvm/IR/Instruction.h"12#include "llvm/SandboxIR/SandboxIR.h"13#include <sstream>1415using namespace llvm::sandboxir;1617IRChangeBase::IRChangeBase(Tracker &Parent) : Parent(Parent) {18#ifndef NDEBUG19assert(!Parent.InMiddleOfCreatingChange &&20"We are in the middle of creating another change!");21if (Parent.isTracking())22Parent.InMiddleOfCreatingChange = true;23#endif // NDEBUG24}2526#ifndef NDEBUG27unsigned IRChangeBase::getIdx() const {28auto It =29find_if(Parent.Changes, [this](auto &Ptr) { return Ptr.get() == this; });30return It - Parent.Changes.begin();31}3233void UseSet::dump() const {34dump(dbgs());35dbgs() << "\n";36}37#endif // NDEBUG3839Tracker::~Tracker() {40assert(Changes.empty() && "You must accept or revert changes!");41}4243EraseFromParent::EraseFromParent(std::unique_ptr<sandboxir::Value> &&ErasedIPtr,44Tracker &Tracker)45: IRChangeBase(Tracker), ErasedIPtr(std::move(ErasedIPtr)) {46auto *I = cast<Instruction>(this->ErasedIPtr.get());47auto LLVMInstrs = I->getLLVMInstrs();48// Iterate in reverse program order.49for (auto *LLVMI : reverse(LLVMInstrs)) {50SmallVector<llvm::Value *> Operands;51Operands.reserve(LLVMI->getNumOperands());52for (auto [OpNum, Use] : enumerate(LLVMI->operands()))53Operands.push_back(Use.get());54InstrData.push_back({Operands, LLVMI});55}56assert(is_sorted(InstrData,57[](const auto &D0, const auto &D1) {58return D0.LLVMI->comesBefore(D1.LLVMI);59}) &&60"Expected reverse program order!");61auto *BotLLVMI = cast<llvm::Instruction>(I->Val);62if (BotLLVMI->getNextNode() != nullptr)63NextLLVMIOrBB = BotLLVMI->getNextNode();64else65NextLLVMIOrBB = BotLLVMI->getParent();66}6768void EraseFromParent::accept() {69for (const auto &IData : InstrData)70IData.LLVMI->deleteValue();71}7273void EraseFromParent::revert() {74// Place the bottom-most instruction first.75auto [Operands, BotLLVMI] = InstrData[0];76if (auto *NextLLVMI = NextLLVMIOrBB.dyn_cast<llvm::Instruction *>()) {77BotLLVMI->insertBefore(NextLLVMI);78} else {79auto *LLVMBB = NextLLVMIOrBB.get<llvm::BasicBlock *>();80BotLLVMI->insertInto(LLVMBB, LLVMBB->end());81}82for (auto [OpNum, Op] : enumerate(Operands))83BotLLVMI->setOperand(OpNum, Op);8485// Go over the rest of the instructions and stack them on top.86for (auto [Operands, LLVMI] : drop_begin(InstrData)) {87LLVMI->insertBefore(BotLLVMI);88for (auto [OpNum, Op] : enumerate(Operands))89LLVMI->setOperand(OpNum, Op);90BotLLVMI = LLVMI;91}92Parent.getContext().registerValue(std::move(ErasedIPtr));93}9495#ifndef NDEBUG96void EraseFromParent::dump() const {97dump(dbgs());98dbgs() << "\n";99}100#endif // NDEBUG101102RemoveFromParent::RemoveFromParent(Instruction *RemovedI, Tracker &Tracker)103: IRChangeBase(Tracker), RemovedI(RemovedI) {104if (auto *NextI = RemovedI->getNextNode())105NextInstrOrBB = NextI;106else107NextInstrOrBB = RemovedI->getParent();108}109110void RemoveFromParent::revert() {111if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {112RemovedI->insertBefore(NextI);113} else {114auto *BB = NextInstrOrBB.get<BasicBlock *>();115RemovedI->insertInto(BB, BB->end());116}117}118119#ifndef NDEBUG120void RemoveFromParent::dump() const {121dump(dbgs());122dbgs() << "\n";123}124#endif125126MoveInstr::MoveInstr(Instruction *MovedI, Tracker &Tracker)127: IRChangeBase(Tracker), MovedI(MovedI) {128if (auto *NextI = MovedI->getNextNode())129NextInstrOrBB = NextI;130else131NextInstrOrBB = MovedI->getParent();132}133134void MoveInstr::revert() {135if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {136MovedI->moveBefore(NextI);137} else {138auto *BB = NextInstrOrBB.get<BasicBlock *>();139MovedI->moveBefore(*BB, BB->end());140}141}142143#ifndef NDEBUG144void MoveInstr::dump() const {145dump(dbgs());146dbgs() << "\n";147}148#endif149150void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {151assert(State == TrackerState::Record && "The tracker should be tracking!");152Changes.push_back(std::move(Change));153154#ifndef NDEBUG155InMiddleOfCreatingChange = false;156#endif157}158159void Tracker::save() { State = TrackerState::Record; }160161void Tracker::revert() {162assert(State == TrackerState::Record && "Forgot to save()!");163State = TrackerState::Disabled;164for (auto &Change : reverse(Changes))165Change->revert();166Changes.clear();167}168169void Tracker::accept() {170assert(State == TrackerState::Record && "Forgot to save()!");171State = TrackerState::Disabled;172for (auto &Change : Changes)173Change->accept();174Changes.clear();175}176177#ifndef NDEBUG178void Tracker::dump(raw_ostream &OS) const {179for (const auto &ChangePtr : Changes) {180ChangePtr->dump(OS);181OS << "\n";182}183}184void Tracker::dump() const {185dump(dbgs());186dbgs() << "\n";187}188#endif // NDEBUG189190191