LLVM API Documentation
00001 //===-- ARMHazardRecognizer.cpp - ARM postra hazard recognizer ------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "ARMHazardRecognizer.h" 00011 #include "ARMBaseInstrInfo.h" 00012 #include "ARMBaseRegisterInfo.h" 00013 #include "ARMSubtarget.h" 00014 #include "llvm/CodeGen/MachineInstr.h" 00015 #include "llvm/CodeGen/ScheduleDAG.h" 00016 #include "llvm/Target/TargetRegisterInfo.h" 00017 using namespace llvm; 00018 00019 static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, 00020 const TargetRegisterInfo &TRI) { 00021 // FIXME: Detect integer instructions properly. 00022 const MCInstrDesc &MCID = MI->getDesc(); 00023 unsigned Domain = MCID.TSFlags & ARMII::DomainMask; 00024 if (MI->mayStore()) 00025 return false; 00026 unsigned Opcode = MCID.getOpcode(); 00027 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) 00028 return false; 00029 if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) 00030 return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI); 00031 return false; 00032 } 00033 00034 ScheduleHazardRecognizer::HazardType 00035 ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { 00036 assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead"); 00037 00038 MachineInstr *MI = SU->getInstr(); 00039 00040 if (!MI->isDebugValue()) { 00041 // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following 00042 // a VMLA / VMLS will cause 4 cycle stall. 00043 const MCInstrDesc &MCID = MI->getDesc(); 00044 if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { 00045 MachineInstr *DefMI = LastMI; 00046 const MCInstrDesc &LastMCID = LastMI->getDesc(); 00047 const TargetMachine &TM = 00048 MI->getParent()->getParent()->getTarget(); 00049 const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>( 00050 TM.getSubtargetImpl()->getInstrInfo()); 00051 00052 // Skip over one non-VFP / NEON instruction. 00053 if (!LastMI->isBarrier() && 00054 // On A9, AGU and NEON/FPU are muxed. 00055 !(TII.getSubtarget().isLikeA9() && 00056 (LastMI->mayLoad() || LastMI->mayStore())) && 00057 (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { 00058 MachineBasicBlock::iterator I = LastMI; 00059 if (I != LastMI->getParent()->begin()) { 00060 I = std::prev(I); 00061 DefMI = &*I; 00062 } 00063 } 00064 00065 if (TII.isFpMLxInstruction(DefMI->getOpcode()) && 00066 (TII.canCauseFpMLxStall(MI->getOpcode()) || 00067 hasRAWHazard(DefMI, MI, TII.getRegisterInfo()))) { 00068 // Try to schedule another instruction for the next 4 cycles. 00069 if (FpMLxStalls == 0) 00070 FpMLxStalls = 4; 00071 return Hazard; 00072 } 00073 } 00074 } 00075 00076 return ScoreboardHazardRecognizer::getHazardType(SU, Stalls); 00077 } 00078 00079 void ARMHazardRecognizer::Reset() { 00080 LastMI = nullptr; 00081 FpMLxStalls = 0; 00082 ScoreboardHazardRecognizer::Reset(); 00083 } 00084 00085 void ARMHazardRecognizer::EmitInstruction(SUnit *SU) { 00086 MachineInstr *MI = SU->getInstr(); 00087 if (!MI->isDebugValue()) { 00088 LastMI = MI; 00089 FpMLxStalls = 0; 00090 } 00091 00092 ScoreboardHazardRecognizer::EmitInstruction(SU); 00093 } 00094 00095 void ARMHazardRecognizer::AdvanceCycle() { 00096 if (FpMLxStalls && --FpMLxStalls == 0) 00097 // Stalled for 4 cycles but still can't schedule any other instructions. 00098 LastMI = nullptr; 00099 ScoreboardHazardRecognizer::AdvanceCycle(); 00100 } 00101 00102 void ARMHazardRecognizer::RecedeCycle() { 00103 llvm_unreachable("reverse ARM hazard checking unsupported"); 00104 }