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