1 //===-- HexagonHazardRecognizer.cpp - Hexagon Post RA Hazard Recognizer ---===// 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 // This file defines the hazard recognizer for scheduling on Hexagon. 11 // Use a DFA based hazard recognizer. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "HexagonHazardRecognizer.h" 16 #include "llvm/CodeGen/MachineFunction.h" 17 #include "llvm/CodeGen/MachineInstr.h" 18 #include "llvm/CodeGen/MachineOperand.h" 19 #include "llvm/CodeGen/ScheduleDAG.h" 20 #include "llvm/Support/Debug.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include <cassert> 23 24 using namespace llvm; 25 26 #define DEBUG_TYPE "post-RA-sched" 27 28 void HexagonHazardRecognizer::Reset() { 29 DEBUG(dbgs() << "Reset hazard recognizer\n"); 30 Resources->clearResources(); 31 PacketNum = 0; 32 UsesDotCur = nullptr; 33 DotCurPNum = -1; 34 RegDefs.clear(); 35 } 36 37 ScheduleHazardRecognizer::HazardType 38 HexagonHazardRecognizer::getHazardType(SUnit *SU, int stalls) { 39 MachineInstr *MI = SU->getInstr(); 40 if (!MI || TII->isZeroCost(MI->getOpcode())) 41 return NoHazard; 42 43 if (!Resources->canReserveResources(*MI)) { 44 DEBUG(dbgs() << "*** Hazard in cycle " << PacketNum << ", " << *MI); 45 HazardType RetVal = Hazard; 46 if (TII->mayBeNewStore(*MI)) { 47 // Make sure the register to be stored is defined by an instruction in the 48 // packet. 49 MachineOperand &MO = MI->getOperand(MI->getNumOperands() - 1); 50 if (!MO.isReg() || RegDefs.count(MO.getReg()) == 0) 51 return Hazard; 52 // The .new store version uses different resources so check if it 53 // causes a hazard. 54 MachineFunction *MF = MI->getParent()->getParent(); 55 MachineInstr *NewMI = 56 MF->CreateMachineInstr(TII->get(TII->getDotNewOp(*MI)), 57 MI->getDebugLoc()); 58 if (Resources->canReserveResources(*NewMI)) 59 RetVal = NoHazard; 60 DEBUG(dbgs() << "*** Try .new version? " << (RetVal == NoHazard) << "\n"); 61 MF->DeleteMachineInstr(NewMI); 62 } 63 return RetVal; 64 } 65 66 if (SU == UsesDotCur && DotCurPNum != (int)PacketNum) { 67 DEBUG(dbgs() << "*** .cur Hazard in cycle " << PacketNum << ", " << *MI); 68 return Hazard; 69 } 70 71 return NoHazard; 72 } 73 74 void HexagonHazardRecognizer::AdvanceCycle() { 75 DEBUG(dbgs() << "Advance cycle, clear state\n"); 76 Resources->clearResources(); 77 if (DotCurPNum != -1 && DotCurPNum != (int)PacketNum) { 78 UsesDotCur = nullptr; 79 DotCurPNum = -1; 80 } 81 PacketNum++; 82 RegDefs.clear(); 83 } 84 85 /// If a packet contains a dot cur instruction, then we may prefer the 86 /// instruction that can use the dot cur result. Or, if the use 87 /// isn't scheduled in the same packet, then prefer other instructions 88 /// in the subsequent packet. 89 bool HexagonHazardRecognizer::ShouldPreferAnother(SUnit *SU) { 90 return UsesDotCur && ((SU == UsesDotCur) ^ (DotCurPNum == (int)PacketNum)); 91 } 92 93 void HexagonHazardRecognizer::EmitInstruction(SUnit *SU) { 94 MachineInstr *MI = SU->getInstr(); 95 if (!MI) 96 return; 97 98 // Keep the set of definitions for each packet, which is used to determine 99 // if a .new can be used. 100 for (const MachineOperand &MO : MI->operands()) 101 if (MO.isReg() && MO.isDef() && !MO.isImplicit()) 102 RegDefs.insert(MO.getReg()); 103 104 if (TII->isZeroCost(MI->getOpcode())) 105 return; 106 107 if (!Resources->canReserveResources(*MI)) { 108 // It must be a .new store since other instructions must be able to be 109 // reserved at this point. 110 assert(TII->mayBeNewStore(*MI) && "Expecting .new store"); 111 MachineFunction *MF = MI->getParent()->getParent(); 112 MachineInstr *NewMI = 113 MF->CreateMachineInstr(TII->get(TII->getDotNewOp(*MI)), 114 MI->getDebugLoc()); 115 assert(Resources->canReserveResources(*NewMI)); 116 Resources->reserveResources(*NewMI); 117 MF->DeleteMachineInstr(NewMI); 118 } 119 else 120 Resources->reserveResources(*MI); 121 DEBUG(dbgs() << " Add instruction " << *MI); 122 123 // When scheduling a dot cur instruction, check if there is an instruction 124 // that can use the dot cur in the same packet. If so, we'll attempt to 125 // schedule it before other instructions. We only do this if the use has 126 // the same height as the dot cur. Otherwise, we may miss scheduling an 127 // instruction with a greater height, which is more important. 128 if (TII->mayBeCurLoad(*MI)) 129 for (auto &S : SU->Succs) 130 if (S.isAssignedRegDep() && S.getLatency() == 0 && 131 SU->getHeight() == S.getSUnit()->getHeight()) { 132 UsesDotCur = S.getSUnit(); 133 DotCurPNum = PacketNum; 134 break; 135 } 136 if (SU == UsesDotCur) { 137 UsesDotCur = nullptr; 138 DotCurPNum = -1; 139 } 140 } 141