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