1 //===-- RISCVTargetMachine.cpp - Define TargetMachine for RISCV -----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Implements the info about RISCV target spec. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RISCVTargetMachine.h" 14 #include "MCTargetDesc/RISCVBaseInfo.h" 15 #include "RISCV.h" 16 #include "RISCVMachineFunctionInfo.h" 17 #include "RISCVTargetObjectFile.h" 18 #include "RISCVTargetTransformInfo.h" 19 #include "TargetInfo/RISCVTargetInfo.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/Analysis/TargetTransformInfo.h" 22 #include "llvm/CodeGen/GlobalISel/IRTranslator.h" 23 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" 24 #include "llvm/CodeGen/GlobalISel/Legalizer.h" 25 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" 26 #include "llvm/CodeGen/MIRParser/MIParser.h" 27 #include "llvm/CodeGen/MIRYamlMapping.h" 28 #include "llvm/CodeGen/Passes.h" 29 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 30 #include "llvm/CodeGen/TargetPassConfig.h" 31 #include "llvm/IR/LegacyPassManager.h" 32 #include "llvm/InitializePasses.h" 33 #include "llvm/MC/TargetRegistry.h" 34 #include "llvm/Support/FormattedStream.h" 35 #include "llvm/Target/TargetOptions.h" 36 using namespace llvm; 37 38 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() { 39 RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target()); 40 RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target()); 41 auto *PR = PassRegistry::getPassRegistry(); 42 initializeGlobalISel(*PR); 43 initializeRISCVGatherScatterLoweringPass(*PR); 44 initializeRISCVMergeBaseOffsetOptPass(*PR); 45 initializeRISCVSExtWRemovalPass(*PR); 46 initializeRISCVExpandPseudoPass(*PR); 47 initializeRISCVInsertVSETVLIPass(*PR); 48 } 49 50 static StringRef computeDataLayout(const Triple &TT) { 51 if (TT.isArch64Bit()) 52 return "e-m:e-p:64:64-i64:64-i128:128-n64-S128"; 53 assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported"); 54 return "e-m:e-p:32:32-i64:64-n32-S128"; 55 } 56 57 static Reloc::Model getEffectiveRelocModel(const Triple &TT, 58 Optional<Reloc::Model> RM) { 59 if (!RM.hasValue()) 60 return Reloc::Static; 61 return *RM; 62 } 63 64 RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT, 65 StringRef CPU, StringRef FS, 66 const TargetOptions &Options, 67 Optional<Reloc::Model> RM, 68 Optional<CodeModel::Model> CM, 69 CodeGenOpt::Level OL, bool JIT) 70 : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, 71 getEffectiveRelocModel(TT, RM), 72 getEffectiveCodeModel(CM, CodeModel::Small), OL), 73 TLOF(std::make_unique<RISCVELFTargetObjectFile>()) { 74 initAsmInfo(); 75 76 // RISC-V supports the MachineOutliner. 77 setMachineOutliner(true); 78 } 79 80 const RISCVSubtarget * 81 RISCVTargetMachine::getSubtargetImpl(const Function &F) const { 82 Attribute CPUAttr = F.getFnAttribute("target-cpu"); 83 Attribute TuneAttr = F.getFnAttribute("tune-cpu"); 84 Attribute FSAttr = F.getFnAttribute("target-features"); 85 86 std::string CPU = 87 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 88 std::string TuneCPU = 89 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; 90 std::string FS = 91 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 92 std::string Key = CPU + TuneCPU + FS; 93 auto &I = SubtargetMap[Key]; 94 if (!I) { 95 // This needs to be done before we create a new subtarget since any 96 // creation will depend on the TM and the code generation flags on the 97 // function that reside in TargetOptions. 98 resetTargetOptions(F); 99 auto ABIName = Options.MCOptions.getABIName(); 100 if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>( 101 F.getParent()->getModuleFlag("target-abi"))) { 102 auto TargetABI = RISCVABI::getTargetABI(ABIName); 103 if (TargetABI != RISCVABI::ABI_Unknown && 104 ModuleTargetABI->getString() != ABIName) { 105 report_fatal_error("-target-abi option != target-abi module flag"); 106 } 107 ABIName = ModuleTargetABI->getString(); 108 } 109 I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, TuneCPU, FS, ABIName, *this); 110 } 111 return I.get(); 112 } 113 114 TargetTransformInfo 115 RISCVTargetMachine::getTargetTransformInfo(const Function &F) { 116 return TargetTransformInfo(RISCVTTIImpl(this, F)); 117 } 118 119 // A RISC-V hart has a single byte-addressable address space of 2^XLEN bytes 120 // for all memory accesses, so it is reasonable to assume that an 121 // implementation has no-op address space casts. If an implementation makes a 122 // change to this, they can override it here. 123 bool RISCVTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS, 124 unsigned DstAS) const { 125 return true; 126 } 127 128 namespace { 129 class RISCVPassConfig : public TargetPassConfig { 130 public: 131 RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM) 132 : TargetPassConfig(TM, PM) {} 133 134 RISCVTargetMachine &getRISCVTargetMachine() const { 135 return getTM<RISCVTargetMachine>(); 136 } 137 138 void addIRPasses() override; 139 bool addInstSelector() override; 140 bool addIRTranslator() override; 141 bool addLegalizeMachineIR() override; 142 bool addRegBankSelect() override; 143 bool addGlobalInstructionSelect() override; 144 void addPreEmitPass() override; 145 void addPreEmitPass2() override; 146 void addPreSched2() override; 147 void addMachineSSAOptimization() override; 148 void addPreRegAlloc() override; 149 }; 150 } // namespace 151 152 TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) { 153 return new RISCVPassConfig(*this, PM); 154 } 155 156 void RISCVPassConfig::addIRPasses() { 157 addPass(createAtomicExpandPass()); 158 159 addPass(createRISCVGatherScatterLoweringPass()); 160 161 TargetPassConfig::addIRPasses(); 162 } 163 164 bool RISCVPassConfig::addInstSelector() { 165 addPass(createRISCVISelDag(getRISCVTargetMachine())); 166 167 return false; 168 } 169 170 bool RISCVPassConfig::addIRTranslator() { 171 addPass(new IRTranslator(getOptLevel())); 172 return false; 173 } 174 175 bool RISCVPassConfig::addLegalizeMachineIR() { 176 addPass(new Legalizer()); 177 return false; 178 } 179 180 bool RISCVPassConfig::addRegBankSelect() { 181 addPass(new RegBankSelect()); 182 return false; 183 } 184 185 bool RISCVPassConfig::addGlobalInstructionSelect() { 186 addPass(new InstructionSelect(getOptLevel())); 187 return false; 188 } 189 190 void RISCVPassConfig::addPreSched2() {} 191 192 void RISCVPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); } 193 194 void RISCVPassConfig::addPreEmitPass2() { 195 addPass(createRISCVExpandPseudoPass()); 196 // Schedule the expansion of AMOs at the last possible moment, avoiding the 197 // possibility for other passes to break the requirements for forward 198 // progress in the LR/SC block. 199 addPass(createRISCVExpandAtomicPseudoPass()); 200 } 201 202 void RISCVPassConfig::addMachineSSAOptimization() { 203 TargetPassConfig::addMachineSSAOptimization(); 204 205 if (TM->getTargetTriple().getArch() == Triple::riscv64) 206 addPass(createRISCVSExtWRemovalPass()); 207 } 208 209 void RISCVPassConfig::addPreRegAlloc() { 210 if (TM->getOptLevel() != CodeGenOpt::None) 211 addPass(createRISCVMergeBaseOffsetOptPass()); 212 addPass(createRISCVInsertVSETVLIPass()); 213 } 214 215 yaml::MachineFunctionInfo * 216 RISCVTargetMachine::createDefaultFuncInfoYAML() const { 217 return new yaml::RISCVMachineFunctionInfo(); 218 } 219 220 yaml::MachineFunctionInfo * 221 RISCVTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const { 222 const auto *MFI = MF.getInfo<RISCVMachineFunctionInfo>(); 223 return new yaml::RISCVMachineFunctionInfo(*MFI); 224 } 225 226 bool RISCVTargetMachine::parseMachineFunctionInfo( 227 const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS, 228 SMDiagnostic &Error, SMRange &SourceRange) const { 229 const auto &YamlMFI = 230 static_cast<const yaml::RISCVMachineFunctionInfo &>(MFI); 231 PFS.MF.getInfo<RISCVMachineFunctionInfo>()->initializeBaseYamlFields(YamlMFI); 232 return false; 233 } 234