| //===- SSAContext.cpp -------------------------------------------*- 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// \file | |
| /// | |
| /// This file defines a specialization of the GenericSSAContext<X> | |
| /// template class for LLVM IR. | |
| /// | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/IR/SSAContext.h" | |
| #include "llvm/IR/BasicBlock.h" | |
| #include "llvm/IR/Function.h" | |
| #include "llvm/IR/Instructions.h" | |
| #include "llvm/IR/Intrinsics.h" | |
| #include "llvm/IR/ModuleSlotTracker.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| using namespace llvm; | |
| template <> | |
| void SSAContext::appendBlockDefs(SmallVectorImpl<Value *> &defs, | |
| BasicBlock &block) { | |
| for (auto &instr : block) { | |
| if (instr.isTerminator()) | |
| break; | |
| defs.push_back(&instr); | |
| } | |
| } | |
| template <> | |
| void SSAContext::appendBlockDefs(SmallVectorImpl<const Value *> &defs, | |
| const BasicBlock &block) { | |
| for (auto &instr : block) { | |
| if (instr.isTerminator()) | |
| break; | |
| defs.push_back(&instr); | |
| } | |
| } | |
| template <> | |
| void SSAContext::appendBlockTerms(SmallVectorImpl<Instruction *> &terms, | |
| BasicBlock &block) { | |
| terms.push_back(block.getTerminator()); | |
| } | |
| template <> | |
| void SSAContext::appendBlockTerms(SmallVectorImpl<const Instruction *> &terms, | |
| const BasicBlock &block) { | |
| terms.push_back(block.getTerminator()); | |
| } | |
| template <> | |
| const BasicBlock *SSAContext::getDefBlock(const Value *value) const { | |
| if (const auto *instruction = dyn_cast<Instruction>(value)) | |
| return instruction->getParent(); | |
| return nullptr; | |
| } | |
| template <> | |
| bool SSAContext::isConstantOrUndefValuePhi(const Instruction &Instr) { | |
| if (auto *Phi = dyn_cast<PHINode>(&Instr)) | |
| return Phi->hasConstantOrUndefValue(); | |
| return false; | |
| } | |
| template <> bool SSAContext::isAlwaysUniform(const Value *V) { | |
| return !isa<Instruction>(V) && !isa<Argument>(V); | |
| } | |
| template <> Intrinsic::ID SSAContext::getIntrinsicID(const Instruction &I) { | |
| if (auto *CB = dyn_cast<CallBase>(&I)) | |
| return CB->getIntrinsicID(); | |
| return Intrinsic::not_intrinsic; | |
| } | |
| template <> Printable SSAContext::print(const Value *V) const { | |
| return Printable([V](raw_ostream &Out) { V->print(Out); }); | |
| } | |
| template <> Printable SSAContext::print(const Instruction *Inst) const { | |
| return print(cast<Value>(Inst)); | |
| } | |
| template <> Printable SSAContext::print(const BasicBlock *BB) const { | |
| if (!BB) | |
| return Printable([](raw_ostream &Out) { Out << "<nullptr>"; }); | |
| if (BB->hasName()) | |
| return Printable([BB](raw_ostream &Out) { Out << BB->getName(); }); | |
| return Printable([BB](raw_ostream &Out) { | |
| ModuleSlotTracker MST{BB->getParent()->getParent()}; | |
| MST.incorporateFunction(*BB->getParent()); | |
| Out << MST.getLocalSlot(BB); | |
| }); | |
| } | |
| template <> Printable SSAContext::printAsOperand(const BasicBlock *BB) const { | |
| return Printable([BB](raw_ostream &Out) { BB->printAsOperand(Out); }); | |
| } |