1//===--- HexagonGenMux.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// During instruction selection, MUX instructions are generated for 11// conditional assignments. Since such assignments often present an 12// opportunity to predicate instructions, HexagonExpandCondsets 13// expands MUXes into pairs of conditional transfers, and then proceeds 14// with predication of the producers/consumers of the registers involved. 15// This happens after exiting from the SSA form, but before the machine 16// instruction scheduler. After the scheduler and after the register 17// allocation there can be cases of pairs of conditional transfers 18// resulting from a MUX where neither of them was further predicated. If 19// these transfers are now placed far enough from the instruction defining 20// the predicate register, they cannot use the .new form. In such cases it 21// is better to collapse them back to a single MUX instruction. 22 23#define DEBUG_TYPE "hexmux" 24 25#include "llvm/CodeGen/Passes.h" 26#include "llvm/CodeGen/MachineFunctionPass.h" 27#include "llvm/CodeGen/MachineInstrBuilder.h" 28#include "llvm/CodeGen/MachineRegisterInfo.h" 29#include "HexagonTargetMachine.h" 30 31using namespace llvm; 32 33namespace llvm { 34 FunctionPass *createHexagonGenMux(); 35 void initializeHexagonGenMuxPass(PassRegistry& Registry); 36} 37 38namespace { 39 class HexagonGenMux : public MachineFunctionPass { 40 public: 41 static char ID; 42 HexagonGenMux() : MachineFunctionPass(ID), HII(0), HRI(0) { 43 initializeHexagonGenMuxPass(*PassRegistry::getPassRegistry()); 44 } 45 const char *getPassName() const override { 46 return "Hexagon generate mux instructions"; 47 } 48 void getAnalysisUsage(AnalysisUsage &AU) const override { 49 MachineFunctionPass::getAnalysisUsage(AU); 50 } 51 bool runOnMachineFunction(MachineFunction &MF) override; 52 53 private: 54 const HexagonInstrInfo *HII; 55 const HexagonRegisterInfo *HRI; 56 57 struct CondsetInfo { 58 unsigned PredR; 59 unsigned TrueX, FalseX; 60 CondsetInfo() : PredR(0), TrueX(UINT_MAX), FalseX(UINT_MAX) {} 61 }; 62 struct DefUseInfo { 63 BitVector Defs, Uses; 64 DefUseInfo() : Defs(), Uses() {} 65 DefUseInfo(const BitVector &D, const BitVector &U) : Defs(D), Uses(U) {} 66 }; 67 struct MuxInfo { 68 MachineBasicBlock::iterator At; 69 unsigned DefR, PredR; 70 MachineOperand *SrcT, *SrcF; 71 MachineInstr *Def1, *Def2; 72 MuxInfo(MachineBasicBlock::iterator It, unsigned DR, unsigned PR, 73 MachineOperand *TOp, MachineOperand *FOp, 74 MachineInstr *D1, MachineInstr *D2) 75 : At(It), DefR(DR), PredR(PR), SrcT(TOp), SrcF(FOp), Def1(D1), 76 Def2(D2) {} 77 }; 78 typedef DenseMap<MachineInstr*,unsigned> InstrIndexMap; 79 typedef DenseMap<unsigned,DefUseInfo> DefUseInfoMap; 80 typedef SmallVector<MuxInfo,4> MuxInfoList; 81 82 bool isRegPair(unsigned Reg) const { 83 return Hexagon::DoubleRegsRegClass.contains(Reg); 84 } 85 void getSubRegs(unsigned Reg, BitVector &SRs) const; 86 void expandReg(unsigned Reg, BitVector &Set) const; 87 void getDefsUses(const MachineInstr *MI, BitVector &Defs, 88 BitVector &Uses) const; 89 void buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X, 90 DefUseInfoMap &DUM); 91 bool isCondTransfer(unsigned Opc) const; 92 unsigned getMuxOpcode(const MachineOperand &Src1, 93 const MachineOperand &Src2) const; 94 bool genMuxInBlock(MachineBasicBlock &B); 95 }; 96 97 char HexagonGenMux::ID = 0; 98} 99 100INITIALIZE_PASS(HexagonGenMux, "hexagon-mux", 101 "Hexagon generate mux instructions", false, false) 102 103 104void HexagonGenMux::getSubRegs(unsigned Reg, BitVector &SRs) const { 105 for (MCSubRegIterator I(Reg, HRI); I.isValid(); ++I) 106 SRs[*I] = true; 107} 108 109 110void HexagonGenMux::expandReg(unsigned Reg, BitVector &Set) const { 111 if (isRegPair(Reg)) 112 getSubRegs(Reg, Set); 113 else 114 Set[Reg] = true; 115} 116 117 118void HexagonGenMux::getDefsUses(const MachineInstr *MI, BitVector &Defs, 119 BitVector &Uses) const { 120 // First, get the implicit defs and uses for this instruction. 121 unsigned Opc = MI->getOpcode(); 122 const MCInstrDesc &D = HII->get(Opc); 123 if (const MCPhysReg *R = D.ImplicitDefs) 124 while (*R) 125 expandReg(*R++, Defs); 126 if (const MCPhysReg *R = D.ImplicitUses) 127 while (*R) 128 expandReg(*R++, Uses); 129 130 // Look over all operands, and collect explicit defs and uses. 131 for (ConstMIOperands Mo(MI); Mo.isValid(); ++Mo) { 132 if (!Mo->isReg() || Mo->isImplicit()) 133 continue; 134 unsigned R = Mo->getReg(); 135 BitVector &Set = Mo->isDef() ? Defs : Uses; 136 expandReg(R, Set); 137 } 138} 139 140 141void HexagonGenMux::buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X, 142 DefUseInfoMap &DUM) { 143 unsigned Index = 0; 144 unsigned NR = HRI->getNumRegs(); 145 BitVector Defs(NR), Uses(NR); 146 147 for (MachineBasicBlock::iterator I = B.begin(), E = B.end(); I != E; ++I) { 148 MachineInstr *MI = &*I; 149 I2X.insert(std::make_pair(MI, Index)); 150 Defs.reset(); 151 Uses.reset(); 152 getDefsUses(MI, Defs, Uses); 153 DUM.insert(std::make_pair(Index, DefUseInfo(Defs, Uses))); 154 Index++; 155 } 156} 157 158 159bool HexagonGenMux::isCondTransfer(unsigned Opc) const { 160 switch (Opc) { 161 case Hexagon::A2_tfrt: 162 case Hexagon::A2_tfrf: 163 case Hexagon::C2_cmoveit: 164 case Hexagon::C2_cmoveif: 165 return true; 166 } 167 return false; 168} 169 170 171unsigned HexagonGenMux::getMuxOpcode(const MachineOperand &Src1, 172 const MachineOperand &Src2) const { 173 bool IsReg1 = Src1.isReg(), IsReg2 = Src2.isReg(); 174 if (IsReg1) 175 return IsReg2 ? Hexagon::C2_mux : Hexagon::C2_muxir; 176 if (IsReg2) 177 return Hexagon::C2_muxri; 178 179 // Neither is a register. The first source is extendable, but the second 180 // is not (s8). 181 if (Src2.isImm() && isInt<8>(Src2.getImm())) 182 return Hexagon::C2_muxii; 183 184 return 0; 185} 186 187 188bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) { 189 bool Changed = false; 190 InstrIndexMap I2X; 191 DefUseInfoMap DUM; 192 buildMaps(B, I2X, DUM); 193 194 typedef DenseMap<unsigned,CondsetInfo> CondsetMap; 195 CondsetMap CM; 196 MuxInfoList ML; 197 198 MachineBasicBlock::iterator NextI, End = B.end(); 199 for (MachineBasicBlock::iterator I = B.begin(); I != End; I = NextI) { 200 MachineInstr *MI = &*I; 201 NextI = std::next(I); 202 unsigned Opc = MI->getOpcode(); 203 if (!isCondTransfer(Opc)) 204 continue; 205 unsigned DR = MI->getOperand(0).getReg(); 206 if (isRegPair(DR)) 207 continue; 208 209 unsigned PR = MI->getOperand(1).getReg(); 210 unsigned Idx = I2X.lookup(MI); 211 CondsetMap::iterator F = CM.find(DR); 212 bool IfTrue = HII->isPredicatedTrue(Opc); 213 214 // If there is no record of a conditional transfer for this register, 215 // or the predicate register differs, create a new record for it. 216 if (F != CM.end() && F->second.PredR != PR) { 217 CM.erase(F); 218 F = CM.end(); 219 } 220 if (F == CM.end()) { 221 auto It = CM.insert(std::make_pair(DR, CondsetInfo())); 222 F = It.first; 223 F->second.PredR = PR; 224 } 225 CondsetInfo &CI = F->second; 226 if (IfTrue) 227 CI.TrueX = Idx; 228 else 229 CI.FalseX = Idx; 230 if (CI.TrueX == UINT_MAX || CI.FalseX == UINT_MAX) 231 continue; 232 233 // There is now a complete definition of DR, i.e. we have the predicate 234 // register, the definition if-true, and definition if-false. 235 236 // First, check if both definitions are far enough from the definition 237 // of the predicate register. 238 unsigned MinX = std::min(CI.TrueX, CI.FalseX); 239 unsigned MaxX = std::max(CI.TrueX, CI.FalseX); 240 unsigned SearchX = (MaxX > 4) ? MaxX-4 : 0; 241 bool NearDef = false; 242 for (unsigned X = SearchX; X < MaxX; ++X) { 243 const DefUseInfo &DU = DUM.lookup(X); 244 if (!DU.Defs[PR]) 245 continue; 246 NearDef = true; 247 break; 248 } 249 if (NearDef) 250 continue; 251 252 // The predicate register is not defined in the last few instructions. 253 // Check if the conversion to MUX is possible (either "up", i.e. at the 254 // place of the earlier partial definition, or "down", where the later 255 // definition is located). Examine all defs and uses between these two 256 // definitions. 257 // SR1, SR2 - source registers from the first and the second definition. 258 MachineBasicBlock::iterator It1 = B.begin(), It2 = B.begin(); 259 std::advance(It1, MinX); 260 std::advance(It2, MaxX); 261 MachineInstr *Def1 = It1, *Def2 = It2; 262 MachineOperand *Src1 = &Def1->getOperand(2), *Src2 = &Def2->getOperand(2); 263 unsigned SR1 = Src1->isReg() ? Src1->getReg() : 0; 264 unsigned SR2 = Src2->isReg() ? Src2->getReg() : 0; 265 bool Failure = false, CanUp = true, CanDown = true; 266 for (unsigned X = MinX+1; X < MaxX; X++) { 267 const DefUseInfo &DU = DUM.lookup(X); 268 if (DU.Defs[PR] || DU.Defs[DR] || DU.Uses[DR]) { 269 Failure = true; 270 break; 271 } 272 if (CanDown && DU.Defs[SR1]) 273 CanDown = false; 274 if (CanUp && DU.Defs[SR2]) 275 CanUp = false; 276 } 277 if (Failure || (!CanUp && !CanDown)) 278 continue; 279 280 MachineOperand *SrcT = (MinX == CI.TrueX) ? Src1 : Src2; 281 MachineOperand *SrcF = (MinX == CI.FalseX) ? Src1 : Src2; 282 // Prefer "down", since this will move the MUX farther away from the 283 // predicate definition. 284 MachineBasicBlock::iterator At = CanDown ? Def2 : Def1; 285 ML.push_back(MuxInfo(At, DR, PR, SrcT, SrcF, Def1, Def2)); 286 } 287 288 for (unsigned I = 0, N = ML.size(); I < N; ++I) { 289 MuxInfo &MX = ML[I]; 290 MachineBasicBlock &B = *MX.At->getParent(); 291 DebugLoc DL = MX.At->getDebugLoc(); 292 unsigned MxOpc = getMuxOpcode(*MX.SrcT, *MX.SrcF); 293 if (!MxOpc) 294 continue; 295 BuildMI(B, MX.At, DL, HII->get(MxOpc), MX.DefR) 296 .addReg(MX.PredR) 297 .addOperand(*MX.SrcT) 298 .addOperand(*MX.SrcF); 299 B.erase(MX.Def1); 300 B.erase(MX.Def2); 301 Changed = true; 302 } 303 304 return Changed; 305} 306 307bool HexagonGenMux::runOnMachineFunction(MachineFunction &MF) { 308 HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo(); 309 HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); 310 bool Changed = false; 311 for (auto &I : MF) 312 Changed |= genMuxInBlock(I); 313 return Changed; 314} 315 316FunctionPass *llvm::createHexagonGenMux() { 317 return new HexagonGenMux(); 318} 319 320