10b57cec5SDimitry Andric //===-- HexagonHazardRecognizer.cpp - Hexagon Post RA Hazard Recognizer ---===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the hazard recognizer for scheduling on Hexagon.
100b57cec5SDimitry Andric // Use a DFA based hazard recognizer.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "HexagonHazardRecognizer.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h"
190b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
200b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
210b57cec5SDimitry Andric #include <cassert>
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric #define DEBUG_TYPE "post-RA-sched"
260b57cec5SDimitry Andric
Reset()270b57cec5SDimitry Andric void HexagonHazardRecognizer::Reset() {
280b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Reset hazard recognizer\n");
290b57cec5SDimitry Andric Resources->clearResources();
300b57cec5SDimitry Andric PacketNum = 0;
310b57cec5SDimitry Andric UsesDotCur = nullptr;
320b57cec5SDimitry Andric DotCurPNum = -1;
330b57cec5SDimitry Andric UsesLoad = false;
340b57cec5SDimitry Andric PrefVectorStoreNew = nullptr;
350b57cec5SDimitry Andric RegDefs.clear();
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric ScheduleHazardRecognizer::HazardType
getHazardType(SUnit * SU,int stalls)390b57cec5SDimitry Andric HexagonHazardRecognizer::getHazardType(SUnit *SU, int stalls) {
400b57cec5SDimitry Andric MachineInstr *MI = SU->getInstr();
410b57cec5SDimitry Andric if (!MI || TII->isZeroCost(MI->getOpcode()))
420b57cec5SDimitry Andric return NoHazard;
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric if (!Resources->canReserveResources(*MI)) {
450b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "*** Hazard in cycle " << PacketNum << ", " << *MI);
460b57cec5SDimitry Andric HazardType RetVal = Hazard;
4704eeddc0SDimitry Andric if (isNewStore(*MI)) {
480b57cec5SDimitry Andric // The .new store version uses different resources so check if it
490b57cec5SDimitry Andric // causes a hazard.
500b57cec5SDimitry Andric MachineFunction *MF = MI->getParent()->getParent();
510b57cec5SDimitry Andric MachineInstr *NewMI =
520b57cec5SDimitry Andric MF->CreateMachineInstr(TII->get(TII->getDotNewOp(*MI)),
530b57cec5SDimitry Andric MI->getDebugLoc());
540b57cec5SDimitry Andric if (Resources->canReserveResources(*NewMI))
550b57cec5SDimitry Andric RetVal = NoHazard;
560b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "*** Try .new version? " << (RetVal == NoHazard)
570b57cec5SDimitry Andric << "\n");
580eae32dcSDimitry Andric MF->deleteMachineInstr(NewMI);
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric return RetVal;
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric if (SU == UsesDotCur && DotCurPNum != (int)PacketNum) {
640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "*** .cur Hazard in cycle " << PacketNum << ", "
650b57cec5SDimitry Andric << *MI);
660b57cec5SDimitry Andric return Hazard;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric return NoHazard;
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric
AdvanceCycle()720b57cec5SDimitry Andric void HexagonHazardRecognizer::AdvanceCycle() {
730b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Advance cycle, clear state\n");
740b57cec5SDimitry Andric Resources->clearResources();
750b57cec5SDimitry Andric if (DotCurPNum != -1 && DotCurPNum != (int)PacketNum) {
760b57cec5SDimitry Andric UsesDotCur = nullptr;
770b57cec5SDimitry Andric DotCurPNum = -1;
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric UsesLoad = false;
800b57cec5SDimitry Andric PrefVectorStoreNew = nullptr;
810b57cec5SDimitry Andric PacketNum++;
820b57cec5SDimitry Andric RegDefs.clear();
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric /// Handle the cases when we prefer one instruction over another. Case 1 - we
860b57cec5SDimitry Andric /// prefer not to generate multiple loads in the packet to avoid a potential
870b57cec5SDimitry Andric /// bank conflict. Case 2 - if a packet contains a dot cur instruction, then we
880b57cec5SDimitry Andric /// prefer the instruction that can use the dot cur result. However, if the use
890b57cec5SDimitry Andric /// is not scheduled in the same packet, then prefer other instructions in the
900b57cec5SDimitry Andric /// subsequent packet. Case 3 - we prefer a vector store that can be converted
910b57cec5SDimitry Andric /// to a .new store. The packetizer will not generate the .new store if the
920b57cec5SDimitry Andric /// store doesn't have resources to fit in the packet (but the .new store may
930b57cec5SDimitry Andric /// have resources). We attempt to schedule the store as soon as possible to
940b57cec5SDimitry Andric /// help packetize the two instructions together.
ShouldPreferAnother(SUnit * SU)950b57cec5SDimitry Andric bool HexagonHazardRecognizer::ShouldPreferAnother(SUnit *SU) {
960b57cec5SDimitry Andric if (PrefVectorStoreNew != nullptr && PrefVectorStoreNew != SU)
970b57cec5SDimitry Andric return true;
980b57cec5SDimitry Andric if (UsesLoad && SU->isInstr() && SU->getInstr()->mayLoad())
990b57cec5SDimitry Andric return true;
1000b57cec5SDimitry Andric return UsesDotCur && ((SU == UsesDotCur) ^ (DotCurPNum == (int)PacketNum));
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric
10304eeddc0SDimitry Andric /// Return true if the instruction would be converted to a new value store when
10404eeddc0SDimitry Andric /// packetized.
isNewStore(MachineInstr & MI)10504eeddc0SDimitry Andric bool HexagonHazardRecognizer::isNewStore(MachineInstr &MI) {
10604eeddc0SDimitry Andric if (!TII->mayBeNewStore(MI))
10704eeddc0SDimitry Andric return false;
10804eeddc0SDimitry Andric MachineOperand &MO = MI.getOperand(MI.getNumOperands() - 1);
109*81ad6265SDimitry Andric return MO.isReg() && RegDefs.contains(MO.getReg());
11004eeddc0SDimitry Andric }
11104eeddc0SDimitry Andric
EmitInstruction(SUnit * SU)1120b57cec5SDimitry Andric void HexagonHazardRecognizer::EmitInstruction(SUnit *SU) {
1130b57cec5SDimitry Andric MachineInstr *MI = SU->getInstr();
1140b57cec5SDimitry Andric if (!MI)
1150b57cec5SDimitry Andric return;
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric // Keep the set of definitions for each packet, which is used to determine
1180b57cec5SDimitry Andric // if a .new can be used.
1190b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands())
1200b57cec5SDimitry Andric if (MO.isReg() && MO.isDef() && !MO.isImplicit())
1210b57cec5SDimitry Andric RegDefs.insert(MO.getReg());
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric if (TII->isZeroCost(MI->getOpcode()))
1240b57cec5SDimitry Andric return;
1250b57cec5SDimitry Andric
12604eeddc0SDimitry Andric if (!Resources->canReserveResources(*MI) || isNewStore(*MI)) {
1270b57cec5SDimitry Andric // It must be a .new store since other instructions must be able to be
1280b57cec5SDimitry Andric // reserved at this point.
1290b57cec5SDimitry Andric assert(TII->mayBeNewStore(*MI) && "Expecting .new store");
1300b57cec5SDimitry Andric MachineFunction *MF = MI->getParent()->getParent();
1310b57cec5SDimitry Andric MachineInstr *NewMI =
1320b57cec5SDimitry Andric MF->CreateMachineInstr(TII->get(TII->getDotNewOp(*MI)),
1330b57cec5SDimitry Andric MI->getDebugLoc());
13404eeddc0SDimitry Andric if (Resources->canReserveResources(*NewMI))
1350b57cec5SDimitry Andric Resources->reserveResources(*NewMI);
1360b57cec5SDimitry Andric else
1370b57cec5SDimitry Andric Resources->reserveResources(*MI);
13804eeddc0SDimitry Andric MF->deleteMachineInstr(NewMI);
13904eeddc0SDimitry Andric } else
14004eeddc0SDimitry Andric Resources->reserveResources(*MI);
1410b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Add instruction " << *MI);
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric // When scheduling a dot cur instruction, check if there is an instruction
1440b57cec5SDimitry Andric // that can use the dot cur in the same packet. If so, we'll attempt to
1450b57cec5SDimitry Andric // schedule it before other instructions. We only do this if the load has a
1460b57cec5SDimitry Andric // single zero-latency use.
1470b57cec5SDimitry Andric if (TII->mayBeCurLoad(*MI))
1480b57cec5SDimitry Andric for (auto &S : SU->Succs)
1490b57cec5SDimitry Andric if (S.isAssignedRegDep() && S.getLatency() == 0 &&
1500b57cec5SDimitry Andric S.getSUnit()->NumPredsLeft == 1) {
1510b57cec5SDimitry Andric UsesDotCur = S.getSUnit();
1520b57cec5SDimitry Andric DotCurPNum = PacketNum;
1530b57cec5SDimitry Andric break;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric if (SU == UsesDotCur) {
1560b57cec5SDimitry Andric UsesDotCur = nullptr;
1570b57cec5SDimitry Andric DotCurPNum = -1;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric UsesLoad = MI->mayLoad();
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric if (TII->isHVXVec(*MI) && !MI->mayLoad() && !MI->mayStore())
1630b57cec5SDimitry Andric for (auto &S : SU->Succs)
1640b57cec5SDimitry Andric if (S.isAssignedRegDep() && S.getLatency() == 0 &&
1650b57cec5SDimitry Andric TII->mayBeNewStore(*S.getSUnit()->getInstr()) &&
1660b57cec5SDimitry Andric Resources->canReserveResources(*S.getSUnit()->getInstr())) {
1670b57cec5SDimitry Andric PrefVectorStoreNew = S.getSUnit();
1680b57cec5SDimitry Andric break;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric }
171