123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- //===-- RISCVTargetMachine.cpp - Define TargetMachine for RISCV -----------===//
- //
- // 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
- //
- //===----------------------------------------------------------------------===//
- //
- // Implements the info about RISCV target spec.
- //
- //===----------------------------------------------------------------------===//
- #include "RISCVTargetMachine.h"
- #include "MCTargetDesc/RISCVBaseInfo.h"
- #include "RISCV.h"
- #include "RISCVMachineFunctionInfo.h"
- #include "RISCVMacroFusion.h"
- #include "RISCVTargetObjectFile.h"
- #include "RISCVTargetTransformInfo.h"
- #include "TargetInfo/RISCVTargetInfo.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/Analysis/TargetTransformInfo.h"
- #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
- #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
- #include "llvm/CodeGen/GlobalISel/Legalizer.h"
- #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
- #include "llvm/CodeGen/MIRParser/MIParser.h"
- #include "llvm/CodeGen/MIRYamlMapping.h"
- #include "llvm/CodeGen/Passes.h"
- #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
- #include "llvm/CodeGen/TargetPassConfig.h"
- #include "llvm/IR/LegacyPassManager.h"
- #include "llvm/InitializePasses.h"
- #include "llvm/MC/TargetRegistry.h"
- #include "llvm/Support/FormattedStream.h"
- #include "llvm/Target/TargetOptions.h"
- #include "llvm/Transforms/IPO.h"
- #include <optional>
- using namespace llvm;
- static cl::opt<bool> EnableRedundantCopyElimination(
- "riscv-enable-copyelim",
- cl::desc("Enable the redundant copy elimination pass"), cl::init(true),
- cl::Hidden);
- // FIXME: Unify control over GlobalMerge.
- static cl::opt<cl::boolOrDefault>
- EnableGlobalMerge("riscv-enable-global-merge", cl::Hidden,
- cl::desc("Enable the global merge pass"));
- static cl::opt<bool>
- EnableMachineCombiner("riscv-enable-machine-combiner",
- cl::desc("Enable the machine combiner pass"),
- cl::init(true), cl::Hidden);
- static cl::opt<unsigned> RVVVectorBitsMaxOpt(
- "riscv-v-vector-bits-max",
- cl::desc("Assume V extension vector registers are at most this big, "
- "with zero meaning no maximum size is assumed."),
- cl::init(0), cl::Hidden);
- static cl::opt<int> RVVVectorBitsMinOpt(
- "riscv-v-vector-bits-min",
- cl::desc("Assume V extension vector registers are at least this big, "
- "with zero meaning no minimum size is assumed. A value of -1 "
- "means use Zvl*b extension. This is primarily used to enable "
- "autovectorization with fixed width vectors."),
- cl::init(-1), cl::Hidden);
- extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
- RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
- RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
- auto *PR = PassRegistry::getPassRegistry();
- initializeGlobalISel(*PR);
- initializeRISCVMakeCompressibleOptPass(*PR);
- initializeRISCVGatherScatterLoweringPass(*PR);
- initializeRISCVCodeGenPreparePass(*PR);
- initializeRISCVMergeBaseOffsetOptPass(*PR);
- initializeRISCVSExtWRemovalPass(*PR);
- initializeRISCVStripWSuffixPass(*PR);
- initializeRISCVPreRAExpandPseudoPass(*PR);
- initializeRISCVExpandPseudoPass(*PR);
- initializeRISCVInsertVSETVLIPass(*PR);
- initializeRISCVDAGToDAGISelPass(*PR);
- }
- static StringRef computeDataLayout(const Triple &TT) {
- if (TT.isArch64Bit())
- return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
- assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
- return "e-m:e-p:32:32-i64:64-n32-S128";
- }
- static Reloc::Model getEffectiveRelocModel(const Triple &TT,
- std::optional<Reloc::Model> RM) {
- return RM.value_or(Reloc::Static);
- }
- RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
- StringRef CPU, StringRef FS,
- const TargetOptions &Options,
- std::optional<Reloc::Model> RM,
- std::optional<CodeModel::Model> CM,
- CodeGenOpt::Level OL, bool JIT)
- : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
- getEffectiveRelocModel(TT, RM),
- getEffectiveCodeModel(CM, CodeModel::Small), OL),
- TLOF(std::make_unique<RISCVELFTargetObjectFile>()) {
- initAsmInfo();
- // RISC-V supports the MachineOutliner.
- setMachineOutliner(true);
- setSupportsDefaultOutlining(true);
- }
- const RISCVSubtarget *
- RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
- Attribute CPUAttr = F.getFnAttribute("target-cpu");
- Attribute TuneAttr = F.getFnAttribute("tune-cpu");
- Attribute FSAttr = F.getFnAttribute("target-features");
- std::string CPU =
- CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
- std::string TuneCPU =
- TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
- std::string FS =
- FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
- unsigned RVVBitsMin = RVVVectorBitsMinOpt;
- unsigned RVVBitsMax = RVVVectorBitsMaxOpt;
- Attribute VScaleRangeAttr = F.getFnAttribute(Attribute::VScaleRange);
- if (VScaleRangeAttr.isValid()) {
- if (!RVVVectorBitsMinOpt.getNumOccurrences())
- RVVBitsMin = VScaleRangeAttr.getVScaleRangeMin() * RISCV::RVVBitsPerBlock;
- std::optional<unsigned> VScaleMax = VScaleRangeAttr.getVScaleRangeMax();
- if (VScaleMax.has_value() && !RVVVectorBitsMaxOpt.getNumOccurrences())
- RVVBitsMax = *VScaleMax * RISCV::RVVBitsPerBlock;
- }
- if (RVVBitsMin != -1U) {
- // FIXME: Change to >= 32 when VLEN = 32 is supported.
- assert((RVVBitsMin == 0 || (RVVBitsMin >= 64 && RVVBitsMin <= 65536 &&
- isPowerOf2_32(RVVBitsMin))) &&
- "V or Zve* extension requires vector length to be in the range of "
- "64 to 65536 and a power 2!");
- assert((RVVBitsMax >= RVVBitsMin || RVVBitsMax == 0) &&
- "Minimum V extension vector length should not be larger than its "
- "maximum!");
- }
- assert((RVVBitsMax == 0 || (RVVBitsMax >= 64 && RVVBitsMax <= 65536 &&
- isPowerOf2_32(RVVBitsMax))) &&
- "V or Zve* extension requires vector length to be in the range of "
- "64 to 65536 and a power 2!");
- if (RVVBitsMin != -1U) {
- if (RVVBitsMax != 0) {
- RVVBitsMin = std::min(RVVBitsMin, RVVBitsMax);
- RVVBitsMax = std::max(RVVBitsMin, RVVBitsMax);
- }
- RVVBitsMin =
- PowerOf2Floor((RVVBitsMin < 64 || RVVBitsMin > 65536) ? 0 : RVVBitsMin);
- }
- RVVBitsMax =
- PowerOf2Floor((RVVBitsMax < 64 || RVVBitsMax > 65536) ? 0 : RVVBitsMax);
- SmallString<512> Key;
- Key += "RVVMin";
- Key += std::to_string(RVVBitsMin);
- Key += "RVVMax";
- Key += std::to_string(RVVBitsMax);
- Key += CPU;
- Key += TuneCPU;
- Key += FS;
- auto &I = SubtargetMap[Key];
- if (!I) {
- // This needs to be done before we create a new subtarget since any
- // creation will depend on the TM and the code generation flags on the
- // function that reside in TargetOptions.
- resetTargetOptions(F);
- auto ABIName = Options.MCOptions.getABIName();
- if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
- F.getParent()->getModuleFlag("target-abi"))) {
- auto TargetABI = RISCVABI::getTargetABI(ABIName);
- if (TargetABI != RISCVABI::ABI_Unknown &&
- ModuleTargetABI->getString() != ABIName) {
- report_fatal_error("-target-abi option != target-abi module flag");
- }
- ABIName = ModuleTargetABI->getString();
- }
- I = std::make_unique<RISCVSubtarget>(
- TargetTriple, CPU, TuneCPU, FS, ABIName, RVVBitsMin, RVVBitsMax, *this);
- }
- return I.get();
- }
- MachineFunctionInfo *RISCVTargetMachine::createMachineFunctionInfo(
- BumpPtrAllocator &Allocator, const Function &F,
- const TargetSubtargetInfo *STI) const {
- return RISCVMachineFunctionInfo::create<RISCVMachineFunctionInfo>(Allocator,
- F, STI);
- }
- TargetTransformInfo
- RISCVTargetMachine::getTargetTransformInfo(const Function &F) const {
- return TargetTransformInfo(RISCVTTIImpl(this, F));
- }
- // A RISC-V hart has a single byte-addressable address space of 2^XLEN bytes
- // for all memory accesses, so it is reasonable to assume that an
- // implementation has no-op address space casts. If an implementation makes a
- // change to this, they can override it here.
- bool RISCVTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS,
- unsigned DstAS) const {
- return true;
- }
- namespace {
- class RISCVPassConfig : public TargetPassConfig {
- public:
- RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM)
- : TargetPassConfig(TM, PM) {}
- RISCVTargetMachine &getRISCVTargetMachine() const {
- return getTM<RISCVTargetMachine>();
- }
- ScheduleDAGInstrs *
- createMachineScheduler(MachineSchedContext *C) const override {
- const RISCVSubtarget &ST = C->MF->getSubtarget<RISCVSubtarget>();
- if (ST.hasMacroFusion()) {
- ScheduleDAGMILive *DAG = createGenericSchedLive(C);
- DAG->addMutation(createRISCVMacroFusionDAGMutation());
- return DAG;
- }
- return nullptr;
- }
- ScheduleDAGInstrs *
- createPostMachineScheduler(MachineSchedContext *C) const override {
- const RISCVSubtarget &ST = C->MF->getSubtarget<RISCVSubtarget>();
- if (ST.hasMacroFusion()) {
- ScheduleDAGMI *DAG = createGenericSchedPostRA(C);
- DAG->addMutation(createRISCVMacroFusionDAGMutation());
- return DAG;
- }
- return nullptr;
- }
- void addIRPasses() override;
- bool addPreISel() override;
- bool addInstSelector() override;
- bool addIRTranslator() override;
- bool addLegalizeMachineIR() override;
- bool addRegBankSelect() override;
- bool addGlobalInstructionSelect() override;
- void addPreEmitPass() override;
- void addPreEmitPass2() override;
- void addPreSched2() override;
- void addMachineSSAOptimization() override;
- void addPreRegAlloc() override;
- void addPostRegAlloc() override;
- };
- } // namespace
- TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new RISCVPassConfig(*this, PM);
- }
- void RISCVPassConfig::addIRPasses() {
- addPass(createAtomicExpandPass());
- if (getOptLevel() != CodeGenOpt::None)
- addPass(createRISCVGatherScatterLoweringPass());
- if (getOptLevel() != CodeGenOpt::None)
- addPass(createRISCVCodeGenPreparePass());
- TargetPassConfig::addIRPasses();
- }
- bool RISCVPassConfig::addPreISel() {
- if (TM->getOptLevel() != CodeGenOpt::None) {
- // Add a barrier before instruction selection so that we will not get
- // deleted block address after enabling default outlining. See D99707 for
- // more details.
- addPass(createBarrierNoopPass());
- }
- if (EnableGlobalMerge == cl::BOU_TRUE) {
- addPass(createGlobalMergePass(TM, /* MaxOffset */ 2047,
- /* OnlyOptimizeForSize */ false,
- /* MergeExternalByDefault */ true));
- }
- return false;
- }
- bool RISCVPassConfig::addInstSelector() {
- addPass(createRISCVISelDag(getRISCVTargetMachine(), getOptLevel()));
- return false;
- }
- bool RISCVPassConfig::addIRTranslator() {
- addPass(new IRTranslator(getOptLevel()));
- return false;
- }
- bool RISCVPassConfig::addLegalizeMachineIR() {
- addPass(new Legalizer());
- return false;
- }
- bool RISCVPassConfig::addRegBankSelect() {
- addPass(new RegBankSelect());
- return false;
- }
- bool RISCVPassConfig::addGlobalInstructionSelect() {
- addPass(new InstructionSelect(getOptLevel()));
- return false;
- }
- void RISCVPassConfig::addPreSched2() {}
- void RISCVPassConfig::addPreEmitPass() {
- addPass(&BranchRelaxationPassID);
- addPass(createRISCVMakeCompressibleOptPass());
- }
- void RISCVPassConfig::addPreEmitPass2() {
- addPass(createRISCVExpandPseudoPass());
- // Schedule the expansion of AMOs at the last possible moment, avoiding the
- // possibility for other passes to break the requirements for forward
- // progress in the LR/SC block.
- addPass(createRISCVExpandAtomicPseudoPass());
- }
- void RISCVPassConfig::addMachineSSAOptimization() {
- TargetPassConfig::addMachineSSAOptimization();
- if (EnableMachineCombiner)
- addPass(&MachineCombinerID);
- if (TM->getTargetTriple().getArch() == Triple::riscv64) {
- addPass(createRISCVSExtWRemovalPass());
- addPass(createRISCVStripWSuffixPass());
- }
- }
- void RISCVPassConfig::addPreRegAlloc() {
- addPass(createRISCVPreRAExpandPseudoPass());
- if (TM->getOptLevel() != CodeGenOpt::None)
- addPass(createRISCVMergeBaseOffsetOptPass());
- addPass(createRISCVInsertVSETVLIPass());
- }
- void RISCVPassConfig::addPostRegAlloc() {
- if (TM->getOptLevel() != CodeGenOpt::None && EnableRedundantCopyElimination)
- addPass(createRISCVRedundantCopyEliminationPass());
- }
- yaml::MachineFunctionInfo *
- RISCVTargetMachine::createDefaultFuncInfoYAML() const {
- return new yaml::RISCVMachineFunctionInfo();
- }
- yaml::MachineFunctionInfo *
- RISCVTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {
- const auto *MFI = MF.getInfo<RISCVMachineFunctionInfo>();
- return new yaml::RISCVMachineFunctionInfo(*MFI);
- }
- bool RISCVTargetMachine::parseMachineFunctionInfo(
- const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
- SMDiagnostic &Error, SMRange &SourceRange) const {
- const auto &YamlMFI =
- static_cast<const yaml::RISCVMachineFunctionInfo &>(MFI);
- PFS.MF.getInfo<RISCVMachineFunctionInfo>()->initializeBaseYamlFields(YamlMFI);
- return false;
- }
|