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