LLVM API Documentation

ARMHazardRecognizer.cpp
Go to the documentation of this file.
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 }