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