xref: /llvm-project/llvm/lib/CodeGen/MachineSSAContext.cpp (revision b60c118f53e6f7e5328e54dc26b4d6787030c02b)
1 //===- MachineSSAContext.cpp ------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file defines a specialization of the GenericSSAContext<X>
11 /// template class for Machine IR.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/CodeGen/MachineSSAContext.h"
16 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
17 #include "llvm/CodeGen/MachineBasicBlock.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/Support/raw_ostream.h"
22 
23 using namespace llvm;
24 
25 template <>
26 void MachineSSAContext::appendBlockDefs(SmallVectorImpl<Register> &defs,
27                                         const MachineBasicBlock &block) {
28   for (auto &instr : block.instrs()) {
29     for (auto &op : instr.all_defs())
30       defs.push_back(op.getReg());
31   }
32 }
33 
34 template <>
35 void MachineSSAContext::appendBlockTerms(SmallVectorImpl<MachineInstr *> &terms,
36                                          MachineBasicBlock &block) {
37   for (auto &T : block.terminators())
38     terms.push_back(&T);
39 }
40 
41 template <>
42 void MachineSSAContext::appendBlockTerms(
43     SmallVectorImpl<const MachineInstr *> &terms,
44     const MachineBasicBlock &block) {
45   for (auto &T : block.terminators())
46     terms.push_back(&T);
47 }
48 
49 /// Get the defining block of a value.
50 template <>
51 const MachineBasicBlock *MachineSSAContext::getDefBlock(Register value) const {
52   if (!value)
53     return nullptr;
54   return F->getRegInfo().getVRegDef(value)->getParent();
55 }
56 
57 static bool isUndef(const MachineInstr &MI) {
58   return MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
59          MI.getOpcode() == TargetOpcode::IMPLICIT_DEF;
60 }
61 
62 /// MachineInstr equivalent of PHINode::hasConstantOrUndefValue() for G_PHI.
63 template <>
64 bool MachineSSAContext::isConstantOrUndefValuePhi(const MachineInstr &Phi) {
65   if (!Phi.isPHI())
66     return false;
67 
68   // In later passes PHI may appear with an undef operand, getVRegDef can fail.
69   if (Phi.getOpcode() == TargetOpcode::PHI)
70     return Phi.isConstantValuePHI();
71 
72   // For G_PHI we do equivalent of PHINode::hasConstantOrUndefValue().
73   const MachineRegisterInfo &MRI = Phi.getMF()->getRegInfo();
74   Register This = Phi.getOperand(0).getReg();
75   Register ConstantValue;
76   for (unsigned i = 1, e = Phi.getNumOperands(); i < e; i += 2) {
77     Register Incoming = Phi.getOperand(i).getReg();
78     if (Incoming != This && !isUndef(*MRI.getVRegDef(Incoming))) {
79       if (ConstantValue && ConstantValue != Incoming)
80         return false;
81       ConstantValue = Incoming;
82     }
83   }
84   return true;
85 }
86 
87 template <>
88 Intrinsic::ID MachineSSAContext::getIntrinsicID(const MachineInstr &MI) {
89   if (auto *GI = dyn_cast<GIntrinsic>(&MI))
90     return GI->getIntrinsicID();
91   return Intrinsic::not_intrinsic;
92 }
93 
94 template <>
95 Printable MachineSSAContext::print(const MachineBasicBlock *Block) const {
96   if (!Block)
97     return Printable([](raw_ostream &Out) { Out << "<nullptr>"; });
98   return Printable([Block](raw_ostream &Out) { Block->printName(Out); });
99 }
100 
101 template <> Printable MachineSSAContext::print(const MachineInstr *I) const {
102   return Printable([I](raw_ostream &Out) { I->print(Out); });
103 }
104 
105 template <> Printable MachineSSAContext::print(Register Value) const {
106   auto *MRI = &F->getRegInfo();
107   return Printable([MRI, Value](raw_ostream &Out) {
108     Out << printReg(Value, MRI->getTargetRegisterInfo(), 0, MRI);
109 
110     if (Value) {
111       // Try to print the definition.
112       if (auto *Instr = MRI->getUniqueVRegDef(Value)) {
113         Out << ": ";
114         Instr->print(Out);
115       }
116     }
117   });
118 }
119 
120 template <>
121 Printable MachineSSAContext::printAsOperand(const MachineBasicBlock *BB) const {
122   return Printable([BB](raw_ostream &Out) { BB->printAsOperand(Out); });
123 }
124