Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
35294 views
//===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Implements the info about LoongArch target spec.9//10//===----------------------------------------------------------------------===//1112#include "LoongArchTargetMachine.h"13#include "LoongArch.h"14#include "LoongArchMachineFunctionInfo.h"15#include "LoongArchTargetTransformInfo.h"16#include "MCTargetDesc/LoongArchBaseInfo.h"17#include "TargetInfo/LoongArchTargetInfo.h"18#include "llvm/Analysis/TargetTransformInfo.h"19#include "llvm/CodeGen/Passes.h"20#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"21#include "llvm/CodeGen/TargetPassConfig.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Support/CodeGen.h"24#include "llvm/Transforms/Scalar.h"25#include <optional>2627using namespace llvm;2829#define DEBUG_TYPE "loongarch"3031extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {32// Register the target.33RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());34RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());35auto *PR = PassRegistry::getPassRegistry();36initializeLoongArchDeadRegisterDefinitionsPass(*PR);37initializeLoongArchOptWInstrsPass(*PR);38initializeLoongArchPreRAExpandPseudoPass(*PR);39initializeLoongArchDAGToDAGISelLegacyPass(*PR);40}4142static cl::opt<bool> EnableLoongArchDeadRegisterElimination(43"loongarch-enable-dead-defs", cl::Hidden,44cl::desc("Enable the pass that removes dead"45" definitons and replaces stores to"46" them with stores to r0"),47cl::init(true));4849static cl::opt<bool>50EnableLoopDataPrefetch("loongarch-enable-loop-data-prefetch", cl::Hidden,51cl::desc("Enable the loop data prefetch pass"),52cl::init(false));5354static std::string computeDataLayout(const Triple &TT) {55if (TT.isArch64Bit())56return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";57assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported");58return "e-m:e-p:32:32-i64:64-n32-S128";59}6061static Reloc::Model getEffectiveRelocModel(const Triple &TT,62std::optional<Reloc::Model> RM) {63return RM.value_or(Reloc::Static);64}6566static CodeModel::Model67getEffectiveLoongArchCodeModel(const Triple &TT,68std::optional<CodeModel::Model> CM) {69if (!CM)70return CodeModel::Small;7172switch (*CM) {73case CodeModel::Small:74return *CM;75case CodeModel::Medium:76case CodeModel::Large:77if (!TT.isArch64Bit())78report_fatal_error("Medium/Large code model requires LA64");79return *CM;80default:81report_fatal_error(82"Only small, medium and large code models are allowed on LoongArch");83}84}8586LoongArchTargetMachine::LoongArchTargetMachine(87const Target &T, const Triple &TT, StringRef CPU, StringRef FS,88const TargetOptions &Options, std::optional<Reloc::Model> RM,89std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT)90: LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,91getEffectiveRelocModel(TT, RM),92getEffectiveLoongArchCodeModel(TT, CM), OL),93TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {94initAsmInfo();95}9697LoongArchTargetMachine::~LoongArchTargetMachine() = default;9899const LoongArchSubtarget *100LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {101Attribute CPUAttr = F.getFnAttribute("target-cpu");102Attribute TuneAttr = F.getFnAttribute("tune-cpu");103Attribute FSAttr = F.getFnAttribute("target-features");104105std::string CPU =106CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;107std::string TuneCPU =108TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;109std::string FS =110FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;111112std::string Key = CPU + TuneCPU + FS;113auto &I = SubtargetMap[Key];114if (!I) {115// This needs to be done before we create a new subtarget since any116// creation will depend on the TM and the code generation flags on the117// function that reside in TargetOptions.118resetTargetOptions(F);119auto ABIName = Options.MCOptions.getABIName();120if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(121F.getParent()->getModuleFlag("target-abi"))) {122auto TargetABI = LoongArchABI::getTargetABI(ABIName);123if (TargetABI != LoongArchABI::ABI_Unknown &&124ModuleTargetABI->getString() != ABIName) {125report_fatal_error("-target-abi option != target-abi module flag");126}127ABIName = ModuleTargetABI->getString();128}129I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS,130ABIName, *this);131}132return I.get();133}134135MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo(136BumpPtrAllocator &Allocator, const Function &F,137const TargetSubtargetInfo *STI) const {138return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>(139Allocator, F, STI);140}141142namespace {143class LoongArchPassConfig : public TargetPassConfig {144public:145LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)146: TargetPassConfig(TM, PM) {}147148LoongArchTargetMachine &getLoongArchTargetMachine() const {149return getTM<LoongArchTargetMachine>();150}151152void addIRPasses() override;153void addCodeGenPrepare() override;154bool addInstSelector() override;155void addPreEmitPass() override;156void addPreEmitPass2() override;157void addMachineSSAOptimization() override;158void addPreRegAlloc() override;159bool addRegAssignAndRewriteFast() override;160bool addRegAssignAndRewriteOptimized() override;161};162} // end namespace163164TargetPassConfig *165LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {166return new LoongArchPassConfig(*this, PM);167}168169void LoongArchPassConfig::addIRPasses() {170// Run LoopDataPrefetch171//172// Run this before LSR to remove the multiplies involved in computing the173// pointer values N iterations ahead.174if (TM->getOptLevel() != CodeGenOptLevel::None && EnableLoopDataPrefetch)175addPass(createLoopDataPrefetchPass());176addPass(createAtomicExpandLegacyPass());177178TargetPassConfig::addIRPasses();179}180181void LoongArchPassConfig::addCodeGenPrepare() {182if (getOptLevel() != CodeGenOptLevel::None)183addPass(createTypePromotionLegacyPass());184TargetPassConfig::addCodeGenPrepare();185}186187bool LoongArchPassConfig::addInstSelector() {188addPass(createLoongArchISelDag(getLoongArchTargetMachine()));189190return false;191}192193TargetTransformInfo194LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const {195return TargetTransformInfo(LoongArchTTIImpl(this, F));196}197198void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }199200void LoongArchPassConfig::addPreEmitPass2() {201addPass(createLoongArchExpandPseudoPass());202// Schedule the expansion of AtomicPseudos at the last possible moment,203// avoiding the possibility for other passes to break the requirements for204// forward progress in the LL/SC block.205addPass(createLoongArchExpandAtomicPseudoPass());206}207208void LoongArchPassConfig::addMachineSSAOptimization() {209TargetPassConfig::addMachineSSAOptimization();210211if (TM->getTargetTriple().isLoongArch64()) {212addPass(createLoongArchOptWInstrsPass());213}214}215216void LoongArchPassConfig::addPreRegAlloc() {217addPass(createLoongArchPreRAExpandPseudoPass());218}219220bool LoongArchPassConfig::addRegAssignAndRewriteFast() {221if (TM->getOptLevel() != CodeGenOptLevel::None &&222EnableLoongArchDeadRegisterElimination)223addPass(createLoongArchDeadRegisterDefinitionsPass());224return TargetPassConfig::addRegAssignAndRewriteFast();225}226227bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() {228if (TM->getOptLevel() != CodeGenOptLevel::None &&229EnableLoongArchDeadRegisterElimination)230addPass(createLoongArchDeadRegisterDefinitionsPass());231return TargetPassConfig::addRegAssignAndRewriteOptimized();232}233234235