[llvm] [llvm][ARM] Add a cortex-m4f alignment hazard recognizer (PR #126991)

Oliver Stannard via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 13 04:37:34 PST 2025


================
@@ -266,3 +271,159 @@ void ARMBankConflictHazardRecognizer::EmitInstruction(SUnit *SU) {
 void ARMBankConflictHazardRecognizer::AdvanceCycle() { Accesses.clear(); }
 
 void ARMBankConflictHazardRecognizer::RecedeCycle() { Accesses.clear(); }
+
+#define DEBUG_TYPE "cortex-m4-alignment-hazard-rec"
+
+STATISTIC(NumNoops, "Number of noops inserted");
+
+static cl::opt<bool> LoopsOnly(DEBUG_TYPE "-loops-only", cl::Hidden,
+                               cl::init(true),
+                               cl::desc("Emit nops only in loops"));
+
+static cl::opt<bool>
+    InnermostLoopsOnly(DEBUG_TYPE "-innermost-loops-only", cl::Hidden,
+                       cl::init(true),
+                       cl::desc("Emit noops only in innermost loops"));
+
+void ARMCortexM4AlignmentHazardRecognizer::Reset() { Offset = 0; }
+
+ARMCortexM4AlignmentHazardRecognizer::ARMCortexM4AlignmentHazardRecognizer(
+    const MCSubtargetInfo &STI)
+    : STI(STI), MBB(nullptr), MF(nullptr), Offset(0), Advanced(false),
+      EmittingNoop(false) {
+  MaxLookAhead = 1;
+}
+
+void ARMCortexM4AlignmentHazardRecognizer::EmitInstruction(SUnit *SU) {
+  if (!SU->isInstr())
+    return;
+
+  MachineInstr *MI = SU->getInstr();
+  assert(MI);
+  return EmitInstruction(MI);
+}
+
+void ARMCortexM4AlignmentHazardRecognizer::EmitInstruction(MachineInstr *MI) {
+  if (MI->isDebugInstr())
+    return;
+
+  unsigned Size = MI->getDesc().getSize();
+  Offset += Size;
+
+  // If the previous instruction had a hazard, then we're inserting a nop. Mark
+  // it with an AsmPrinter comment.
+  if (EmittingNoop)
+    if (MachineInstr *Prev = MI->getPrevNode())
+      Prev->setAsmPrinterFlag(ARM::M4F_ALIGNMENT_HAZARD);
+
+  EmittingNoop = false;
+}
+
+ScheduleHazardRecognizer::HazardType
+ARMCortexM4AlignmentHazardRecognizer::getHazardType(SUnit *SU,
+                                                    int /*Ignored*/) {
+  if (!SU->isInstr())
+    return HazardType::NoHazard;
+
+  MachineInstr *MI = SU->getInstr();
+  assert(MI);
+  return getHazardTypeAssumingOffset(MI, Offset);
+}
+
+ScheduleHazardRecognizer::HazardType
+ARMCortexM4AlignmentHazardRecognizer::getHazardTypeAssumingOffset(
+    MachineInstr *MI, size_t AssumedOffset) {
+  if (Advanced) {
+    Advanced = false;
+    return HazardType::NoHazard;
+  }
+
+  if (AssumedOffset % 4 == 0)
+    return HazardType::NoHazard;
+
+  const MCSchedModel &SCModel = STI.getSchedModel();
+  const MachineFunction *MF = MI->getParent()->getParent();
+  const ARMBaseInstrInfo &TII =
+      *static_cast<const ARMBaseInstrInfo *>(MF->getSubtarget().getInstrInfo());
+  int Latency = SCModel.computeInstrLatency<MCSubtargetInfo, MCInstrInfo,
+                                            InstrItineraryData, MachineInstr>(
+      STI, TII, *MI);
+  if (!Latency)
+    return HazardType::NoHazard;
+
+  const MCInstrDesc &MCID = MI->getDesc();
+  unsigned Domain = MCID.TSFlags & ARMII::DomainMask;
+
+  bool SingleCycleFP =
+      Latency == 1 && (Domain & (ARMII::DomainNEON | ARMII::DomainVFP));
+  if (SingleCycleFP)
----------------
ostannard wrote:

The document you linked says that this happens for long sequences of misaligned instructions, would it be possible to only emit the NOP if more than some number of consecutive instructions are misaligned? I've not looked at hazard recognisers before, so maybe this isn't possible.

https://github.com/llvm/llvm-project/pull/126991


More information about the llvm-commits mailing list