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