]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
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" | |
17 | using namespace llvm; | |
18 | ||
19 | static 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 | ||
34 | ScheduleHazardRecognizer::HazardType | |
35 | ARMHazardRecognizer::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(); | |
1a4d82fc JJ |
47 | const TargetMachine &TM = |
48 | MI->getParent()->getParent()->getTarget(); | |
49 | const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>( | |
50 | TM.getSubtargetImpl()->getInstrInfo()); | |
51 | ||
223e47cc LB |
52 | // Skip over one non-VFP / NEON instruction. |
53 | if (!LastMI->isBarrier() && | |
54 | // On A9, AGU and NEON/FPU are muxed. | |
1a4d82fc JJ |
55 | !(TII.getSubtarget().isLikeA9() && |
56 | (LastMI->mayLoad() || LastMI->mayStore())) && | |
223e47cc LB |
57 | (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { |
58 | MachineBasicBlock::iterator I = LastMI; | |
59 | if (I != LastMI->getParent()->begin()) { | |
1a4d82fc | 60 | I = std::prev(I); |
223e47cc LB |
61 | DefMI = &*I; |
62 | } | |
63 | } | |
64 | ||
65 | if (TII.isFpMLxInstruction(DefMI->getOpcode()) && | |
66 | (TII.canCauseFpMLxStall(MI->getOpcode()) || | |
1a4d82fc | 67 | hasRAWHazard(DefMI, MI, TII.getRegisterInfo()))) { |
223e47cc LB |
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 | ||
79 | void ARMHazardRecognizer::Reset() { | |
1a4d82fc | 80 | LastMI = nullptr; |
223e47cc LB |
81 | FpMLxStalls = 0; |
82 | ScoreboardHazardRecognizer::Reset(); | |
83 | } | |
84 | ||
85 | void 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 | ||
95 | void ARMHazardRecognizer::AdvanceCycle() { | |
96 | if (FpMLxStalls && --FpMLxStalls == 0) | |
97 | // Stalled for 4 cycles but still can't schedule any other instructions. | |
1a4d82fc | 98 | LastMI = nullptr; |
223e47cc LB |
99 | ScoreboardHazardRecognizer::AdvanceCycle(); |
100 | } | |
101 | ||
102 | void ARMHazardRecognizer::RecedeCycle() { | |
103 | llvm_unreachable("reverse ARM hazard checking unsupported"); | |
104 | } |