1 //===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===// 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 LoongArch target spec. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LoongArchTargetMachine.h" 14 #include "LoongArch.h" 15 #include "LoongArchMachineFunctionInfo.h" 16 #include "LoongArchTargetTransformInfo.h" 17 #include "MCTargetDesc/LoongArchBaseInfo.h" 18 #include "TargetInfo/LoongArchTargetInfo.h" 19 #include "llvm/Analysis/TargetTransformInfo.h" 20 #include "llvm/CodeGen/Passes.h" 21 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 22 #include "llvm/CodeGen/TargetPassConfig.h" 23 #include "llvm/MC/TargetRegistry.h" 24 #include "llvm/Support/CodeGen.h" 25 #include "llvm/Support/Compiler.h" 26 #include "llvm/Transforms/Scalar.h" 27 #include <optional> 28 29 using namespace llvm; 30 31 #define DEBUG_TYPE "loongarch" 32 33 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void 34 LLVMInitializeLoongArchTarget() { 35 // Register the target. 36 RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target()); 37 RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target()); 38 auto *PR = PassRegistry::getPassRegistry(); 39 initializeLoongArchDeadRegisterDefinitionsPass(*PR); 40 initializeLoongArchMergeBaseOffsetOptPass(*PR); 41 initializeLoongArchOptWInstrsPass(*PR); 42 initializeLoongArchPreRAExpandPseudoPass(*PR); 43 initializeLoongArchExpandPseudoPass(*PR); 44 initializeLoongArchDAGToDAGISelLegacyPass(*PR); 45 initializeLoongArchExpandAtomicPseudoPass(*PR); 46 } 47 48 static cl::opt<bool> EnableLoongArchDeadRegisterElimination( 49 "loongarch-enable-dead-defs", cl::Hidden, 50 cl::desc("Enable the pass that removes dead" 51 " definitons and replaces stores to" 52 " them with stores to r0"), 53 cl::init(true)); 54 55 static cl::opt<bool> 56 EnableLoopDataPrefetch("loongarch-enable-loop-data-prefetch", cl::Hidden, 57 cl::desc("Enable the loop data prefetch pass"), 58 cl::init(false)); 59 60 static std::string computeDataLayout(const Triple &TT) { 61 if (TT.isArch64Bit()) 62 return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"; 63 assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported"); 64 return "e-m:e-p:32:32-i64:64-n32-S128"; 65 } 66 67 static Reloc::Model getEffectiveRelocModel(const Triple &TT, 68 std::optional<Reloc::Model> RM) { 69 return RM.value_or(Reloc::Static); 70 } 71 72 static CodeModel::Model 73 getEffectiveLoongArchCodeModel(const Triple &TT, 74 std::optional<CodeModel::Model> CM) { 75 if (!CM) 76 return TT.isArch64Bit() ? CodeModel::Medium : CodeModel::Small; 77 78 switch (*CM) { 79 case CodeModel::Small: 80 return *CM; 81 case CodeModel::Medium: 82 case CodeModel::Large: 83 if (!TT.isArch64Bit()) 84 report_fatal_error("Medium/Large code model requires LA64"); 85 return *CM; 86 default: 87 report_fatal_error( 88 "Only small, medium and large code models are allowed on LoongArch"); 89 } 90 } 91 92 LoongArchTargetMachine::LoongArchTargetMachine( 93 const Target &T, const Triple &TT, StringRef CPU, StringRef FS, 94 const TargetOptions &Options, std::optional<Reloc::Model> RM, 95 std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT) 96 : CodeGenTargetMachineImpl(T, computeDataLayout(TT), TT, CPU, FS, Options, 97 getEffectiveRelocModel(TT, RM), 98 getEffectiveLoongArchCodeModel(TT, CM), OL), 99 TLOF(std::make_unique<TargetLoweringObjectFileELF>()) { 100 initAsmInfo(); 101 } 102 103 LoongArchTargetMachine::~LoongArchTargetMachine() = default; 104 105 const LoongArchSubtarget * 106 LoongArchTargetMachine::getSubtargetImpl(const Function &F) const { 107 Attribute CPUAttr = F.getFnAttribute("target-cpu"); 108 Attribute TuneAttr = F.getFnAttribute("tune-cpu"); 109 Attribute FSAttr = F.getFnAttribute("target-features"); 110 111 std::string CPU = 112 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 113 std::string TuneCPU = 114 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; 115 std::string FS = 116 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 117 118 std::string Key = CPU + TuneCPU + FS; 119 auto &I = SubtargetMap[Key]; 120 if (!I) { 121 // This needs to be done before we create a new subtarget since any 122 // creation will depend on the TM and the code generation flags on the 123 // function that reside in TargetOptions. 124 resetTargetOptions(F); 125 auto ABIName = Options.MCOptions.getABIName(); 126 if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>( 127 F.getParent()->getModuleFlag("target-abi"))) { 128 auto TargetABI = LoongArchABI::getTargetABI(ABIName); 129 if (TargetABI != LoongArchABI::ABI_Unknown && 130 ModuleTargetABI->getString() != ABIName) { 131 report_fatal_error("-target-abi option != target-abi module flag"); 132 } 133 ABIName = ModuleTargetABI->getString(); 134 } 135 I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS, 136 ABIName, *this); 137 } 138 return I.get(); 139 } 140 141 MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo( 142 BumpPtrAllocator &Allocator, const Function &F, 143 const TargetSubtargetInfo *STI) const { 144 return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>( 145 Allocator, F, STI); 146 } 147 148 namespace { 149 class LoongArchPassConfig : public TargetPassConfig { 150 public: 151 LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM) 152 : TargetPassConfig(TM, PM) {} 153 154 LoongArchTargetMachine &getLoongArchTargetMachine() const { 155 return getTM<LoongArchTargetMachine>(); 156 } 157 158 void addIRPasses() override; 159 void addCodeGenPrepare() override; 160 bool addInstSelector() override; 161 void addPreEmitPass() override; 162 void addPreEmitPass2() override; 163 void addMachineSSAOptimization() override; 164 void addPreRegAlloc() override; 165 bool addRegAssignAndRewriteFast() override; 166 bool addRegAssignAndRewriteOptimized() override; 167 }; 168 } // end namespace 169 170 TargetPassConfig * 171 LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { 172 return new LoongArchPassConfig(*this, PM); 173 } 174 175 void LoongArchPassConfig::addIRPasses() { 176 // Run LoopDataPrefetch 177 // 178 // Run this before LSR to remove the multiplies involved in computing the 179 // pointer values N iterations ahead. 180 if (TM->getOptLevel() != CodeGenOptLevel::None && EnableLoopDataPrefetch) 181 addPass(createLoopDataPrefetchPass()); 182 addPass(createAtomicExpandLegacyPass()); 183 184 TargetPassConfig::addIRPasses(); 185 } 186 187 void LoongArchPassConfig::addCodeGenPrepare() { 188 if (getOptLevel() != CodeGenOptLevel::None) 189 addPass(createTypePromotionLegacyPass()); 190 TargetPassConfig::addCodeGenPrepare(); 191 } 192 193 bool LoongArchPassConfig::addInstSelector() { 194 addPass(createLoongArchISelDag(getLoongArchTargetMachine(), getOptLevel())); 195 196 return false; 197 } 198 199 TargetTransformInfo 200 LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const { 201 return TargetTransformInfo(std::make_unique<LoongArchTTIImpl>(this, F)); 202 } 203 204 void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); } 205 206 void LoongArchPassConfig::addPreEmitPass2() { 207 addPass(createLoongArchExpandPseudoPass()); 208 // Schedule the expansion of AtomicPseudos at the last possible moment, 209 // avoiding the possibility for other passes to break the requirements for 210 // forward progress in the LL/SC block. 211 addPass(createLoongArchExpandAtomicPseudoPass()); 212 } 213 214 void LoongArchPassConfig::addMachineSSAOptimization() { 215 TargetPassConfig::addMachineSSAOptimization(); 216 217 if (TM->getTargetTriple().isLoongArch64()) { 218 addPass(createLoongArchOptWInstrsPass()); 219 } 220 } 221 222 void LoongArchPassConfig::addPreRegAlloc() { 223 addPass(createLoongArchPreRAExpandPseudoPass()); 224 if (TM->getOptLevel() != CodeGenOptLevel::None) 225 addPass(createLoongArchMergeBaseOffsetOptPass()); 226 } 227 228 bool LoongArchPassConfig::addRegAssignAndRewriteFast() { 229 if (TM->getOptLevel() != CodeGenOptLevel::None && 230 EnableLoongArchDeadRegisterElimination) 231 addPass(createLoongArchDeadRegisterDefinitionsPass()); 232 return TargetPassConfig::addRegAssignAndRewriteFast(); 233 } 234 235 bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() { 236 if (TM->getOptLevel() != CodeGenOptLevel::None && 237 EnableLoongArchDeadRegisterElimination) 238 addPass(createLoongArchDeadRegisterDefinitionsPass()); 239 return TargetPassConfig::addRegAssignAndRewriteOptimized(); 240 } 241