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