1444c6d26SLu Weining //===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===// 2444c6d26SLu Weining // 3444c6d26SLu Weining // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4444c6d26SLu Weining // See https://llvm.org/LICENSE.txt for license information. 5444c6d26SLu Weining // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6444c6d26SLu Weining // 7444c6d26SLu Weining //===----------------------------------------------------------------------===// 8444c6d26SLu Weining // 9444c6d26SLu Weining // Implements the info about LoongArch target spec. 10444c6d26SLu Weining // 11444c6d26SLu Weining //===----------------------------------------------------------------------===// 12444c6d26SLu Weining 13444c6d26SLu Weining #include "LoongArchTargetMachine.h" 1433388ae8SLu Weining #include "LoongArch.h" 1508220df6Swanglei #include "LoongArchMachineFunctionInfo.h" 161918cf58SZhao Qi #include "LoongArchTargetTransformInfo.h" 1733388ae8SLu Weining #include "MCTargetDesc/LoongArchBaseInfo.h" 18444c6d26SLu Weining #include "TargetInfo/LoongArchTargetInfo.h" 191918cf58SZhao Qi #include "llvm/Analysis/TargetTransformInfo.h" 2033388ae8SLu Weining #include "llvm/CodeGen/Passes.h" 2133388ae8SLu Weining #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 2233388ae8SLu Weining #include "llvm/CodeGen/TargetPassConfig.h" 23444c6d26SLu Weining #include "llvm/MC/TargetRegistry.h" 2400786d3aSWANG Xuerui #include "llvm/Support/CodeGen.h" 2511674147SXiaodong Liu #include "llvm/Transforms/Scalar.h" 268c7c20f0SKrzysztof Parzyszek #include <optional> 27444c6d26SLu Weining 28444c6d26SLu Weining using namespace llvm; 29444c6d26SLu Weining 30444c6d26SLu Weining #define DEBUG_TYPE "loongarch" 31444c6d26SLu Weining 32444c6d26SLu Weining extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() { 33444c6d26SLu Weining // Register the target. 34444c6d26SLu Weining RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target()); 35444c6d26SLu Weining RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target()); 3675265c7fSwanglei auto *PR = PassRegistry::getPassRegistry(); 37240512c4Shev initializeLoongArchDeadRegisterDefinitionsPass(*PR); 38b2e69f52Shev initializeLoongArchMergeBaseOffsetOptPass(*PR); 39e9bcd2bfShev initializeLoongArchOptWInstrsPass(*PR); 4075265c7fSwanglei initializeLoongArchPreRAExpandPseudoPass(*PR); 41*0288d065SZhaoQi initializeLoongArchExpandPseudoPass(*PR); 427652a594Spaperchalice initializeLoongArchDAGToDAGISelLegacyPass(*PR); 43444c6d26SLu Weining } 44444c6d26SLu Weining 45240512c4Shev static cl::opt<bool> EnableLoongArchDeadRegisterElimination( 46240512c4Shev "loongarch-enable-dead-defs", cl::Hidden, 47240512c4Shev cl::desc("Enable the pass that removes dead" 48240512c4Shev " definitons and replaces stores to" 49240512c4Shev " them with stores to r0"), 50240512c4Shev cl::init(true)); 51240512c4Shev 5211674147SXiaodong Liu static cl::opt<bool> 5311674147SXiaodong Liu EnableLoopDataPrefetch("loongarch-enable-loop-data-prefetch", cl::Hidden, 5411674147SXiaodong Liu cl::desc("Enable the loop data prefetch pass"), 5511674147SXiaodong Liu cl::init(false)); 5611674147SXiaodong Liu 57444c6d26SLu Weining static std::string computeDataLayout(const Triple &TT) { 58a1c67439Swanglei if (TT.isArch64Bit()) 5946edc02eShev return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"; 60a1c67439Swanglei assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported"); 61a1c67439Swanglei return "e-m:e-p:32:32-i64:64-n32-S128"; 62444c6d26SLu Weining } 63444c6d26SLu Weining 64444c6d26SLu Weining static Reloc::Model getEffectiveRelocModel(const Triple &TT, 65bac97427SFangrui Song std::optional<Reloc::Model> RM) { 663c849d0aSFangrui Song return RM.value_or(Reloc::Static); 67444c6d26SLu Weining } 68444c6d26SLu Weining 6900786d3aSWANG Xuerui static CodeModel::Model 7000786d3aSWANG Xuerui getEffectiveLoongArchCodeModel(const Triple &TT, 7100786d3aSWANG Xuerui std::optional<CodeModel::Model> CM) { 7200786d3aSWANG Xuerui if (!CM) 7300786d3aSWANG Xuerui return CodeModel::Small; 7400786d3aSWANG Xuerui 7500786d3aSWANG Xuerui switch (*CM) { 7600786d3aSWANG Xuerui case CodeModel::Small: 7700786d3aSWANG Xuerui return *CM; 782cf420d5Swanglei case CodeModel::Medium: 7900786d3aSWANG Xuerui case CodeModel::Large: 8000786d3aSWANG Xuerui if (!TT.isArch64Bit()) 812cf420d5Swanglei report_fatal_error("Medium/Large code model requires LA64"); 8200786d3aSWANG Xuerui return *CM; 8300786d3aSWANG Xuerui default: 8400786d3aSWANG Xuerui report_fatal_error( 8500786d3aSWANG Xuerui "Only small, medium and large code models are allowed on LoongArch"); 8600786d3aSWANG Xuerui } 8700786d3aSWANG Xuerui } 8800786d3aSWANG Xuerui 89444c6d26SLu Weining LoongArchTargetMachine::LoongArchTargetMachine( 90444c6d26SLu Weining const Target &T, const Triple &TT, StringRef CPU, StringRef FS, 91bac97427SFangrui Song const TargetOptions &Options, std::optional<Reloc::Model> RM, 920a1aa6cdSArthur Eubanks std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT) 93bb3f5e1fSMatin Raayai : CodeGenTargetMachineImpl(T, computeDataLayout(TT), TT, CPU, FS, Options, 94444c6d26SLu Weining getEffectiveRelocModel(TT, RM), 9500786d3aSWANG Xuerui getEffectiveLoongArchCodeModel(TT, CM), OL), 9633388ae8SLu Weining TLOF(std::make_unique<TargetLoweringObjectFileELF>()) { 97444c6d26SLu Weining initAsmInfo(); 98444c6d26SLu Weining } 99444c6d26SLu Weining 100444c6d26SLu Weining LoongArchTargetMachine::~LoongArchTargetMachine() = default; 10133388ae8SLu Weining 10233388ae8SLu Weining const LoongArchSubtarget * 10333388ae8SLu Weining LoongArchTargetMachine::getSubtargetImpl(const Function &F) const { 10433388ae8SLu Weining Attribute CPUAttr = F.getFnAttribute("target-cpu"); 10533388ae8SLu Weining Attribute TuneAttr = F.getFnAttribute("tune-cpu"); 10633388ae8SLu Weining Attribute FSAttr = F.getFnAttribute("target-features"); 10733388ae8SLu Weining 10833388ae8SLu Weining std::string CPU = 10933388ae8SLu Weining CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 11033388ae8SLu Weining std::string TuneCPU = 11133388ae8SLu Weining TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; 11233388ae8SLu Weining std::string FS = 11333388ae8SLu Weining FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 11433388ae8SLu Weining 11533388ae8SLu Weining std::string Key = CPU + TuneCPU + FS; 11633388ae8SLu Weining auto &I = SubtargetMap[Key]; 11733388ae8SLu Weining if (!I) { 11833388ae8SLu Weining // This needs to be done before we create a new subtarget since any 11933388ae8SLu Weining // creation will depend on the TM and the code generation flags on the 12033388ae8SLu Weining // function that reside in TargetOptions. 12133388ae8SLu Weining resetTargetOptions(F); 12233388ae8SLu Weining auto ABIName = Options.MCOptions.getABIName(); 12333388ae8SLu Weining if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>( 12433388ae8SLu Weining F.getParent()->getModuleFlag("target-abi"))) { 12533388ae8SLu Weining auto TargetABI = LoongArchABI::getTargetABI(ABIName); 12633388ae8SLu Weining if (TargetABI != LoongArchABI::ABI_Unknown && 12733388ae8SLu Weining ModuleTargetABI->getString() != ABIName) { 12833388ae8SLu Weining report_fatal_error("-target-abi option != target-abi module flag"); 12933388ae8SLu Weining } 13033388ae8SLu Weining ABIName = ModuleTargetABI->getString(); 13133388ae8SLu Weining } 13233388ae8SLu Weining I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS, 13333388ae8SLu Weining ABIName, *this); 13433388ae8SLu Weining } 13533388ae8SLu Weining return I.get(); 13633388ae8SLu Weining } 13733388ae8SLu Weining 138c774fd55SMatt Arsenault MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo( 139c774fd55SMatt Arsenault BumpPtrAllocator &Allocator, const Function &F, 140c774fd55SMatt Arsenault const TargetSubtargetInfo *STI) const { 141c774fd55SMatt Arsenault return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>( 142c774fd55SMatt Arsenault Allocator, F, STI); 143c774fd55SMatt Arsenault } 144c774fd55SMatt Arsenault 14533388ae8SLu Weining namespace { 14633388ae8SLu Weining class LoongArchPassConfig : public TargetPassConfig { 14733388ae8SLu Weining public: 14833388ae8SLu Weining LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM) 14933388ae8SLu Weining : TargetPassConfig(TM, PM) {} 15033388ae8SLu Weining 15133388ae8SLu Weining LoongArchTargetMachine &getLoongArchTargetMachine() const { 15233388ae8SLu Weining return getTM<LoongArchTargetMachine>(); 15333388ae8SLu Weining } 15433388ae8SLu Weining 15547f3dc6dSgonglingqin void addIRPasses() override; 1563850912fShev void addCodeGenPrepare() override; 15733388ae8SLu Weining bool addInstSelector() override; 15857ad3f1dSXiaodong Liu void addPreEmitPass() override; 159b60f8016Sgonglingqin void addPreEmitPass2() override; 160e9bcd2bfShev void addMachineSSAOptimization() override; 16175265c7fSwanglei void addPreRegAlloc() override; 162240512c4Shev bool addRegAssignAndRewriteFast() override; 163240512c4Shev bool addRegAssignAndRewriteOptimized() override; 16433388ae8SLu Weining }; 165904a87acSWeining Lu } // end namespace 16633388ae8SLu Weining 16733388ae8SLu Weining TargetPassConfig * 16833388ae8SLu Weining LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { 16933388ae8SLu Weining return new LoongArchPassConfig(*this, PM); 17033388ae8SLu Weining } 17133388ae8SLu Weining 17247f3dc6dSgonglingqin void LoongArchPassConfig::addIRPasses() { 17311674147SXiaodong Liu // Run LoopDataPrefetch 17411674147SXiaodong Liu // 17511674147SXiaodong Liu // Run this before LSR to remove the multiplies involved in computing the 17611674147SXiaodong Liu // pointer values N iterations ahead. 1770a1aa6cdSArthur Eubanks if (TM->getOptLevel() != CodeGenOptLevel::None && EnableLoopDataPrefetch) 17811674147SXiaodong Liu addPass(createLoopDataPrefetchPass()); 179fe42e72dSRishabh Bali addPass(createAtomicExpandLegacyPass()); 18047f3dc6dSgonglingqin 18147f3dc6dSgonglingqin TargetPassConfig::addIRPasses(); 18247f3dc6dSgonglingqin } 18347f3dc6dSgonglingqin 1843850912fShev void LoongArchPassConfig::addCodeGenPrepare() { 1853850912fShev if (getOptLevel() != CodeGenOptLevel::None) 1863850912fShev addPass(createTypePromotionLegacyPass()); 1873850912fShev TargetPassConfig::addCodeGenPrepare(); 1883850912fShev } 1893850912fShev 19033388ae8SLu Weining bool LoongArchPassConfig::addInstSelector() { 19133388ae8SLu Weining addPass(createLoongArchISelDag(getLoongArchTargetMachine())); 19233388ae8SLu Weining 19333388ae8SLu Weining return false; 19433388ae8SLu Weining } 195b60f8016Sgonglingqin 1961918cf58SZhao Qi TargetTransformInfo 1971918cf58SZhao Qi LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const { 1981918cf58SZhao Qi return TargetTransformInfo(LoongArchTTIImpl(this, F)); 1991918cf58SZhao Qi } 2001918cf58SZhao Qi 20157ad3f1dSXiaodong Liu void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); } 20257ad3f1dSXiaodong Liu 203b60f8016Sgonglingqin void LoongArchPassConfig::addPreEmitPass2() { 204271087e3Swanglei addPass(createLoongArchExpandPseudoPass()); 205b60f8016Sgonglingqin // Schedule the expansion of AtomicPseudos at the last possible moment, 206b60f8016Sgonglingqin // avoiding the possibility for other passes to break the requirements for 207b60f8016Sgonglingqin // forward progress in the LL/SC block. 208b60f8016Sgonglingqin addPass(createLoongArchExpandAtomicPseudoPass()); 209b60f8016Sgonglingqin } 21075265c7fSwanglei 211e9bcd2bfShev void LoongArchPassConfig::addMachineSSAOptimization() { 212e9bcd2bfShev TargetPassConfig::addMachineSSAOptimization(); 213e9bcd2bfShev 214e9bcd2bfShev if (TM->getTargetTriple().isLoongArch64()) { 215e9bcd2bfShev addPass(createLoongArchOptWInstrsPass()); 216e9bcd2bfShev } 217e9bcd2bfShev } 218e9bcd2bfShev 21975265c7fSwanglei void LoongArchPassConfig::addPreRegAlloc() { 22075265c7fSwanglei addPass(createLoongArchPreRAExpandPseudoPass()); 221b2e69f52Shev if (TM->getOptLevel() != CodeGenOptLevel::None) 222b2e69f52Shev addPass(createLoongArchMergeBaseOffsetOptPass()); 22375265c7fSwanglei } 224240512c4Shev 225240512c4Shev bool LoongArchPassConfig::addRegAssignAndRewriteFast() { 226240512c4Shev if (TM->getOptLevel() != CodeGenOptLevel::None && 227240512c4Shev EnableLoongArchDeadRegisterElimination) 228240512c4Shev addPass(createLoongArchDeadRegisterDefinitionsPass()); 229240512c4Shev return TargetPassConfig::addRegAssignAndRewriteFast(); 230240512c4Shev } 231240512c4Shev 232240512c4Shev bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() { 233240512c4Shev if (TM->getOptLevel() != CodeGenOptLevel::None && 234240512c4Shev EnableLoongArchDeadRegisterElimination) 235240512c4Shev addPass(createLoongArchDeadRegisterDefinitionsPass()); 236240512c4Shev return TargetPassConfig::addRegAssignAndRewriteOptimized(); 237240512c4Shev } 238