1 //===-- ARMHazardRecognizer.cpp - ARM postra hazard recognizer ------------===// 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 9 #include "ARMHazardRecognizer.h" 10 #include "ARMBaseInstrInfo.h" 11 #include "ARMBaseRegisterInfo.h" 12 #include "ARMSubtarget.h" 13 #include "llvm/CodeGen/MachineInstr.h" 14 #include "llvm/CodeGen/ScheduleDAG.h" 15 #include "llvm/CodeGen/TargetRegisterInfo.h" 16 using namespace llvm; 17 18 static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, 19 const TargetRegisterInfo &TRI) { 20 // FIXME: Detect integer instructions properly. 21 const MCInstrDesc &MCID = MI->getDesc(); 22 unsigned Domain = MCID.TSFlags & ARMII::DomainMask; 23 if (MI->mayStore()) 24 return false; 25 unsigned Opcode = MCID.getOpcode(); 26 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) 27 return false; 28 if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) 29 return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI); 30 return false; 31 } 32 33 ScheduleHazardRecognizer::HazardType 34 ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { 35 assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead"); 36 37 MachineInstr *MI = SU->getInstr(); 38 39 if (!MI->isDebugInstr()) { 40 // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following 41 // a VMLA / VMLS will cause 4 cycle stall. 42 const MCInstrDesc &MCID = MI->getDesc(); 43 if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { 44 MachineInstr *DefMI = LastMI; 45 const MCInstrDesc &LastMCID = LastMI->getDesc(); 46 const MachineFunction *MF = MI->getParent()->getParent(); 47 const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>( 48 MF->getSubtarget().getInstrInfo()); 49 50 // Skip over one non-VFP / NEON instruction. 51 if (!LastMI->isBarrier() && 52 !(TII.getSubtarget().hasMuxedUnits() && LastMI->mayLoadOrStore()) && 53 (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { 54 MachineBasicBlock::iterator I = LastMI; 55 if (I != LastMI->getParent()->begin()) { 56 I = std::prev(I); 57 DefMI = &*I; 58 } 59 } 60 61 if (TII.isFpMLxInstruction(DefMI->getOpcode()) && 62 (TII.canCauseFpMLxStall(MI->getOpcode()) || 63 hasRAWHazard(DefMI, MI, TII.getRegisterInfo()))) { 64 // Try to schedule another instruction for the next 4 cycles. 65 if (FpMLxStalls == 0) 66 FpMLxStalls = 4; 67 return Hazard; 68 } 69 } 70 } 71 72 return ScoreboardHazardRecognizer::getHazardType(SU, Stalls); 73 } 74 75 void ARMHazardRecognizer::Reset() { 76 LastMI = nullptr; 77 FpMLxStalls = 0; 78 ScoreboardHazardRecognizer::Reset(); 79 } 80 81 void ARMHazardRecognizer::EmitInstruction(SUnit *SU) { 82 MachineInstr *MI = SU->getInstr(); 83 if (!MI->isDebugInstr()) { 84 LastMI = MI; 85 FpMLxStalls = 0; 86 } 87 88 ScoreboardHazardRecognizer::EmitInstruction(SU); 89 } 90 91 void ARMHazardRecognizer::AdvanceCycle() { 92 if (FpMLxStalls && --FpMLxStalls == 0) 93 // Stalled for 4 cycles but still can't schedule any other instructions. 94 LastMI = nullptr; 95 ScoreboardHazardRecognizer::AdvanceCycle(); 96 } 97 98 void ARMHazardRecognizer::RecedeCycle() { 99 llvm_unreachable("reverse ARM hazard checking unsupported"); 100 } 101