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