| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 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" | 
| Evan Cheng | e45d685 | 2011-01-11 21:46:47 +0000 | [diff] [blame] | 12 | #include "ARMBaseRegisterInfo.h" | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 13 | #include "ARMSubtarget.h" | 
|  | 14 | #include "llvm/CodeGen/MachineInstr.h" | 
|  | 15 | #include "llvm/CodeGen/ScheduleDAG.h" | 
|  | 16 | #include "llvm/Target/TargetRegisterInfo.h" | 
|  | 17 | using namespace llvm; | 
|  | 18 |  | 
|  | 19 | static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, | 
|  | 20 | const TargetRegisterInfo &TRI) { | 
|  | 21 | // FIXME: Detect integer instructions properly. | 
| Evan Cheng | 6cc775f | 2011-06-28 19:10:37 +0000 | [diff] [blame] | 22 | const MCInstrDesc &MCID = MI->getDesc(); | 
|  | 23 | unsigned Domain = MCID.TSFlags & ARMII::DomainMask; | 
| Evan Cheng | 7f8e563 | 2011-12-07 07:15:52 +0000 | [diff] [blame] | 24 | if (MI->mayStore()) | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 25 | return false; | 
| Evan Cheng | 6cc775f | 2011-06-28 19:10:37 +0000 | [diff] [blame] | 26 | unsigned Opcode = MCID.getOpcode(); | 
| Evan Cheng | 04ad35b | 2011-02-22 19:53:14 +0000 | [diff] [blame] | 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; | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 32 | } | 
|  | 33 |  | 
|  | 34 | ScheduleHazardRecognizer::HazardType | 
| Andrew Trick | 10ffc2b | 2010-12-24 05:03:26 +0000 | [diff] [blame] | 35 | ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { | 
|  | 36 | assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead"); | 
|  | 37 |  | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 38 | MachineInstr *MI = SU->getInstr(); | 
|  | 39 |  | 
|  | 40 | if (!MI->isDebugValue()) { | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 41 | // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following | 
|  | 42 | // a VMLA / VMLS will cause 4 cycle stall. | 
| Evan Cheng | 6cc775f | 2011-06-28 19:10:37 +0000 | [diff] [blame] | 43 | const MCInstrDesc &MCID = MI->getDesc(); | 
|  | 44 | if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 45 | MachineInstr *DefMI = LastMI; | 
| Evan Cheng | 6cc775f | 2011-06-28 19:10:37 +0000 | [diff] [blame] | 46 | const MCInstrDesc &LastMCID = LastMI->getDesc(); | 
| Eric Christopher | 1b21f00 | 2015-01-29 00:19:33 +0000 | [diff] [blame] | 47 | const MachineFunction *MF = MI->getParent()->getParent(); | 
| Eric Christopher | d913448 | 2014-08-04 21:25:23 +0000 | [diff] [blame] | 48 | const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>( | 
| Eric Christopher | 1b21f00 | 2015-01-29 00:19:33 +0000 | [diff] [blame] | 49 | MF->getSubtarget().getInstrInfo()); | 
| Bill Wendling | f95178e | 2013-06-07 05:54:19 +0000 | [diff] [blame] | 50 |  | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 51 | // Skip over one non-VFP / NEON instruction. | 
| Evan Cheng | 7f8e563 | 2011-12-07 07:15:52 +0000 | [diff] [blame] | 52 | if (!LastMI->isBarrier() && | 
| Bob Wilson | 0858c3a | 2011-04-19 18:11:57 +0000 | [diff] [blame] | 53 | // On A9, AGU and NEON/FPU are muxed. | 
| Bill Wendling | f95178e | 2013-06-07 05:54:19 +0000 | [diff] [blame] | 54 | !(TII.getSubtarget().isLikeA9() && | 
|  | 55 | (LastMI->mayLoad() || LastMI->mayStore())) && | 
| Evan Cheng | 6cc775f | 2011-06-28 19:10:37 +0000 | [diff] [blame] | 56 | (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 57 | MachineBasicBlock::iterator I = LastMI; | 
|  | 58 | if (I != LastMI->getParent()->begin()) { | 
| Benjamin Kramer | b6d0bd4 | 2014-03-02 12:27:27 +0000 | [diff] [blame] | 59 | I = std::prev(I); | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 60 | DefMI = &*I; | 
|  | 61 | } | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | if (TII.isFpMLxInstruction(DefMI->getOpcode()) && | 
|  | 65 | (TII.canCauseFpMLxStall(MI->getOpcode()) || | 
| Bill Wendling | f95178e | 2013-06-07 05:54:19 +0000 | [diff] [blame] | 66 | hasRAWHazard(DefMI, MI, TII.getRegisterInfo()))) { | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 67 | // Try to schedule another instruction for the next 4 cycles. | 
| Andrew Trick | 10ffc2b | 2010-12-24 05:03:26 +0000 | [diff] [blame] | 68 | if (FpMLxStalls == 0) | 
|  | 69 | FpMLxStalls = 4; | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 70 | return Hazard; | 
|  | 71 | } | 
|  | 72 | } | 
|  | 73 | } | 
|  | 74 |  | 
| Andrew Trick | 10ffc2b | 2010-12-24 05:03:26 +0000 | [diff] [blame] | 75 | return ScoreboardHazardRecognizer::getHazardType(SU, Stalls); | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 76 | } | 
|  | 77 |  | 
|  | 78 | void ARMHazardRecognizer::Reset() { | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 79 | LastMI = nullptr; | 
| Andrew Trick | 10ffc2b | 2010-12-24 05:03:26 +0000 | [diff] [blame] | 80 | FpMLxStalls = 0; | 
| Andrew Trick | 00067fb | 2010-12-08 20:04:29 +0000 | [diff] [blame] | 81 | ScoreboardHazardRecognizer::Reset(); | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 82 | } | 
|  | 83 |  | 
|  | 84 | void ARMHazardRecognizer::EmitInstruction(SUnit *SU) { | 
|  | 85 | MachineInstr *MI = SU->getInstr(); | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 86 | if (!MI->isDebugValue()) { | 
|  | 87 | LastMI = MI; | 
| Andrew Trick | 10ffc2b | 2010-12-24 05:03:26 +0000 | [diff] [blame] | 88 | FpMLxStalls = 0; | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 89 | } | 
|  | 90 |  | 
| Andrew Trick | 00067fb | 2010-12-08 20:04:29 +0000 | [diff] [blame] | 91 | ScoreboardHazardRecognizer::EmitInstruction(SU); | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 92 | } | 
|  | 93 |  | 
|  | 94 | void ARMHazardRecognizer::AdvanceCycle() { | 
| Andrew Trick | 10ffc2b | 2010-12-24 05:03:26 +0000 | [diff] [blame] | 95 | if (FpMLxStalls && --FpMLxStalls == 0) | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 96 | // Stalled for 4 cycles but still can't schedule any other instructions. | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 97 | LastMI = nullptr; | 
| Andrew Trick | 00067fb | 2010-12-08 20:04:29 +0000 | [diff] [blame] | 98 | ScoreboardHazardRecognizer::AdvanceCycle(); | 
|  | 99 | } | 
|  | 100 |  | 
|  | 101 | void ARMHazardRecognizer::RecedeCycle() { | 
|  | 102 | llvm_unreachable("reverse ARM hazard checking unsupported"); | 
| Evan Cheng | 62c7b5b | 2010-12-05 22:04:16 +0000 | [diff] [blame] | 103 | } |