10eae32dcSDimitry Andric //===- SSAContext.cpp -------------------------------------------*- C++ -*-===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
80eae32dcSDimitry Andric /// \file
90eae32dcSDimitry Andric ///
100eae32dcSDimitry Andric /// This file defines a specialization of the GenericSSAContext<X>
110eae32dcSDimitry Andric /// template class for LLVM IR.
120eae32dcSDimitry Andric ///
130eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
140eae32dcSDimitry Andric
150eae32dcSDimitry Andric #include "llvm/IR/SSAContext.h"
16bdd1243dSDimitry Andric #include "llvm/IR/Argument.h"
170eae32dcSDimitry Andric #include "llvm/IR/BasicBlock.h"
180eae32dcSDimitry Andric #include "llvm/IR/Function.h"
19bdd1243dSDimitry Andric #include "llvm/IR/Instructions.h"
20*5f757f3fSDimitry Andric #include "llvm/IR/Intrinsics.h"
21*5f757f3fSDimitry Andric #include "llvm/IR/ModuleSlotTracker.h"
220eae32dcSDimitry Andric #include "llvm/Support/raw_ostream.h"
230eae32dcSDimitry Andric
240eae32dcSDimitry Andric using namespace llvm;
250eae32dcSDimitry Andric
26*5f757f3fSDimitry Andric template <>
appendBlockDefs(SmallVectorImpl<Value * > & defs,BasicBlock & block)27bdd1243dSDimitry Andric void SSAContext::appendBlockDefs(SmallVectorImpl<Value *> &defs,
28bdd1243dSDimitry Andric BasicBlock &block) {
29*5f757f3fSDimitry Andric for (auto &instr : block) {
30bdd1243dSDimitry Andric if (instr.isTerminator())
31bdd1243dSDimitry Andric break;
32*5f757f3fSDimitry Andric defs.push_back(&instr);
33bdd1243dSDimitry Andric }
34bdd1243dSDimitry Andric }
35bdd1243dSDimitry Andric
36*5f757f3fSDimitry Andric template <>
appendBlockDefs(SmallVectorImpl<const Value * > & defs,const BasicBlock & block)37bdd1243dSDimitry Andric void SSAContext::appendBlockDefs(SmallVectorImpl<const Value *> &defs,
38bdd1243dSDimitry Andric const BasicBlock &block) {
39bdd1243dSDimitry Andric for (auto &instr : block) {
40bdd1243dSDimitry Andric if (instr.isTerminator())
41bdd1243dSDimitry Andric break;
42bdd1243dSDimitry Andric defs.push_back(&instr);
43bdd1243dSDimitry Andric }
44bdd1243dSDimitry Andric }
45bdd1243dSDimitry Andric
46*5f757f3fSDimitry Andric template <>
appendBlockTerms(SmallVectorImpl<Instruction * > & terms,BasicBlock & block)47bdd1243dSDimitry Andric void SSAContext::appendBlockTerms(SmallVectorImpl<Instruction *> &terms,
48bdd1243dSDimitry Andric BasicBlock &block) {
49bdd1243dSDimitry Andric terms.push_back(block.getTerminator());
50bdd1243dSDimitry Andric }
51bdd1243dSDimitry Andric
52*5f757f3fSDimitry Andric template <>
appendBlockTerms(SmallVectorImpl<const Instruction * > & terms,const BasicBlock & block)53bdd1243dSDimitry Andric void SSAContext::appendBlockTerms(SmallVectorImpl<const Instruction *> &terms,
54bdd1243dSDimitry Andric const BasicBlock &block) {
55bdd1243dSDimitry Andric terms.push_back(block.getTerminator());
56bdd1243dSDimitry Andric }
57bdd1243dSDimitry Andric
58*5f757f3fSDimitry Andric template <>
getDefBlock(const Value * value) const59bdd1243dSDimitry Andric const BasicBlock *SSAContext::getDefBlock(const Value *value) const {
60bdd1243dSDimitry Andric if (const auto *instruction = dyn_cast<Instruction>(value))
61bdd1243dSDimitry Andric return instruction->getParent();
62bdd1243dSDimitry Andric return nullptr;
63bdd1243dSDimitry Andric }
64bdd1243dSDimitry Andric
65*5f757f3fSDimitry Andric template <>
isConstantOrUndefValuePhi(const Instruction & Instr)6606c3fb27SDimitry Andric bool SSAContext::isConstantOrUndefValuePhi(const Instruction &Instr) {
67bdd1243dSDimitry Andric if (auto *Phi = dyn_cast<PHINode>(&Instr))
6806c3fb27SDimitry Andric return Phi->hasConstantOrUndefValue();
69bdd1243dSDimitry Andric return false;
70bdd1243dSDimitry Andric }
71bdd1243dSDimitry Andric
getIntrinsicID(const Instruction & I)72*5f757f3fSDimitry Andric template <> Intrinsic::ID SSAContext::getIntrinsicID(const Instruction &I) {
73*5f757f3fSDimitry Andric if (auto *CB = dyn_cast<CallBase>(&I))
74*5f757f3fSDimitry Andric return CB->getIntrinsicID();
75*5f757f3fSDimitry Andric return Intrinsic::not_intrinsic;
76*5f757f3fSDimitry Andric }
77*5f757f3fSDimitry Andric
print(const Value * V) const78*5f757f3fSDimitry Andric template <> Printable SSAContext::print(const Value *V) const {
790eae32dcSDimitry Andric return Printable([V](raw_ostream &Out) { V->print(Out); });
800eae32dcSDimitry Andric }
810eae32dcSDimitry Andric
print(const Instruction * Inst) const82*5f757f3fSDimitry Andric template <> Printable SSAContext::print(const Instruction *Inst) const {
830eae32dcSDimitry Andric return print(cast<Value>(Inst));
840eae32dcSDimitry Andric }
850eae32dcSDimitry Andric
print(const BasicBlock * BB) const86*5f757f3fSDimitry Andric template <> Printable SSAContext::print(const BasicBlock *BB) const {
87bdd1243dSDimitry Andric if (!BB)
88bdd1243dSDimitry Andric return Printable([](raw_ostream &Out) { Out << "<nullptr>"; });
890eae32dcSDimitry Andric if (BB->hasName())
900eae32dcSDimitry Andric return Printable([BB](raw_ostream &Out) { Out << BB->getName(); });
910eae32dcSDimitry Andric
920eae32dcSDimitry Andric return Printable([BB](raw_ostream &Out) {
930eae32dcSDimitry Andric ModuleSlotTracker MST{BB->getParent()->getParent(), false};
940eae32dcSDimitry Andric MST.incorporateFunction(*BB->getParent());
950eae32dcSDimitry Andric Out << MST.getLocalSlot(BB);
960eae32dcSDimitry Andric });
970eae32dcSDimitry Andric }
98*5f757f3fSDimitry Andric
printAsOperand(const BasicBlock * BB) const99*5f757f3fSDimitry Andric template <> Printable SSAContext::printAsOperand(const BasicBlock *BB) const {
100*5f757f3fSDimitry Andric return Printable([BB](raw_ostream &Out) { BB->printAsOperand(Out); });
101*5f757f3fSDimitry Andric }
102