diff --git a/llvm/include/llvm/CodeGen/MultiHazardRecognizer.h b/llvm/include/llvm/CodeGen/MultiHazardRecognizer.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/CodeGen/MultiHazardRecognizer.h @@ -0,0 +1,47 @@ +//=- llvm/CodeGen/MultiHazardRecognizer.h - Scheduling Support ----*- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the MultiHazardRecognizer class, which is a wrapper +// for a set of ScheduleHazardRecognizer instances +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" + +namespace llvm { + +class MachineInstr; +class SUnit; + +class MultiHazardRecognizer : public ScheduleHazardRecognizer { + SmallVector, 4> Recognizers; + +public: + MultiHazardRecognizer() = default; + void AddHazardRecognizer(std::unique_ptr &&); + + bool atIssueLimit() const override; + HazardType getHazardType(SUnit *m, int Stalls = 0) override; + void Reset() override; + void EmitInstruction(SUnit *) override; + void EmitInstruction(MachineInstr *) override; + unsigned PreEmitNoops(SUnit *) override; + unsigned PreEmitNoops(MachineInstr *) override; + bool ShouldPreferAnother(SUnit *) override; + void AdvanceCycle() override; + void RecedeCycle() override; + void EmitNoop() override; +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_MULTIHAZARDRECOGNIZER_H diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -106,6 +106,7 @@ MachineTraceMetrics.cpp MachineVerifier.cpp ModuloSchedule.cpp + MultiHazardRecognizer.cpp PatchableFunction.cpp MBFIWrapper.cpp MIRPrinter.cpp diff --git a/llvm/lib/CodeGen/MultiHazardRecognizer.cpp b/llvm/lib/CodeGen/MultiHazardRecognizer.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/CodeGen/MultiHazardRecognizer.cpp @@ -0,0 +1,91 @@ +//===- MultiHazardRecognizer.cpp - Scheduler Support ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the MultiHazardRecognizer class, which is a wrapper +// for a set of ScheduleHazardRecognizer instances +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MultiHazardRecognizer.h" +#include +#include +#include + +using namespace llvm; + +void MultiHazardRecognizer::AddHazardRecognizer( + std::unique_ptr &&R) { + MaxLookAhead = std::max(MaxLookAhead, R->getMaxLookAhead()); + Recognizers.push_back(std::move(R)); +} + +bool MultiHazardRecognizer::atIssueLimit() const { + return std::any_of(Recognizers.begin(), Recognizers.end(), + std::mem_fn(&ScheduleHazardRecognizer::atIssueLimit)); +} + +ScheduleHazardRecognizer::HazardType +MultiHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { + for (auto &R : Recognizers) { + auto res = R->getHazardType(SU, Stalls); + if (res != NoHazard) + return res; + } + return NoHazard; +} + +void MultiHazardRecognizer::Reset() { + for (auto &R : Recognizers) + R->Reset(); +} + +void MultiHazardRecognizer::EmitInstruction(SUnit *SU) { + for (auto &R : Recognizers) + R->EmitInstruction(SU); +} + +void MultiHazardRecognizer::EmitInstruction(MachineInstr *MI) { + for (auto &R : Recognizers) + R->EmitInstruction(MI); +} + +unsigned MultiHazardRecognizer::PreEmitNoops(SUnit *SU) { + auto MN = [=](unsigned a, std::unique_ptr &R) { + return std::max(a, R->PreEmitNoops(SU)); + }; + return std::accumulate(Recognizers.begin(), Recognizers.end(), 0u, MN); +} + +unsigned MultiHazardRecognizer::PreEmitNoops(MachineInstr *MI) { + auto MN = [=](unsigned a, std::unique_ptr &R) { + return std::max(a, R->PreEmitNoops(MI)); + }; + return std::accumulate(Recognizers.begin(), Recognizers.end(), 0u, MN); +} + +bool MultiHazardRecognizer::ShouldPreferAnother(SUnit *SU) { + auto SPA = [=](std::unique_ptr &R) { + return R->ShouldPreferAnother(SU); + }; + return std::any_of(Recognizers.begin(), Recognizers.end(), SPA); +} + +void MultiHazardRecognizer::AdvanceCycle() { + for (auto &R : Recognizers) + R->AdvanceCycle(); +} + +void MultiHazardRecognizer::RecedeCycle() { + for (auto &R : Recognizers) + R->RecedeCycle(); +} + +void MultiHazardRecognizer::EmitNoop() { + for (auto &R : Recognizers) + R->EmitNoop(); +} diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -35,6 +35,8 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineScheduler.h" +#include "llvm/CodeGen/MultiHazardRecognizer.h" #include "llvm/CodeGen/ScoreboardHazardRecognizer.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetInstrInfo.h" @@ -134,9 +136,15 @@ ScheduleHazardRecognizer *ARMBaseInstrInfo:: CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const { + MultiHazardRecognizer *MHR = new MultiHazardRecognizer(); + if (Subtarget.isThumb2() || Subtarget.hasVFP2Base()) - return new ARMHazardRecognizer(II, DAG); - return TargetInstrInfo::CreateTargetPostRAHazardRecognizer(II, DAG); + MHR->AddHazardRecognizer(std::make_unique()); + + auto BHR = TargetInstrInfo::CreateTargetPostRAHazardRecognizer(II, DAG); + if (BHR) + MHR->AddHazardRecognizer(std::unique_ptr(BHR)); + return MHR; } MachineInstr *ARMBaseInstrInfo::convertToThreeAddress( diff --git a/llvm/lib/Target/ARM/ARMHazardRecognizer.h b/llvm/lib/Target/ARM/ARMHazardRecognizer.h --- a/llvm/lib/Target/ARM/ARMHazardRecognizer.h +++ b/llvm/lib/Target/ARM/ARMHazardRecognizer.h @@ -13,27 +13,17 @@ #ifndef LLVM_LIB_TARGET_ARM_ARMHAZARDRECOGNIZER_H #define LLVM_LIB_TARGET_ARM_ARMHAZARDRECOGNIZER_H -#include "llvm/CodeGen/ScoreboardHazardRecognizer.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" namespace llvm { -class ARMBaseInstrInfo; -class ARMBaseRegisterInfo; -class ARMSubtarget; -class MachineInstr; - -/// ARMHazardRecognizer handles special constraints that are not expressed in -/// the scheduling itinerary. This is only used during postRA scheduling. The -/// ARM preRA scheduler uses an unspecialized instance of the -/// ScoreboardHazardRecognizer. -class ARMHazardRecognizer : public ScoreboardHazardRecognizer { +// Hazards related to FP MLx instructions +class ARMHazardRecognizerFPMLx : public ScheduleHazardRecognizer { MachineInstr *LastMI = nullptr; unsigned FpMLxStalls = 0; public: - ARMHazardRecognizer(const InstrItineraryData *ItinData, - const ScheduleDAG *DAG) - : ScoreboardHazardRecognizer(ItinData, DAG, "post-RA-sched") {} + ARMHazardRecognizerFPMLx() : ScheduleHazardRecognizer() { MaxLookAhead = 1; } HazardType getHazardType(SUnit *SU, int Stalls) override; void Reset() override; diff --git a/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp b/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp --- a/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp +++ b/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp @@ -31,7 +31,7 @@ } ScheduleHazardRecognizer::HazardType -ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { +ARMHazardRecognizerFPMLx::getHazardType(SUnit *SU, int Stalls) { assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead"); MachineInstr *MI = SU->getInstr(); @@ -68,33 +68,28 @@ } } } - - return ScoreboardHazardRecognizer::getHazardType(SU, Stalls); + return NoHazard; } -void ARMHazardRecognizer::Reset() { +void ARMHazardRecognizerFPMLx::Reset() { LastMI = nullptr; FpMLxStalls = 0; - ScoreboardHazardRecognizer::Reset(); } -void ARMHazardRecognizer::EmitInstruction(SUnit *SU) { +void ARMHazardRecognizerFPMLx::EmitInstruction(SUnit *SU) { MachineInstr *MI = SU->getInstr(); if (!MI->isDebugInstr()) { LastMI = MI; FpMLxStalls = 0; } - - ScoreboardHazardRecognizer::EmitInstruction(SU); } -void ARMHazardRecognizer::AdvanceCycle() { +void ARMHazardRecognizerFPMLx::AdvanceCycle() { if (FpMLxStalls && --FpMLxStalls == 0) // Stalled for 4 cycles but still can't schedule any other instructions. LastMI = nullptr; - ScoreboardHazardRecognizer::AdvanceCycle(); } -void ARMHazardRecognizer::RecedeCycle() { +void ARMHazardRecognizerFPMLx::RecedeCycle() { llvm_unreachable("reverse ARM hazard checking unsupported"); }