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 #include "llvm/Transforms/IPO.h" 37 using namespace llvm; 38 39 static cl::opt<bool> EnableRedundantCopyElimination( 40 "riscv-enable-copyelim", 41 cl::desc("Enable the redundant copy elimination pass"), cl::init(true), 42 cl::Hidden); 43 44 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() { 45 RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target()); 46 RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target()); 47 auto *PR = PassRegistry::getPassRegistry(); 48 initializeGlobalISel(*PR); 49 initializeRISCVMakeCompressibleOptPass(*PR); 50 initializeRISCVGatherScatterLoweringPass(*PR); 51 initializeRISCVMergeBaseOffsetOptPass(*PR); 52 initializeRISCVSExtWRemovalPass(*PR); 53 initializeRISCVExpandPseudoPass(*PR); 54 initializeRISCVInsertVSETVLIPass(*PR); 55 } 56 57 static StringRef computeDataLayout(const Triple &TT) { 58 if (TT.isArch64Bit()) 59 return "e-m:e-p:64:64-i64:64-i128:128-n64-S128"; 60 assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported"); 61 return "e-m:e-p:32:32-i64:64-n32-S128"; 62 } 63 64 static Reloc::Model getEffectiveRelocModel(const Triple &TT, 65 Optional<Reloc::Model> RM) { 66 return RM.value_or(Reloc::Static); 67 } 68 69 RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT, 70 StringRef CPU, StringRef FS, 71 const TargetOptions &Options, 72 Optional<Reloc::Model> RM, 73 Optional<CodeModel::Model> CM, 74 CodeGenOpt::Level OL, bool JIT) 75 : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, 76 getEffectiveRelocModel(TT, RM), 77 getEffectiveCodeModel(CM, CodeModel::Small), OL), 78 TLOF(std::make_unique<RISCVELFTargetObjectFile>()) { 79 initAsmInfo(); 80 81 // RISC-V supports the MachineOutliner. 82 setMachineOutliner(true); 83 setSupportsDefaultOutlining(true); 84 } 85 86 const RISCVSubtarget * 87 RISCVTargetMachine::getSubtargetImpl(const Function &F) const { 88 Attribute CPUAttr = F.getFnAttribute("target-cpu"); 89 Attribute TuneAttr = F.getFnAttribute("tune-cpu"); 90 Attribute FSAttr = F.getFnAttribute("target-features"); 91 92 std::string CPU = 93 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 94 std::string TuneCPU = 95 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; 96 std::string FS = 97 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 98 std::string Key = CPU + TuneCPU + FS; 99 auto &I = SubtargetMap[Key]; 100 if (!I) { 101 // This needs to be done before we create a new subtarget since any 102 // creation will depend on the TM and the code generation flags on the 103 // function that reside in TargetOptions. 104 resetTargetOptions(F); 105 auto ABIName = Options.MCOptions.getABIName(); 106 if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>( 107 F.getParent()->getModuleFlag("target-abi"))) { 108 auto TargetABI = RISCVABI::getTargetABI(ABIName); 109 if (TargetABI != RISCVABI::ABI_Unknown && 110 ModuleTargetABI->getString() != ABIName) { 111 report_fatal_error("-target-abi option != target-abi module flag"); 112 } 113 ABIName = ModuleTargetABI->getString(); 114 } 115 I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, TuneCPU, FS, ABIName, *this); 116 } 117 return I.get(); 118 } 119 120 TargetTransformInfo 121 RISCVTargetMachine::getTargetTransformInfo(const Function &F) const { 122 return TargetTransformInfo(RISCVTTIImpl(this, F)); 123 } 124 125 // A RISC-V hart has a single byte-addressable address space of 2^XLEN bytes 126 // for all memory accesses, so it is reasonable to assume that an 127 // implementation has no-op address space casts. If an implementation makes a 128 // change to this, they can override it here. 129 bool RISCVTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS, 130 unsigned DstAS) const { 131 return true; 132 } 133 134 namespace { 135 class RISCVPassConfig : public TargetPassConfig { 136 public: 137 RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM) 138 : TargetPassConfig(TM, PM) {} 139 140 RISCVTargetMachine &getRISCVTargetMachine() const { 141 return getTM<RISCVTargetMachine>(); 142 } 143 144 void addIRPasses() override; 145 bool addPreISel() override; 146 bool addInstSelector() override; 147 bool addIRTranslator() override; 148 bool addLegalizeMachineIR() override; 149 bool addRegBankSelect() override; 150 bool addGlobalInstructionSelect() override; 151 void addPreEmitPass() override; 152 void addPreEmitPass2() override; 153 void addPreSched2() override; 154 void addMachineSSAOptimization() override; 155 void addPreRegAlloc() override; 156 void addPostRegAlloc() override; 157 }; 158 } // namespace 159 160 TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) { 161 return new RISCVPassConfig(*this, PM); 162 } 163 164 void RISCVPassConfig::addIRPasses() { 165 addPass(createAtomicExpandPass()); 166 167 addPass(createRISCVGatherScatterLoweringPass()); 168 169 TargetPassConfig::addIRPasses(); 170 } 171 172 bool RISCVPassConfig::addPreISel() { 173 if (TM->getOptLevel() != CodeGenOpt::None) { 174 // Add a barrier before instruction selection so that we will not get 175 // deleted block address after enabling default outlining. See D99707 for 176 // more details. 177 addPass(createBarrierNoopPass()); 178 } 179 return false; 180 } 181 182 bool RISCVPassConfig::addInstSelector() { 183 addPass(createRISCVISelDag(getRISCVTargetMachine(), getOptLevel())); 184 185 return false; 186 } 187 188 bool RISCVPassConfig::addIRTranslator() { 189 addPass(new IRTranslator(getOptLevel())); 190 return false; 191 } 192 193 bool RISCVPassConfig::addLegalizeMachineIR() { 194 addPass(new Legalizer()); 195 return false; 196 } 197 198 bool RISCVPassConfig::addRegBankSelect() { 199 addPass(new RegBankSelect()); 200 return false; 201 } 202 203 bool RISCVPassConfig::addGlobalInstructionSelect() { 204 addPass(new InstructionSelect(getOptLevel())); 205 return false; 206 } 207 208 void RISCVPassConfig::addPreSched2() {} 209 210 void RISCVPassConfig::addPreEmitPass() { 211 addPass(&BranchRelaxationPassID); 212 addPass(createRISCVMakeCompressibleOptPass()); 213 } 214 215 void RISCVPassConfig::addPreEmitPass2() { 216 addPass(createRISCVExpandPseudoPass()); 217 // Schedule the expansion of AMOs at the last possible moment, avoiding the 218 // possibility for other passes to break the requirements for forward 219 // progress in the LR/SC block. 220 addPass(createRISCVExpandAtomicPseudoPass()); 221 } 222 223 void RISCVPassConfig::addMachineSSAOptimization() { 224 TargetPassConfig::addMachineSSAOptimization(); 225 226 if (TM->getTargetTriple().getArch() == Triple::riscv64) 227 addPass(createRISCVSExtWRemovalPass()); 228 } 229 230 void RISCVPassConfig::addPreRegAlloc() { 231 if (TM->getOptLevel() != CodeGenOpt::None) 232 addPass(createRISCVMergeBaseOffsetOptPass()); 233 addPass(createRISCVInsertVSETVLIPass()); 234 } 235 236 void RISCVPassConfig::addPostRegAlloc() { 237 if (TM->getOptLevel() != CodeGenOpt::None && EnableRedundantCopyElimination) 238 addPass(createRISCVRedundantCopyEliminationPass()); 239 } 240 241 yaml::MachineFunctionInfo * 242 RISCVTargetMachine::createDefaultFuncInfoYAML() const { 243 return new yaml::RISCVMachineFunctionInfo(); 244 } 245 246 yaml::MachineFunctionInfo * 247 RISCVTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const { 248 const auto *MFI = MF.getInfo<RISCVMachineFunctionInfo>(); 249 return new yaml::RISCVMachineFunctionInfo(*MFI); 250 } 251 252 bool RISCVTargetMachine::parseMachineFunctionInfo( 253 const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS, 254 SMDiagnostic &Error, SMRange &SourceRange) const { 255 const auto &YamlMFI = 256 static_cast<const yaml::RISCVMachineFunctionInfo &>(MFI); 257 PFS.MF.getInfo<RISCVMachineFunctionInfo>()->initializeBaseYamlFields(YamlMFI); 258 return false; 259 } 260