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