148575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng//===-- ARMHazardRecognizer.cpp - ARM postra hazard recognizer ------------===//
248575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng//
348575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng//                     The LLVM Compiler Infrastructure
448575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng//
548575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng// This file is distributed under the University of Illinois Open Source
648575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng// License. See LICENSE.TXT for details.
748575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng//
848575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng//===----------------------------------------------------------------------===//
948575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
1048575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng#include "ARMHazardRecognizer.h"
1148575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng#include "ARMBaseInstrInfo.h"
12b72d2a92b75daa9cbac7338aff0cd8ae04c2b4bdEvan Cheng#include "ARMBaseRegisterInfo.h"
1348575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng#include "ARMSubtarget.h"
1448575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng#include "llvm/CodeGen/MachineInstr.h"
1548575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng#include "llvm/CodeGen/ScheduleDAG.h"
1648575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng#include "llvm/Target/TargetRegisterInfo.h"
1748575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Chengusing namespace llvm;
1848575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
1948575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Chengstatic bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI,
2048575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng                         const TargetRegisterInfo &TRI) {
2148575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng  // FIXME: Detect integer instructions properly.
22e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  const MCInstrDesc &MCID = MI->getDesc();
23e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  unsigned Domain = MCID.TSFlags & ARMII::DomainMask;
245a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng  if (MI->mayStore())
2548575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng    return false;
26e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  unsigned Opcode = MCID.getOpcode();
276557bce3ec8d5a82b2ea299a18cb51677b299633Evan Cheng  if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
286557bce3ec8d5a82b2ea299a18cb51677b299633Evan Cheng    return false;
296557bce3ec8d5a82b2ea299a18cb51677b299633Evan Cheng  if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON))
306557bce3ec8d5a82b2ea299a18cb51677b299633Evan Cheng    return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI);
316557bce3ec8d5a82b2ea299a18cb51677b299633Evan Cheng  return false;
3248575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng}
3348575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
3448575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan ChengScheduleHazardRecognizer::HazardType
352da8bc8a5f7705ac131184cd247f48500da0d74eAndrew TrickARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
362da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead");
372da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
3848575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng  MachineInstr *MI = SU->getInstr();
3948575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
4048575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng  if (!MI->isDebugValue()) {
4148575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng    // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following
4248575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng    // a VMLA / VMLS will cause 4 cycle stall.
43e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    const MCInstrDesc &MCID = MI->getDesc();
44e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng    if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) {
4548575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng      MachineInstr *DefMI = LastMI;
46e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng      const MCInstrDesc &LastMCID = LastMI->getDesc();
4748575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng      // Skip over one non-VFP / NEON instruction.
485a96b3dad2f634c9081c8b2b6c2575441dc5a2bdEvan Cheng      if (!LastMI->isBarrier() &&
4984c5eed15baa3710d7fb8522c7a28c8e0b732c2bBob Wilson          // On A9, AGU and NEON/FPU are muxed.
50616471d4bfe4717fa86259ff4534703357b3b723Silviu Baranga          !(STI.isLikeA9() && (LastMI->mayLoad() || LastMI->mayStore())) &&
51e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng          (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) {
5248575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng        MachineBasicBlock::iterator I = LastMI;
5348575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng        if (I != LastMI->getParent()->begin()) {
5448575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng          I = llvm::prior(I);
5548575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng          DefMI = &*I;
5648575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng        }
5748575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng      }
5848575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
5948575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng      if (TII.isFpMLxInstruction(DefMI->getOpcode()) &&
6048575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng          (TII.canCauseFpMLxStall(MI->getOpcode()) ||
6148575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng           hasRAWHazard(DefMI, MI, TRI))) {
6248575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng        // Try to schedule another instruction for the next 4 cycles.
632da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        if (FpMLxStalls == 0)
642da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick          FpMLxStalls = 4;
6548575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng        return Hazard;
6648575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng      }
6748575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng    }
6848575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng  }
6948575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
702da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  return ScoreboardHazardRecognizer::getHazardType(SU, Stalls);
7148575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng}
7248575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
7348575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Chengvoid ARMHazardRecognizer::Reset() {
7448575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng  LastMI = 0;
752da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  FpMLxStalls = 0;
766b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  ScoreboardHazardRecognizer::Reset();
7748575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng}
7848575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
7948575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Chengvoid ARMHazardRecognizer::EmitInstruction(SUnit *SU) {
8048575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng  MachineInstr *MI = SU->getInstr();
8148575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng  if (!MI->isDebugValue()) {
8248575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng    LastMI = MI;
832da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick    FpMLxStalls = 0;
8448575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng  }
8548575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
866b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  ScoreboardHazardRecognizer::EmitInstruction(SU);
8748575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng}
8848575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng
8948575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Chengvoid ARMHazardRecognizer::AdvanceCycle() {
902da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  if (FpMLxStalls && --FpMLxStalls == 0)
9148575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng    // Stalled for 4 cycles but still can't schedule any other instructions.
9248575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng    LastMI = 0;
936b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  ScoreboardHazardRecognizer::AdvanceCycle();
946b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick}
956b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick
966b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ARMHazardRecognizer::RecedeCycle() {
976b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  llvm_unreachable("reverse ARM hazard checking unsupported");
9848575f6ea7d5cd21ab29ca370f58fcf9ca31400bEvan Cheng}
99