LLVM  16.0.0git
ARMHazardRecognizer.cpp
Go to the documentation of this file.
1 //===-- ARMHazardRecognizer.cpp - ARM postra hazard recognizer ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ARMHazardRecognizer.h"
10 #include "ARMBaseInstrInfo.h"
11 #include "ARMBaseRegisterInfo.h"
12 #include "ARMSubtarget.h"
20 
21 using namespace llvm;
22 
23 static cl::opt<int> DataBankMask("arm-data-bank-mask", cl::init(-1),
24  cl::Hidden);
25 static cl::opt<bool> AssumeITCMConflict("arm-assume-itcm-bankconflict",
26  cl::init(false), cl::Hidden);
27 
29  const TargetRegisterInfo &TRI) {
30  // FIXME: Detect integer instructions properly.
31  const MCInstrDesc &MCID = MI->getDesc();
32  unsigned Domain = MCID.TSFlags & ARMII::DomainMask;
33  if (MI->mayStore())
34  return false;
35  unsigned Opcode = MCID.getOpcode();
36  if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
37  return false;
39  return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI);
40  return false;
41 }
42 
45  assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead");
46 
47  MachineInstr *MI = SU->getInstr();
48 
49  if (!MI->isDebugInstr()) {
50  // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following
51  // a VMLA / VMLS will cause 4 cycle stall.
52  const MCInstrDesc &MCID = MI->getDesc();
53  if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) {
54  MachineInstr *DefMI = LastMI;
55  const MCInstrDesc &LastMCID = LastMI->getDesc();
56  const MachineFunction *MF = MI->getParent()->getParent();
57  const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>(
58  MF->getSubtarget().getInstrInfo());
59 
60  // Skip over one non-VFP / NEON instruction.
61  if (!LastMI->isBarrier() &&
62  !(TII.getSubtarget().hasMuxedUnits() && LastMI->mayLoadOrStore()) &&
65  if (I != LastMI->getParent()->begin()) {
66  I = std::prev(I);
67  DefMI = &*I;
68  }
69  }
70 
71  if (TII.isFpMLxInstruction(DefMI->getOpcode()) &&
72  (TII.canCauseFpMLxStall(MI->getOpcode()) ||
73  hasRAWHazard(DefMI, MI, TII.getRegisterInfo()))) {
74  // Try to schedule another instruction for the next 4 cycles.
75  if (FpMLxStalls == 0)
76  FpMLxStalls = 4;
77  return Hazard;
78  }
79  }
80  }
81  return NoHazard;
82 }
83 
85  LastMI = nullptr;
86  FpMLxStalls = 0;
87 }
88 
90  MachineInstr *MI = SU->getInstr();
91  if (!MI->isDebugInstr()) {
92  LastMI = MI;
93  FpMLxStalls = 0;
94  }
95 }
96 
98  if (FpMLxStalls && --FpMLxStalls == 0)
99  // Stalled for 4 cycles but still can't schedule any other instructions.
100  LastMI = nullptr;
101 }
102 
104  llvm_unreachable("reverse ARM hazard checking unsupported");
105 }
106 
107 ///////// Bank conflicts handled as hazards //////////////
108 
109 static bool getBaseOffset(const MachineInstr &MI, const MachineOperand *&BaseOp,
110  int64_t &Offset) {
111 
112  uint64_t TSFlags = MI.getDesc().TSFlags;
113  unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
114  unsigned IndexMode =
116 
117  // Address mode tells us what we want to know about operands for T2
118  // instructions (but not size). It tells us size (but not about operands)
119  // for T1 instructions.
120  switch (AddrMode) {
121  default:
122  return false;
124  // t2LDRBT, t2LDRB_POST, t2LDRB_PRE, t2LDRBi8,
125  // t2LDRHT, t2LDRH_POST, t2LDRH_PRE, t2LDRHi8,
126  // t2LDRSBT, t2LDRSB_POST, t2LDRSB_PRE, t2LDRSBi8,
127  // t2LDRSHT, t2LDRSH_POST, t2LDRSH_PRE, t2LDRSHi8,
128  // t2LDRT, t2LDR_POST, t2LDR_PRE, t2LDRi8
129  BaseOp = &MI.getOperand(1);
130  Offset = (IndexMode == ARMII::IndexModePost)
131  ? 0
134  ? MI.getOperand(3).getImm()
135  : MI.getOperand(2).getImm();
136  return true;
138  // t2LDRBi12, t2LDRHi12
139  // t2LDRSBi12, t2LDRSHi12
140  // t2LDRi12
141  BaseOp = &MI.getOperand(1);
142  Offset = MI.getOperand(2).getImm();
143  return true;
145  // t2LDRD_POST, t2LDRD_PRE, t2LDRDi8
146  BaseOp = &MI.getOperand(2);
147  Offset = (IndexMode == ARMII::IndexModePost)
148  ? 0
151  ? MI.getOperand(4).getImm()
152  : MI.getOperand(3).getImm();
153  return true;
154  case ARMII::AddrModeT1_1:
155  // tLDRBi, tLDRBr (watch out!), TLDRSB
156  case ARMII::AddrModeT1_2:
157  // tLDRHi, tLDRHr (watch out!), TLDRSH
158  case ARMII::AddrModeT1_4:
159  // tLDRi, tLDRr (watch out!)
160  BaseOp = &MI.getOperand(1);
161  Offset = MI.getOperand(2).isImm() ? MI.getOperand(2).getImm() : 0;
162  return MI.getOperand(2).isImm();
163  }
164  return false;
165 }
166 
168  const ScheduleDAG *DAG, int64_t CPUBankMask, bool CPUAssumeITCMConflict)
169  : MF(DAG->MF), DL(DAG->MF.getDataLayout()),
170  DataMask(DataBankMask.getNumOccurrences() ? int64_t(DataBankMask)
171  : CPUBankMask),
172  AssumeITCMBankConflict(AssumeITCMConflict.getNumOccurrences()
174  : CPUAssumeITCMConflict) {
175  MaxLookAhead = 1;
176 }
177 
179 ARMBankConflictHazardRecognizer::CheckOffsets(unsigned O0, unsigned O1) {
180  return (((O0 ^ O1) & DataMask) != 0) ? NoHazard : Hazard;
181 }
182 
185  MachineInstr &L0 = *SU->getInstr();
186  if (!L0.mayLoad() || L0.mayStore() || L0.getNumMemOperands() != 1)
187  return NoHazard;
188 
189  auto MO0 = *L0.memoperands().begin();
190  auto BaseVal0 = MO0->getValue();
191  auto BasePseudoVal0 = MO0->getPseudoValue();
192  int64_t Offset0 = 0;
193 
194  if (MO0->getSize() > 4)
195  return NoHazard;
196 
197  bool SPvalid = false;
198  const MachineOperand *SP = nullptr;
199  int64_t SPOffset0 = 0;
200 
201  for (auto L1 : Accesses) {
202  auto MO1 = *L1->memoperands().begin();
203  auto BaseVal1 = MO1->getValue();
204  auto BasePseudoVal1 = MO1->getPseudoValue();
205  int64_t Offset1 = 0;
206 
207  // Pointers to the same object
208  if (BaseVal0 && BaseVal1) {
209  const Value *Ptr0, *Ptr1;
210  Ptr0 = GetPointerBaseWithConstantOffset(BaseVal0, Offset0, DL, true);
211  Ptr1 = GetPointerBaseWithConstantOffset(BaseVal1, Offset1, DL, true);
212  if (Ptr0 == Ptr1 && Ptr0)
213  return CheckOffsets(Offset0, Offset1);
214  }
215 
216  if (BasePseudoVal0 && BasePseudoVal1 &&
217  BasePseudoVal0->kind() == BasePseudoVal1->kind() &&
218  BasePseudoVal0->kind() == PseudoSourceValue::FixedStack) {
219  // Spills/fills
220  auto FS0 = cast<FixedStackPseudoSourceValue>(BasePseudoVal0);
221  auto FS1 = cast<FixedStackPseudoSourceValue>(BasePseudoVal1);
222  Offset0 = MF.getFrameInfo().getObjectOffset(FS0->getFrameIndex());
223  Offset1 = MF.getFrameInfo().getObjectOffset(FS1->getFrameIndex());
224  return CheckOffsets(Offset0, Offset1);
225  }
226 
227  // Constant pools (likely in ITCM)
228  if (BasePseudoVal0 && BasePseudoVal1 &&
229  BasePseudoVal0->kind() == BasePseudoVal1->kind() &&
230  BasePseudoVal0->isConstantPool() && AssumeITCMBankConflict)
231  return Hazard;
232 
233  // Is this a stack pointer-relative access? We could in general try to
234  // use "is this the same register and is it unchanged?", but the
235  // memory operand tracking is highly likely to have already found that.
236  // What we're after here is bank conflicts between different objects in
237  // the stack frame.
238  if (!SPvalid) { // set up SP
239  if (!getBaseOffset(L0, SP, SPOffset0) || SP->getReg().id() != ARM::SP)
240  SP = nullptr;
241  SPvalid = true;
242  }
243  if (SP) {
244  int64_t SPOffset1;
245  const MachineOperand *SP1;
246  if (getBaseOffset(*L1, SP1, SPOffset1) && SP1->getReg().id() == ARM::SP)
247  return CheckOffsets(SPOffset0, SPOffset1);
248  }
249  }
250 
251  return NoHazard;
252 }
253 
254 void ARMBankConflictHazardRecognizer::Reset() { Accesses.clear(); }
255 
257  MachineInstr &MI = *SU->getInstr();
258  if (!MI.mayLoad() || MI.mayStore() || MI.getNumMemOperands() != 1)
259  return;
260 
261  auto MO = *MI.memoperands().begin();
262  uint64_t Size1 = MO->getSize();
263  if (Size1 > 4)
264  return;
265  Accesses.push_back(&MI);
266 }
267 
269 
ARMSubtarget.h
llvm::MCInstrDesc::getOpcode
unsigned getOpcode() const
Return the opcode number for this descriptor.
Definition: MCInstrDesc.h:223
ScheduleDAG.h
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:108
MachineInstr.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::ARMHazardRecognizerFPMLx::getHazardType
HazardType getHazardType(SUnit *SU, int Stalls) override
getHazardType - Return the hazard type of emitting this node.
Definition: ARMHazardRecognizer.cpp:44
llvm::MachineInstr::mayLoadOrStore
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
Definition: MachineInstr.h:1079
llvm::ARMHazardRecognizerFPMLx::AdvanceCycle
void AdvanceCycle() override
AdvanceCycle - This callback is invoked whenever the next top-down instruction to be scheduled cannot...
Definition: ARMHazardRecognizer.cpp:97
llvm::TargetSubtargetInfo::getInstrInfo
virtual const TargetInstrInfo * getInstrInfo() const
Definition: TargetSubtargetInfo.h:93
llvm::Register::id
unsigned id() const
Definition: Register.h:111
llvm::ARMII::AddrModeT2_i8s4
@ AddrModeT2_i8s4
Definition: ARMBaseInfo.h:203
llvm::ScheduleHazardRecognizer::MaxLookAhead
unsigned MaxLookAhead
MaxLookAhead - Indicate the number of cycles in the scoreboard state.
Definition: ScheduleHazardRecognizer.h:31
AssumeITCMConflict
static cl::opt< bool > AssumeITCMConflict("arm-assume-itcm-bankconflict", cl::init(false), cl::Hidden)
llvm::MachineInstr::mayLoad
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
Definition: MachineInstr.h:1056
llvm::ARMII::DomainGeneral
@ DomainGeneral
Definition: ARMBaseInfo.h:427
ValueTracking.h
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:140
llvm::TargetRegisterInfo
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Definition: TargetRegisterInfo.h:237
llvm::ARMHazardRecognizerFPMLx::RecedeCycle
void RecedeCycle() override
RecedeCycle - This callback is invoked whenever the next bottom-up instruction to be scheduled cannot...
Definition: ARMHazardRecognizer.cpp:103
DataBankMask
static cl::opt< int > DataBankMask("arm-data-bank-mask", cl::init(-1), cl::Hidden)
llvm::MachineInstr::getDesc
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:513
llvm::ARMII::AddrModeT1_4
@ AddrModeT1_4
Definition: ARMBaseInfo.h:195
llvm::ARMBankConflictHazardRecognizer::Reset
void Reset() override
Reset - This callback is invoked when a new block of instructions is about to be schedule.
Definition: ARMHazardRecognizer.cpp:254
llvm::ScheduleHazardRecognizer::Hazard
@ Hazard
Definition: ScheduleHazardRecognizer.h:39
TRI
unsigned const TargetRegisterInfo * TRI
Definition: MachineSink.cpp:1628
llvm::ARMII::IndexMode
IndexMode
ARM Index Modes.
Definition: ARMBaseInfo.h:177
llvm::ARMHazardRecognizerFPMLx::Reset
void Reset() override
Reset - This callback is invoked when a new block of instructions is about to be schedule.
Definition: ARMHazardRecognizer.cpp:84
CommandLine.h
llvm::MCInstrDesc::TSFlags
uint64_t TSFlags
Definition: MCInstrDesc.h:205
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:526
Domain
Domain
Definition: CorrelatedValuePropagation.cpp:710
llvm::ARMBankConflictHazardRecognizer::RecedeCycle
void RecedeCycle() override
RecedeCycle - This callback is invoked whenever the next bottom-up instruction to be scheduled cannot...
Definition: ARMHazardRecognizer.cpp:270
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:125
llvm::MCInstrDesc
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:197
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:48
llvm::PseudoSourceValue::FixedStack
@ FixedStack
Definition: PseudoSourceValue.h:42
llvm::MachineFrameInfo::getObjectOffset
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
Definition: MachineFrameInfo.h:518
TSFlags
uint64_t TSFlags
Definition: RISCVInsertVSETVLI.cpp:775
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:656
llvm::cl::opt
Definition: CommandLine.h:1400
llvm::ARMII::AddrModeMask
@ AddrModeMask
Definition: ARMBaseInfo.h:303
llvm::ScheduleHazardRecognizer::HazardType
HazardType
Definition: ScheduleHazardRecognizer.h:37
ARMBaseRegisterInfo.h
llvm::ARMII::IndexModeMask
@ IndexModeMask
Definition: ARMBaseInfo.h:309
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
llvm::MachineInstr::getNumMemOperands
unsigned getNumMemOperands() const
Return the number of memory operands.
Definition: MachineInstr.h:749
uint64_t
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::SUnit::getInstr
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
Definition: ScheduleDAG.h:373
llvm::ARMBaseInstrInfo
Definition: ARMBaseInstrInfo.h:37
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:440
llvm::ARMISD::VMOVRRD
@ VMOVRRD
Definition: ARMISelLowering.h:114
MachineFunctionPass.h
llvm::ARMII::IndexModeUpd
@ IndexModeUpd
Definition: ARMBaseInfo.h:181
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineFunction::getFrameInfo
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Definition: MachineFunction.h:672
llvm::ARMBankConflictHazardRecognizer::EmitInstruction
void EmitInstruction(SUnit *SU) override
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
Definition: ARMHazardRecognizer.cpp:256
llvm::ARMII::AddrModeT1_1
@ AddrModeT1_1
Definition: ARMBaseInfo.h:193
ARMBaseInstrInfo.h
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:359
llvm::MachineFunction
Definition: MachineFunction.h:257
llvm::ARMII::IndexModeShift
@ IndexModeShift
Definition: ARMBaseInfo.h:308
llvm::ARMHazardRecognizerFPMLx::EmitInstruction
void EmitInstruction(SUnit *SU) override
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
Definition: ARMHazardRecognizer.cpp:89
getBaseOffset
static bool getBaseOffset(const MachineInstr &MI, const MachineOperand *&BaseOp, int64_t &Offset)
Definition: ARMHazardRecognizer.cpp:109
llvm::ScheduleDAG
Definition: ScheduleDAG.h:554
llvm::ARMII::DomainVFP
@ DomainVFP
Definition: ARMBaseInfo.h:428
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:516
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::ARMBankConflictHazardRecognizer::ARMBankConflictHazardRecognizer
ARMBankConflictHazardRecognizer(const ScheduleDAG *DAG, int64_t DDM, bool ABC)
Definition: ARMHazardRecognizer.cpp:167
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
AddrMode
AddrMode
Definition: MSP430Disassembler.cpp:142
llvm::MachineInstr::getParent
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:313
ARMHazardRecognizer.h
llvm::ScheduleHazardRecognizer::NoHazard
@ NoHazard
Definition: ScheduleHazardRecognizer.h:38
MachineFrameInfo.h
llvm::MachineInstr::mayStore
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
Definition: MachineInstr.h:1069
llvm::ARMII::DomainNEON
@ DomainNEON
Definition: ARMBaseInfo.h:429
hasRAWHazard
static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, const TargetRegisterInfo &TRI)
Definition: ARMHazardRecognizer.cpp:28
llvm::ARMII::AddrModeT2_i12
@ AddrModeT2_i12
Definition: ARMBaseInfo.h:197
llvm::ARMBankConflictHazardRecognizer::AdvanceCycle
void AdvanceCycle() override
AdvanceCycle - This callback is invoked whenever the next top-down instruction to be scheduled cannot...
Definition: ARMHazardRecognizer.cpp:268
llvm::ARMII::AddrModeT2_i8
@ AddrModeT2_i8
Definition: ARMBaseInfo.h:198
llvm::ARMII::AddrModeT1_2
@ AddrModeT1_2
Definition: ARMBaseInfo.h:194
llvm::GetPointerBaseWithConstantOffset
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
Definition: ValueTracking.h:272
llvm::ARMII::IndexModePre
@ IndexModePre
Definition: ARMBaseInfo.h:179
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:305
DefMI
MachineInstrBuilder MachineInstrBuilder & DefMI
Definition: AArch64ExpandPseudoInsts.cpp:106
llvm::ARMBankConflictHazardRecognizer::getHazardType
HazardType getHazardType(SUnit *SU, int Stalls) override
getHazardType - Return the hazard type of emitting this node.
Definition: ARMHazardRecognizer.cpp:184
llvm::ARMII::IndexModePost
@ IndexModePost
Definition: ARMBaseInfo.h:180
llvm::MachineInstr::memoperands
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:713
llvm::SUnit
Scheduling unit. This is a node in the scheduling DAG.
Definition: ScheduleDAG.h:242
llvm::ARMII::DomainMask
@ DomainMask
Definition: ARMBaseInfo.h:426
llvm::MachineInstrBundleIterator< MachineInstr >
llvm::MachineInstr::isBarrier
bool isBarrier(QueryType Type=AnyInBundle) const
Returns true if the specified instruction stops control flow from executing the instruction immediate...
Definition: MachineInstr.h:887
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
TargetRegisterInfo.h