1b2e5472dSAlex Bradbury //===-- RISCVTargetMachine.cpp - Define TargetMachine for RISCV -----------===//
2b2e5472dSAlex Bradbury //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b2e5472dSAlex Bradbury //
7b2e5472dSAlex Bradbury //===----------------------------------------------------------------------===//
8b2e5472dSAlex Bradbury //
9b2e5472dSAlex Bradbury // Implements the info about RISCV target spec.
10b2e5472dSAlex Bradbury //
11b2e5472dSAlex Bradbury //===----------------------------------------------------------------------===//
12b2e5472dSAlex Bradbury 
13b2e5472dSAlex Bradbury #include "RISCVTargetMachine.h"
14387d3c24SCraig Topper #include "MCTargetDesc/RISCVBaseInfo.h"
1596c8bc79SSam Elliott #include "RISCV.h"
16690085c9SKito Cheng #include "RISCVMachineFunctionInfo.h"
174045b62dSCraig Topper #include "RISCVMacroFusion.h"
1898bc25a0SMandeep Singh Grang #include "RISCVTargetObjectFile.h"
1996c8bc79SSam Elliott #include "RISCVTargetTransformInfo.h"
2051fc56d6SRichard Trieu #include "TargetInfo/RISCVTargetInfo.h"
21b2e5472dSAlex Bradbury #include "llvm/ADT/STLExtras.h"
2296c8bc79SSam Elliott #include "llvm/Analysis/TargetTransformInfo.h"
23a16bd4f9SDaniel Sanders #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
24a16bd4f9SDaniel Sanders #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
25a16bd4f9SDaniel Sanders #include "llvm/CodeGen/GlobalISel/Legalizer.h"
26a16bd4f9SDaniel Sanders #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
27690085c9SKito Cheng #include "llvm/CodeGen/MIRParser/MIParser.h"
28690085c9SKito Cheng #include "llvm/CodeGen/MIRYamlMapping.h"
296bda14b3SChandler Carruth #include "llvm/CodeGen/Passes.h"
30b2e5472dSAlex Bradbury #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
31b2e5472dSAlex Bradbury #include "llvm/CodeGen/TargetPassConfig.h"
32b2e5472dSAlex Bradbury #include "llvm/IR/LegacyPassManager.h"
3305da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
3489b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
35b2e5472dSAlex Bradbury #include "llvm/Support/FormattedStream.h"
36b2e5472dSAlex Bradbury #include "llvm/Target/TargetOptions.h"
374ff5e818Swangpc #include "llvm/Transforms/IPO.h"
38b2e5472dSAlex Bradbury using namespace llvm;
39b2e5472dSAlex Bradbury 
401d8bbe3dSCraig Topper static cl::opt<bool> EnableRedundantCopyElimination(
411d8bbe3dSCraig Topper     "riscv-enable-copyelim",
421d8bbe3dSCraig Topper     cl::desc("Enable the redundant copy elimination pass"), cl::init(true),
431d8bbe3dSCraig Topper     cl::Hidden);
441d8bbe3dSCraig Topper 
LLVMInitializeRISCVTarget()450dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
46b2e5472dSAlex Bradbury   RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
47b2e5472dSAlex Bradbury   RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
487948cd11SFraser Cormack   auto *PR = PassRegistry::getPassRegistry();
49a16bd4f9SDaniel Sanders   initializeGlobalISel(*PR);
5029a5a7c6SLewis Revill   initializeRISCVMakeCompressibleOptPass(*PR);
51d85e347aSCraig Topper   initializeRISCVGatherScatterLoweringPass(*PR);
521a8468baSCraig Topper   initializeRISCVCodeGenPreparePass(*PR);
538b403243SCraig Topper   initializeRISCVMergeBaseOffsetOptPass(*PR);
5456ca11e3SCraig Topper   initializeRISCVSExtWRemovalPass(*PR);
5521aea51eSAlex Bradbury   initializeRISCVExpandPseudoPass(*PR);
56b510e4cfSCraig Topper   initializeRISCVInsertVSETVLIPass(*PR);
57b2e5472dSAlex Bradbury }
58b2e5472dSAlex Bradbury 
computeDataLayout(const Triple & TT)596aae2161SAlex Bradbury static StringRef computeDataLayout(const Triple &TT) {
607948cd11SFraser Cormack   if (TT.isArch64Bit())
6147fbc591SMandeep Singh Grang     return "e-m:e-p:64:64-i64:64-i128:128-n64-S128";
62b2e5472dSAlex Bradbury   assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
63e4f731b8SAlex Bradbury   return "e-m:e-p:32:32-i64:64-n32-S128";
64b2e5472dSAlex Bradbury }
65b2e5472dSAlex Bradbury 
getEffectiveRelocModel(const Triple & TT,Optional<Reloc::Model> RM)66b2e5472dSAlex Bradbury static Reloc::Model getEffectiveRelocModel(const Triple &TT,
67b2e5472dSAlex Bradbury                                            Optional<Reloc::Model> RM) {
68ad7ce1e7SKazu Hirata   return RM.value_or(Reloc::Static);
69b2e5472dSAlex Bradbury }
70b2e5472dSAlex Bradbury 
RISCVTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,Optional<Reloc::Model> RM,Optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)71b2e5472dSAlex Bradbury RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
72b2e5472dSAlex Bradbury                                        StringRef CPU, StringRef FS,
73b2e5472dSAlex Bradbury                                        const TargetOptions &Options,
74b2e5472dSAlex Bradbury                                        Optional<Reloc::Model> RM,
7579e238afSRafael Espindola                                        Optional<CodeModel::Model> CM,
7679e238afSRafael Espindola                                        CodeGenOpt::Level OL, bool JIT)
77bb8507e6SMatthias Braun     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
7879e238afSRafael Espindola                         getEffectiveRelocModel(TT, RM),
79ca29c271SDavid Green                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
802c8e22d2SZakk Chen       TLOF(std::make_unique<RISCVELFTargetObjectFile>()) {
81e4f731b8SAlex Bradbury   initAsmInfo();
82a116f28aSlewis-revill 
83a116f28aSlewis-revill   // RISC-V supports the MachineOutliner.
84a116f28aSlewis-revill   setMachineOutliner(true);
854ff5e818Swangpc   setSupportsDefaultOutlining(true);
86e4f731b8SAlex Bradbury }
87b2e5472dSAlex Bradbury 
882c8e22d2SZakk Chen const RISCVSubtarget *
getSubtargetImpl(const Function & F) const892c8e22d2SZakk Chen RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
902c8e22d2SZakk Chen   Attribute CPUAttr = F.getFnAttribute("target-cpu");
91cfa7094eSKito Cheng   Attribute TuneAttr = F.getFnAttribute("tune-cpu");
922c8e22d2SZakk Chen   Attribute FSAttr = F.getFnAttribute("target-features");
932c8e22d2SZakk Chen 
94aab90384SCraig Topper   std::string CPU =
95aab90384SCraig Topper       CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
96cfa7094eSKito Cheng   std::string TuneCPU =
97cfa7094eSKito Cheng       TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
98aab90384SCraig Topper   std::string FS =
99aab90384SCraig Topper       FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
100cfa7094eSKito Cheng   std::string Key = CPU + TuneCPU + FS;
1012c8e22d2SZakk Chen   auto &I = SubtargetMap[Key];
1022c8e22d2SZakk Chen   if (!I) {
1032c8e22d2SZakk Chen     // This needs to be done before we create a new subtarget since any
1042c8e22d2SZakk Chen     // creation will depend on the TM and the code generation flags on the
1052c8e22d2SZakk Chen     // function that reside in TargetOptions.
1062c8e22d2SZakk Chen     resetTargetOptions(F);
1071256d680SZakk Chen     auto ABIName = Options.MCOptions.getABIName();
1081256d680SZakk Chen     if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
1091256d680SZakk Chen             F.getParent()->getModuleFlag("target-abi"))) {
1101256d680SZakk Chen       auto TargetABI = RISCVABI::getTargetABI(ABIName);
1111256d680SZakk Chen       if (TargetABI != RISCVABI::ABI_Unknown &&
1121256d680SZakk Chen           ModuleTargetABI->getString() != ABIName) {
1131256d680SZakk Chen         report_fatal_error("-target-abi option != target-abi module flag");
1141256d680SZakk Chen       }
1151256d680SZakk Chen       ABIName = ModuleTargetABI->getString();
1161256d680SZakk Chen     }
117cfa7094eSKito Cheng     I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, TuneCPU, FS, ABIName, *this);
1182c8e22d2SZakk Chen   }
1192c8e22d2SZakk Chen   return I.get();
1202c8e22d2SZakk Chen }
1212c8e22d2SZakk Chen 
12296c8bc79SSam Elliott TargetTransformInfo
getTargetTransformInfo(const Function & F) const123c4b1a63aSJameson Nash RISCVTargetMachine::getTargetTransformInfo(const Function &F) const {
12496c8bc79SSam Elliott   return TargetTransformInfo(RISCVTTIImpl(this, F));
12596c8bc79SSam Elliott }
12696c8bc79SSam Elliott 
127d4ed253dSFraser Cormack // A RISC-V hart has a single byte-addressable address space of 2^XLEN bytes
128d4ed253dSFraser Cormack // for all memory accesses, so it is reasonable to assume that an
129d4ed253dSFraser Cormack // implementation has no-op address space casts. If an implementation makes a
130d4ed253dSFraser Cormack // change to this, they can override it here.
isNoopAddrSpaceCast(unsigned SrcAS,unsigned DstAS) const131d4ed253dSFraser Cormack bool RISCVTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS,
132d4ed253dSFraser Cormack                                              unsigned DstAS) const {
133d4ed253dSFraser Cormack   return true;
134d4ed253dSFraser Cormack }
135d4ed253dSFraser Cormack 
1368971842fSAlex Bradbury namespace {
1378971842fSAlex Bradbury class RISCVPassConfig : public TargetPassConfig {
1388971842fSAlex Bradbury public:
RISCVPassConfig(RISCVTargetMachine & TM,PassManagerBase & PM)1398971842fSAlex Bradbury   RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM)
1408971842fSAlex Bradbury       : TargetPassConfig(TM, PM) {}
1418971842fSAlex Bradbury 
getRISCVTargetMachine() const1428971842fSAlex Bradbury   RISCVTargetMachine &getRISCVTargetMachine() const {
1438971842fSAlex Bradbury     return getTM<RISCVTargetMachine>();
1448971842fSAlex Bradbury   }
1458971842fSAlex Bradbury 
1464045b62dSCraig Topper   ScheduleDAGInstrs *
createMachineScheduler(MachineSchedContext * C) const1474045b62dSCraig Topper   createMachineScheduler(MachineSchedContext *C) const override {
1484045b62dSCraig Topper     const RISCVSubtarget &ST = C->MF->getSubtarget<RISCVSubtarget>();
1494045b62dSCraig Topper     if (ST.hasMacroFusion()) {
1504045b62dSCraig Topper       ScheduleDAGMILive *DAG = createGenericSchedLive(C);
1514045b62dSCraig Topper       DAG->addMutation(createRISCVMacroFusionDAGMutation());
1524045b62dSCraig Topper       return DAG;
1534045b62dSCraig Topper     }
1544045b62dSCraig Topper     return nullptr;
1554045b62dSCraig Topper   }
1564045b62dSCraig Topper 
1574045b62dSCraig Topper   ScheduleDAGInstrs *
createPostMachineScheduler(MachineSchedContext * C) const1584045b62dSCraig Topper   createPostMachineScheduler(MachineSchedContext *C) const override {
1594045b62dSCraig Topper     const RISCVSubtarget &ST = C->MF->getSubtarget<RISCVSubtarget>();
1604045b62dSCraig Topper     if (ST.hasMacroFusion()) {
1614045b62dSCraig Topper       ScheduleDAGMI *DAG = createGenericSchedPostRA(C);
1624045b62dSCraig Topper       DAG->addMutation(createRISCVMacroFusionDAGMutation());
1634045b62dSCraig Topper       return DAG;
1644045b62dSCraig Topper     }
1654045b62dSCraig Topper     return nullptr;
1664045b62dSCraig Topper   }
1674045b62dSCraig Topper 
168dc790dd5SAlex Bradbury   void addIRPasses() override;
1694ff5e818Swangpc   bool addPreISel() override;
1708971842fSAlex Bradbury   bool addInstSelector() override;
171a16bd4f9SDaniel Sanders   bool addIRTranslator() override;
172a16bd4f9SDaniel Sanders   bool addLegalizeMachineIR() override;
173a16bd4f9SDaniel Sanders   bool addRegBankSelect() override;
174a16bd4f9SDaniel Sanders   bool addGlobalInstructionSelect() override;
175315cd3acSAlex Bradbury   void addPreEmitPass() override;
17621aea51eSAlex Bradbury   void addPreEmitPass2() override;
1772cb0644fSLuís Marques   void addPreSched2() override;
17856ca11e3SCraig Topper   void addMachineSSAOptimization() override;
1799b65ffb0SSameer AbuAsal   void addPreRegAlloc() override;
1801d8bbe3dSCraig Topper   void addPostRegAlloc() override;
1818971842fSAlex Bradbury };
1827948cd11SFraser Cormack } // namespace
1838971842fSAlex Bradbury 
createPassConfig(PassManagerBase & PM)184b2e5472dSAlex Bradbury TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
1858971842fSAlex Bradbury   return new RISCVPassConfig(*this, PM);
1868971842fSAlex Bradbury }
1878971842fSAlex Bradbury 
addIRPasses()188dc790dd5SAlex Bradbury void RISCVPassConfig::addIRPasses() {
189dc790dd5SAlex Bradbury   addPass(createAtomicExpandPass());
190d85e347aSCraig Topper 
191ee6267c4SCraig Topper   if (getOptLevel() != CodeGenOpt::None)
192d85e347aSCraig Topper     addPass(createRISCVGatherScatterLoweringPass());
193d85e347aSCraig Topper 
1941a8468baSCraig Topper   if (getOptLevel() != CodeGenOpt::None)
1951a8468baSCraig Topper     addPass(createRISCVCodeGenPreparePass());
196*8cc48309SCraig Topper 
197*8cc48309SCraig Topper   TargetPassConfig::addIRPasses();
1981a8468baSCraig Topper }
1991a8468baSCraig Topper 
addPreISel()2004ff5e818Swangpc bool RISCVPassConfig::addPreISel() {
2014ff5e818Swangpc   if (TM->getOptLevel() != CodeGenOpt::None) {
2024ff5e818Swangpc     // Add a barrier before instruction selection so that we will not get
2034ff5e818Swangpc     // deleted block address after enabling default outlining. See D99707 for
2044ff5e818Swangpc     // more details.
2054ff5e818Swangpc     addPass(createBarrierNoopPass());
2064ff5e818Swangpc   }
2074ff5e818Swangpc   return false;
2084ff5e818Swangpc }
2094ff5e818Swangpc 
addInstSelector()2108971842fSAlex Bradbury bool RISCVPassConfig::addInstSelector() {
2112cadf84fSeopXD   addPass(createRISCVISelDag(getRISCVTargetMachine(), getOptLevel()));
2128971842fSAlex Bradbury 
2138971842fSAlex Bradbury   return false;
214b2e5472dSAlex Bradbury }
215315cd3acSAlex Bradbury 
addIRTranslator()216a16bd4f9SDaniel Sanders bool RISCVPassConfig::addIRTranslator() {
217e5784ef8SAmara Emerson   addPass(new IRTranslator(getOptLevel()));
218a16bd4f9SDaniel Sanders   return false;
219a16bd4f9SDaniel Sanders }
220a16bd4f9SDaniel Sanders 
addLegalizeMachineIR()221a16bd4f9SDaniel Sanders bool RISCVPassConfig::addLegalizeMachineIR() {
222a16bd4f9SDaniel Sanders   addPass(new Legalizer());
223a16bd4f9SDaniel Sanders   return false;
224a16bd4f9SDaniel Sanders }
225a16bd4f9SDaniel Sanders 
addRegBankSelect()226a16bd4f9SDaniel Sanders bool RISCVPassConfig::addRegBankSelect() {
227a16bd4f9SDaniel Sanders   addPass(new RegBankSelect());
228a16bd4f9SDaniel Sanders   return false;
229a16bd4f9SDaniel Sanders }
230a16bd4f9SDaniel Sanders 
addGlobalInstructionSelect()231a16bd4f9SDaniel Sanders bool RISCVPassConfig::addGlobalInstructionSelect() {
2328a316045SAmara Emerson   addPass(new InstructionSelect(getOptLevel()));
233a16bd4f9SDaniel Sanders   return false;
234a16bd4f9SDaniel Sanders }
235a16bd4f9SDaniel Sanders 
addPreSched2()236b2aa546bSLuís Marques void RISCVPassConfig::addPreSched2() {}
2372cb0644fSLuís Marques 
addPreEmitPass()23829a5a7c6SLewis Revill void RISCVPassConfig::addPreEmitPass() {
23929a5a7c6SLewis Revill   addPass(&BranchRelaxationPassID);
24029a5a7c6SLewis Revill   addPass(createRISCVMakeCompressibleOptPass());
24129a5a7c6SLewis Revill }
2429b65ffb0SSameer AbuAsal 
addPreEmitPass2()24321aea51eSAlex Bradbury void RISCVPassConfig::addPreEmitPass2() {
2441d15bbb9SSam Elliott   addPass(createRISCVExpandPseudoPass());
24521aea51eSAlex Bradbury   // Schedule the expansion of AMOs at the last possible moment, avoiding the
24621aea51eSAlex Bradbury   // possibility for other passes to break the requirements for forward
24721aea51eSAlex Bradbury   // progress in the LR/SC block.
2482cb0644fSLuís Marques   addPass(createRISCVExpandAtomicPseudoPass());
24921aea51eSAlex Bradbury }
25021aea51eSAlex Bradbury 
addMachineSSAOptimization()25156ca11e3SCraig Topper void RISCVPassConfig::addMachineSSAOptimization() {
25256ca11e3SCraig Topper   TargetPassConfig::addMachineSSAOptimization();
25356ca11e3SCraig Topper 
25456ca11e3SCraig Topper   if (TM->getTargetTriple().getArch() == Triple::riscv64)
25556ca11e3SCraig Topper     addPass(createRISCVSExtWRemovalPass());
25656ca11e3SCraig Topper }
25756ca11e3SCraig Topper 
addPreRegAlloc()2589b65ffb0SSameer AbuAsal void RISCVPassConfig::addPreRegAlloc() {
259b510e4cfSCraig Topper   if (TM->getOptLevel() != CodeGenOpt::None)
2609b65ffb0SSameer AbuAsal     addPass(createRISCVMergeBaseOffsetOptPass());
261b510e4cfSCraig Topper   addPass(createRISCVInsertVSETVLIPass());
2629b65ffb0SSameer AbuAsal }
2631d8bbe3dSCraig Topper 
addPostRegAlloc()2641d8bbe3dSCraig Topper void RISCVPassConfig::addPostRegAlloc() {
2651d8bbe3dSCraig Topper   if (TM->getOptLevel() != CodeGenOpt::None && EnableRedundantCopyElimination)
2661d8bbe3dSCraig Topper     addPass(createRISCVRedundantCopyEliminationPass());
2671d8bbe3dSCraig Topper }
268690085c9SKito Cheng 
269690085c9SKito Cheng yaml::MachineFunctionInfo *
createDefaultFuncInfoYAML() const270690085c9SKito Cheng RISCVTargetMachine::createDefaultFuncInfoYAML() const {
271690085c9SKito Cheng   return new yaml::RISCVMachineFunctionInfo();
272690085c9SKito Cheng }
273690085c9SKito Cheng 
274690085c9SKito Cheng yaml::MachineFunctionInfo *
convertFuncInfoToYAML(const MachineFunction & MF) const275690085c9SKito Cheng RISCVTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {
276690085c9SKito Cheng   const auto *MFI = MF.getInfo<RISCVMachineFunctionInfo>();
277690085c9SKito Cheng   return new yaml::RISCVMachineFunctionInfo(*MFI);
278690085c9SKito Cheng }
279690085c9SKito Cheng 
parseMachineFunctionInfo(const yaml::MachineFunctionInfo & MFI,PerFunctionMIParsingState & PFS,SMDiagnostic & Error,SMRange & SourceRange) const280690085c9SKito Cheng bool RISCVTargetMachine::parseMachineFunctionInfo(
281690085c9SKito Cheng     const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
282690085c9SKito Cheng     SMDiagnostic &Error, SMRange &SourceRange) const {
283690085c9SKito Cheng   const auto &YamlMFI =
284690085c9SKito Cheng       static_cast<const yaml::RISCVMachineFunctionInfo &>(MFI);
285690085c9SKito Cheng   PFS.MF.getInfo<RISCVMachineFunctionInfo>()->initializeBaseYamlFields(YamlMFI);
286690085c9SKito Cheng   return false;
287690085c9SKito Cheng }
288