245 lines · cpp
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-exception6//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 29using namespace llvm;30 31#define DEBUG_TYPE "loongarch"32 33extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void34LLVMInitializeLoongArchTarget() {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 48static 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 55static 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 60static cl::opt<bool>61 EnableMergeBaseOffset("loongarch-enable-merge-offset",62 cl::desc("Enable the merge base offset pass"),63 cl::init(true), cl::Hidden);64 65static cl::opt<bool>66 EnableSinkFold("loongarch-enable-sink-fold",67 cl::desc("Enable sinking and folding of instruction copies"),68 cl::init(true), cl::Hidden);69 70static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {71 return RM.value_or(Reloc::Static);72}73 74static CodeModel::Model75getEffectiveLoongArchCodeModel(const Triple &TT,76 std::optional<CodeModel::Model> CM) {77 if (!CM)78 return TT.isArch64Bit() ? CodeModel::Medium : CodeModel::Small;79 80 switch (*CM) {81 case CodeModel::Small:82 return *CM;83 case CodeModel::Medium:84 case CodeModel::Large:85 if (!TT.isArch64Bit())86 report_fatal_error("Medium/Large code model requires LA64");87 return *CM;88 default:89 report_fatal_error(90 "Only small, medium and large code models are allowed on LoongArch");91 }92}93 94LoongArchTargetMachine::LoongArchTargetMachine(95 const Target &T, const Triple &TT, StringRef CPU, StringRef FS,96 const TargetOptions &Options, std::optional<Reloc::Model> RM,97 std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT)98 : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,99 getEffectiveRelocModel(RM),100 getEffectiveLoongArchCodeModel(TT, CM), OL),101 TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {102 initAsmInfo();103}104 105LoongArchTargetMachine::~LoongArchTargetMachine() = default;106 107const LoongArchSubtarget *108LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {109 Attribute CPUAttr = F.getFnAttribute("target-cpu");110 Attribute TuneAttr = F.getFnAttribute("tune-cpu");111 Attribute FSAttr = F.getFnAttribute("target-features");112 113 std::string CPU =114 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;115 std::string TuneCPU =116 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;117 std::string FS =118 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;119 120 std::string Key = CPU + TuneCPU + FS;121 auto &I = SubtargetMap[Key];122 if (!I) {123 // This needs to be done before we create a new subtarget since any124 // creation will depend on the TM and the code generation flags on the125 // function that reside in TargetOptions.126 resetTargetOptions(F);127 auto ABIName = Options.MCOptions.getABIName();128 if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(129 F.getParent()->getModuleFlag("target-abi"))) {130 auto TargetABI = LoongArchABI::getTargetABI(ABIName);131 if (TargetABI != LoongArchABI::ABI_Unknown &&132 ModuleTargetABI->getString() != ABIName) {133 report_fatal_error("-target-abi option != target-abi module flag");134 }135 ABIName = ModuleTargetABI->getString();136 }137 I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS,138 ABIName, *this);139 }140 return I.get();141}142 143MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo(144 BumpPtrAllocator &Allocator, const Function &F,145 const TargetSubtargetInfo *STI) const {146 return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>(147 Allocator, F, STI);148}149 150namespace {151class LoongArchPassConfig : public TargetPassConfig {152public:153 LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)154 : TargetPassConfig(TM, PM) {155 setEnableSinkAndFold(EnableSinkFold);156 }157 158 LoongArchTargetMachine &getLoongArchTargetMachine() const {159 return getTM<LoongArchTargetMachine>();160 }161 162 void addIRPasses() override;163 void addCodeGenPrepare() override;164 bool addInstSelector() override;165 void addPreEmitPass() override;166 void addPreEmitPass2() override;167 void addMachineSSAOptimization() override;168 void addPreRegAlloc() override;169 bool addRegAssignAndRewriteFast() override;170 bool addRegAssignAndRewriteOptimized() override;171};172} // end namespace173 174TargetPassConfig *175LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {176 return new LoongArchPassConfig(*this, PM);177}178 179void LoongArchPassConfig::addIRPasses() {180 // Run LoopDataPrefetch181 //182 // Run this before LSR to remove the multiplies involved in computing the183 // pointer values N iterations ahead.184 if (TM->getOptLevel() != CodeGenOptLevel::None && EnableLoopDataPrefetch)185 addPass(createLoopDataPrefetchPass());186 addPass(createAtomicExpandLegacyPass());187 188 TargetPassConfig::addIRPasses();189}190 191void LoongArchPassConfig::addCodeGenPrepare() {192 if (getOptLevel() != CodeGenOptLevel::None)193 addPass(createTypePromotionLegacyPass());194 TargetPassConfig::addCodeGenPrepare();195}196 197bool LoongArchPassConfig::addInstSelector() {198 addPass(createLoongArchISelDag(getLoongArchTargetMachine(), getOptLevel()));199 200 return false;201}202 203TargetTransformInfo204LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const {205 return TargetTransformInfo(std::make_unique<LoongArchTTIImpl>(this, F));206}207 208void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }209 210void LoongArchPassConfig::addPreEmitPass2() {211 addPass(createLoongArchExpandPseudoPass());212 // Schedule the expansion of AtomicPseudos at the last possible moment,213 // avoiding the possibility for other passes to break the requirements for214 // forward progress in the LL/SC block.215 addPass(createLoongArchExpandAtomicPseudoPass());216}217 218void LoongArchPassConfig::addMachineSSAOptimization() {219 TargetPassConfig::addMachineSSAOptimization();220 221 if (TM->getTargetTriple().isLoongArch64()) {222 addPass(createLoongArchOptWInstrsPass());223 }224}225 226void LoongArchPassConfig::addPreRegAlloc() {227 addPass(createLoongArchPreRAExpandPseudoPass());228 if (TM->getOptLevel() != CodeGenOptLevel::None && EnableMergeBaseOffset)229 addPass(createLoongArchMergeBaseOffsetOptPass());230}231 232bool LoongArchPassConfig::addRegAssignAndRewriteFast() {233 if (TM->getOptLevel() != CodeGenOptLevel::None &&234 EnableLoongArchDeadRegisterElimination)235 addPass(createLoongArchDeadRegisterDefinitionsPass());236 return TargetPassConfig::addRegAssignAndRewriteFast();237}238 239bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() {240 if (TM->getOptLevel() != CodeGenOptLevel::None &&241 EnableLoongArchDeadRegisterElimination)242 addPass(createLoongArchDeadRegisterDefinitionsPass());243 return TargetPassConfig::addRegAssignAndRewriteOptimized();244}245