1218885Sdim//===-- ARMHazardRecognizer.cpp - ARM postra hazard recognizer ------------===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim 10218885Sdim#include "ARMHazardRecognizer.h" 11218885Sdim#include "ARMBaseInstrInfo.h" 12218885Sdim#include "ARMBaseRegisterInfo.h" 13218885Sdim#include "ARMSubtarget.h" 14218885Sdim#include "llvm/CodeGen/MachineInstr.h" 15218885Sdim#include "llvm/CodeGen/ScheduleDAG.h" 16218885Sdim#include "llvm/Target/TargetRegisterInfo.h" 17218885Sdimusing namespace llvm; 18218885Sdim 19218885Sdimstatic bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, 20218885Sdim const TargetRegisterInfo &TRI) { 21218885Sdim // FIXME: Detect integer instructions properly. 22224145Sdim const MCInstrDesc &MCID = MI->getDesc(); 23224145Sdim unsigned Domain = MCID.TSFlags & ARMII::DomainMask; 24235633Sdim if (MI->mayStore()) 25218885Sdim return false; 26224145Sdim unsigned Opcode = MCID.getOpcode(); 27219077Sdim if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) 28219077Sdim return false; 29219077Sdim if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) 30219077Sdim return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI); 31219077Sdim return false; 32218885Sdim} 33218885Sdim 34218885SdimScheduleHazardRecognizer::HazardType 35218885SdimARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { 36218885Sdim assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead"); 37218885Sdim 38218885Sdim MachineInstr *MI = SU->getInstr(); 39218885Sdim 40218885Sdim if (!MI->isDebugValue()) { 41218885Sdim // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following 42218885Sdim // a VMLA / VMLS will cause 4 cycle stall. 43224145Sdim const MCInstrDesc &MCID = MI->getDesc(); 44224145Sdim if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { 45218885Sdim MachineInstr *DefMI = LastMI; 46224145Sdim const MCInstrDesc &LastMCID = LastMI->getDesc(); 47263509Sdim const TargetMachine &TM = 48263509Sdim MI->getParent()->getParent()->getTarget(); 49263509Sdim const ARMBaseInstrInfo &TII = 50263509Sdim *static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo()); 51263509Sdim 52218885Sdim // Skip over one non-VFP / NEON instruction. 53235633Sdim if (!LastMI->isBarrier() && 54221345Sdim // On A9, AGU and NEON/FPU are muxed. 55263509Sdim !(TII.getSubtarget().isLikeA9() && 56263509Sdim (LastMI->mayLoad() || LastMI->mayStore())) && 57224145Sdim (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { 58218885Sdim MachineBasicBlock::iterator I = LastMI; 59218885Sdim if (I != LastMI->getParent()->begin()) { 60218885Sdim I = llvm::prior(I); 61218885Sdim DefMI = &*I; 62218885Sdim } 63218885Sdim } 64218885Sdim 65218885Sdim if (TII.isFpMLxInstruction(DefMI->getOpcode()) && 66218885Sdim (TII.canCauseFpMLxStall(MI->getOpcode()) || 67263509Sdim hasRAWHazard(DefMI, MI, TII.getRegisterInfo()))) { 68218885Sdim // Try to schedule another instruction for the next 4 cycles. 69218885Sdim if (FpMLxStalls == 0) 70218885Sdim FpMLxStalls = 4; 71218885Sdim return Hazard; 72218885Sdim } 73218885Sdim } 74218885Sdim } 75218885Sdim 76218885Sdim return ScoreboardHazardRecognizer::getHazardType(SU, Stalls); 77218885Sdim} 78218885Sdim 79218885Sdimvoid ARMHazardRecognizer::Reset() { 80218885Sdim LastMI = 0; 81218885Sdim FpMLxStalls = 0; 82218885Sdim ScoreboardHazardRecognizer::Reset(); 83218885Sdim} 84218885Sdim 85218885Sdimvoid ARMHazardRecognizer::EmitInstruction(SUnit *SU) { 86218885Sdim MachineInstr *MI = SU->getInstr(); 87218885Sdim if (!MI->isDebugValue()) { 88218885Sdim LastMI = MI; 89218885Sdim FpMLxStalls = 0; 90218885Sdim } 91218885Sdim 92218885Sdim ScoreboardHazardRecognizer::EmitInstruction(SU); 93218885Sdim} 94218885Sdim 95218885Sdimvoid ARMHazardRecognizer::AdvanceCycle() { 96218885Sdim if (FpMLxStalls && --FpMLxStalls == 0) 97218885Sdim // Stalled for 4 cycles but still can't schedule any other instructions. 98218885Sdim LastMI = 0; 99218885Sdim ScoreboardHazardRecognizer::AdvanceCycle(); 100218885Sdim} 101218885Sdim 102218885Sdimvoid ARMHazardRecognizer::RecedeCycle() { 103218885Sdim llvm_unreachable("reverse ARM hazard checking unsupported"); 104218885Sdim} 105