142 lines
5.0 KiB
C++
142 lines
5.0 KiB
C++
//===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Implements the info about LoongArch target spec.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "LoongArchTargetMachine.h"
|
|
#include "LoongArch.h"
|
|
#include "MCTargetDesc/LoongArchBaseInfo.h"
|
|
#include "TargetInfo/LoongArchTargetInfo.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
|
#include "llvm/MC/TargetRegistry.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "loongarch"
|
|
|
|
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
|
|
// Register the target.
|
|
RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());
|
|
RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
|
|
auto *PR = PassRegistry::getPassRegistry();
|
|
initializeLoongArchPreRAExpandPseudoPass(*PR);
|
|
}
|
|
|
|
static std::string computeDataLayout(const Triple &TT) {
|
|
if (TT.isArch64Bit())
|
|
return "e-m:e-p:64:64-i64:64-i128:128-n64-S128";
|
|
assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported");
|
|
return "e-m:e-p:32:32-i64:64-n32-S128";
|
|
}
|
|
|
|
static Reloc::Model getEffectiveRelocModel(const Triple &TT,
|
|
Optional<Reloc::Model> RM) {
|
|
return RM.value_or(Reloc::Static);
|
|
}
|
|
|
|
LoongArchTargetMachine::LoongArchTargetMachine(
|
|
const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
|
|
const TargetOptions &Options, Optional<Reloc::Model> RM,
|
|
Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
|
|
: LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
|
|
getEffectiveRelocModel(TT, RM),
|
|
getEffectiveCodeModel(CM, CodeModel::Small), OL),
|
|
TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
|
|
initAsmInfo();
|
|
}
|
|
|
|
LoongArchTargetMachine::~LoongArchTargetMachine() = default;
|
|
|
|
const LoongArchSubtarget *
|
|
LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {
|
|
Attribute CPUAttr = F.getFnAttribute("target-cpu");
|
|
Attribute TuneAttr = F.getFnAttribute("tune-cpu");
|
|
Attribute FSAttr = F.getFnAttribute("target-features");
|
|
|
|
std::string CPU =
|
|
CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
|
|
std::string TuneCPU =
|
|
TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
|
|
std::string FS =
|
|
FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
|
|
|
|
std::string Key = CPU + TuneCPU + FS;
|
|
auto &I = SubtargetMap[Key];
|
|
if (!I) {
|
|
// This needs to be done before we create a new subtarget since any
|
|
// creation will depend on the TM and the code generation flags on the
|
|
// function that reside in TargetOptions.
|
|
resetTargetOptions(F);
|
|
auto ABIName = Options.MCOptions.getABIName();
|
|
if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
|
|
F.getParent()->getModuleFlag("target-abi"))) {
|
|
auto TargetABI = LoongArchABI::getTargetABI(ABIName);
|
|
if (TargetABI != LoongArchABI::ABI_Unknown &&
|
|
ModuleTargetABI->getString() != ABIName) {
|
|
report_fatal_error("-target-abi option != target-abi module flag");
|
|
}
|
|
ABIName = ModuleTargetABI->getString();
|
|
}
|
|
I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS,
|
|
ABIName, *this);
|
|
}
|
|
return I.get();
|
|
}
|
|
|
|
namespace {
|
|
class LoongArchPassConfig : public TargetPassConfig {
|
|
public:
|
|
LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)
|
|
: TargetPassConfig(TM, PM) {}
|
|
|
|
LoongArchTargetMachine &getLoongArchTargetMachine() const {
|
|
return getTM<LoongArchTargetMachine>();
|
|
}
|
|
|
|
void addIRPasses() override;
|
|
bool addInstSelector() override;
|
|
void addPreEmitPass() override;
|
|
void addPreEmitPass2() override;
|
|
void addPreRegAlloc() override;
|
|
};
|
|
} // end namespace
|
|
|
|
TargetPassConfig *
|
|
LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
|
|
return new LoongArchPassConfig(*this, PM);
|
|
}
|
|
|
|
void LoongArchPassConfig::addIRPasses() {
|
|
addPass(createAtomicExpandPass());
|
|
|
|
TargetPassConfig::addIRPasses();
|
|
}
|
|
|
|
bool LoongArchPassConfig::addInstSelector() {
|
|
addPass(createLoongArchISelDag(getLoongArchTargetMachine()));
|
|
|
|
return false;
|
|
}
|
|
|
|
void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
|
|
|
|
void LoongArchPassConfig::addPreEmitPass2() {
|
|
// Schedule the expansion of AtomicPseudos at the last possible moment,
|
|
// avoiding the possibility for other passes to break the requirements for
|
|
// forward progress in the LL/SC block.
|
|
addPass(createLoongArchExpandAtomicPseudoPass());
|
|
}
|
|
|
|
void LoongArchPassConfig::addPreRegAlloc() {
|
|
addPass(createLoongArchPreRAExpandPseudoPass());
|
|
}
|