1 //===- RDFCopy.cpp --------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // RDF-based copy propagation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "RDFCopy.h" 15 #include "RDFGraph.h" 16 #include "RDFLiveness.h" 17 #include "RDFRegisters.h" 18 #include "llvm/CodeGen/MachineDominators.h" 19 #include "llvm/CodeGen/MachineInstr.h" 20 #include "llvm/CodeGen/MachineOperand.h" 21 #include "llvm/CodeGen/MachineRegisterInfo.h" 22 #include "llvm/CodeGen/TargetOpcodes.h" 23 #include "llvm/CodeGen/TargetRegisterInfo.h" 24 #include "llvm/MC/MCRegisterInfo.h" 25 #include "llvm/Support/CommandLine.h" 26 #include "llvm/Support/Debug.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include <cassert> 30 #include <cstdint> 31 #include <utility> 32 33 using namespace llvm; 34 using namespace rdf; 35 36 #ifndef NDEBUG 37 static cl::opt<unsigned> CpLimit("rdf-cp-limit", cl::init(0), cl::Hidden); 38 static unsigned CpCount = 0; 39 #endif 40 41 bool CopyPropagation::interpretAsCopy(const MachineInstr *MI, EqualityMap &EM) { 42 unsigned Opc = MI->getOpcode(); 43 switch (Opc) { 44 case TargetOpcode::COPY: { 45 const MachineOperand &Dst = MI->getOperand(0); 46 const MachineOperand &Src = MI->getOperand(1); 47 RegisterRef DstR = DFG.makeRegRef(Dst.getReg(), Dst.getSubReg()); 48 RegisterRef SrcR = DFG.makeRegRef(Src.getReg(), Src.getSubReg()); 49 assert(TargetRegisterInfo::isPhysicalRegister(DstR.Reg)); 50 assert(TargetRegisterInfo::isPhysicalRegister(SrcR.Reg)); 51 const TargetRegisterInfo &TRI = DFG.getTRI(); 52 if (TRI.getMinimalPhysRegClass(DstR.Reg) != 53 TRI.getMinimalPhysRegClass(SrcR.Reg)) 54 return false; 55 EM.insert(std::make_pair(DstR, SrcR)); 56 return true; 57 } 58 case TargetOpcode::REG_SEQUENCE: 59 llvm_unreachable("Unexpected REG_SEQUENCE"); 60 } 61 return false; 62 } 63 64 void CopyPropagation::recordCopy(NodeAddr<StmtNode*> SA, EqualityMap &EM) { 65 CopyMap.insert(std::make_pair(SA.Id, EM)); 66 Copies.push_back(SA.Id); 67 } 68 69 bool CopyPropagation::scanBlock(MachineBasicBlock *B) { 70 bool Changed = false; 71 NodeAddr<BlockNode*> BA = DFG.findBlock(B); 72 73 for (NodeAddr<InstrNode*> IA : BA.Addr->members(DFG)) { 74 if (DFG.IsCode<NodeAttrs::Stmt>(IA)) { 75 NodeAddr<StmtNode*> SA = IA; 76 EqualityMap EM; 77 if (interpretAsCopy(SA.Addr->getCode(), EM)) 78 recordCopy(SA, EM); 79 } 80 } 81 82 MachineDomTreeNode *N = MDT.getNode(B); 83 for (auto I : *N) 84 Changed |= scanBlock(I->getBlock()); 85 86 return Changed; 87 } 88 89 NodeId CopyPropagation::getLocalReachingDef(RegisterRef RefRR, 90 NodeAddr<InstrNode*> IA) { 91 NodeAddr<RefNode*> RA = L.getNearestAliasedRef(RefRR, IA); 92 if (RA.Id != 0) { 93 if (RA.Addr->getKind() == NodeAttrs::Def) 94 return RA.Id; 95 assert(RA.Addr->getKind() == NodeAttrs::Use); 96 if (NodeId RD = RA.Addr->getReachingDef()) 97 return RD; 98 } 99 return 0; 100 } 101 102 bool CopyPropagation::run() { 103 scanBlock(&DFG.getMF().front()); 104 105 if (trace()) { 106 dbgs() << "Copies:\n"; 107 for (NodeId I : Copies) { 108 dbgs() << "Instr: " << *DFG.addr<StmtNode*>(I).Addr->getCode(); 109 dbgs() << " eq: {"; 110 for (auto J : CopyMap[I]) 111 dbgs() << ' ' << Print<RegisterRef>(J.first, DFG) << '=' 112 << Print<RegisterRef>(J.second, DFG); 113 dbgs() << " }\n"; 114 } 115 } 116 117 bool Changed = false; 118 #ifndef NDEBUG 119 bool HasLimit = CpLimit.getNumOccurrences() > 0; 120 #endif 121 122 auto MinPhysReg = [this] (RegisterRef RR) -> unsigned { 123 const TargetRegisterInfo &TRI = DFG.getTRI(); 124 const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(RR.Reg); 125 if ((RC.LaneMask & RR.Mask) == RC.LaneMask) 126 return RR.Reg; 127 for (MCSubRegIndexIterator S(RR.Reg, &TRI); S.isValid(); ++S) 128 if (RR.Mask == TRI.getSubRegIndexLaneMask(S.getSubRegIndex())) 129 return S.getSubReg(); 130 llvm_unreachable("Should have found a register"); 131 return 0; 132 }; 133 134 for (NodeId C : Copies) { 135 #ifndef NDEBUG 136 if (HasLimit && CpCount >= CpLimit) 137 break; 138 #endif 139 auto SA = DFG.addr<InstrNode*>(C); 140 auto FS = CopyMap.find(SA.Id); 141 if (FS == CopyMap.end()) 142 continue; 143 144 EqualityMap &EM = FS->second; 145 for (NodeAddr<DefNode*> DA : SA.Addr->members_if(DFG.IsDef, DFG)) { 146 RegisterRef DR = DA.Addr->getRegRef(DFG); 147 auto FR = EM.find(DR); 148 if (FR == EM.end()) 149 continue; 150 RegisterRef SR = FR->second; 151 if (DR == SR) 152 continue; 153 154 NodeId AtCopy = getLocalReachingDef(SR, SA); 155 156 for (NodeId N = DA.Addr->getReachedUse(), NextN; N; N = NextN) { 157 auto UA = DFG.addr<UseNode*>(N); 158 NextN = UA.Addr->getSibling(); 159 uint16_t F = UA.Addr->getFlags(); 160 if ((F & NodeAttrs::PhiRef) || (F & NodeAttrs::Fixed)) 161 continue; 162 if (UA.Addr->getRegRef(DFG) != DR) 163 continue; 164 165 NodeAddr<InstrNode*> IA = UA.Addr->getOwner(DFG); 166 assert(DFG.IsCode<NodeAttrs::Stmt>(IA)); 167 NodeId AtUse = getLocalReachingDef(SR, IA); 168 if (AtCopy != AtUse) 169 continue; 170 171 MachineOperand &Op = UA.Addr->getOp(); 172 if (Op.isTied()) 173 continue; 174 if (trace()) { 175 dbgs() << "Can replace " << Print<RegisterRef>(DR, DFG) 176 << " with " << Print<RegisterRef>(SR, DFG) << " in " 177 << *NodeAddr<StmtNode*>(IA).Addr->getCode(); 178 } 179 180 unsigned NewReg = MinPhysReg(SR); 181 Op.setReg(NewReg); 182 Op.setSubReg(0); 183 DFG.unlinkUse(UA, false); 184 if (AtCopy != 0) { 185 UA.Addr->linkToDef(UA.Id, DFG.addr<DefNode*>(AtCopy)); 186 } else { 187 UA.Addr->setReachingDef(0); 188 UA.Addr->setSibling(0); 189 } 190 191 Changed = true; 192 #ifndef NDEBUG 193 if (HasLimit && CpCount >= CpLimit) 194 break; 195 CpCount++; 196 #endif 197 198 auto FC = CopyMap.find(IA.Id); 199 if (FC != CopyMap.end()) { 200 // Update the EM map in the copy's entry. 201 auto &M = FC->second; 202 for (auto &J : M) { 203 if (J.second != DR) 204 continue; 205 J.second = SR; 206 break; 207 } 208 } 209 } // for (N in reached-uses) 210 } // for (DA in defs) 211 } // for (C in Copies) 212 213 return Changed; 214 } 215