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