llvm-project/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
Luís Marques 05a20a9e9a [RISCV] Temporarily move riscv-expand-pseudo pass to PreEmitPass2
The pass to split atomic and non-atomic RISC-V pseudo-instructions was itself
split into two passes in D79635 / commit rG2cb0644f90b7, with the splitting of
non-atomic instructions being moved to the PreSched2 phase. A comment was
added to D79635 detailing a case where this caused problems, so this commit
moves the non-atomic split pass back to the PreEmitPass2 phase. This allows
the bulk of the changes from D79635 to remain committed, while addressing the
the reported problem (the pass split is now almost NFC). Once the root problem
is fixed we can move the (non-atomic) instruction splitting pass back to
earlier in the pipeline.
2020-07-01 15:42:18 +01:00

186 lines
6.2 KiB
C++

//===-- RISCVTargetMachine.cpp - Define TargetMachine for RISCV -----------===//
//
// 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 RISCV target spec.
//
//===----------------------------------------------------------------------===//
#include "RISCVTargetMachine.h"
#include "RISCV.h"
#include "RISCVTargetObjectFile.h"
#include "RISCVTargetTransformInfo.h"
#include "TargetInfo/RISCVTargetInfo.h"
#include "Utils/RISCVBaseInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
auto PR = PassRegistry::getPassRegistry();
initializeGlobalISel(*PR);
initializeRISCVExpandPseudoPass(*PR);
}
static StringRef computeDataLayout(const Triple &TT) {
if (TT.isArch64Bit()) {
return "e-m:e-p:64:64-i64:64-i128:128-n64-S128";
} else {
assert(TT.isArch32Bit() && "only RV32 and RV64 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) {
if (!RM.hasValue())
return Reloc::Static;
return *RM;
}
RISCVTargetMachine::RISCVTargetMachine(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<RISCVELFTargetObjectFile>()) {
initAsmInfo();
// RISC-V supports the MachineOutliner.
setMachineOutliner(true);
}
const RISCVSubtarget *
RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
Attribute CPUAttr = F.getFnAttribute("target-cpu");
Attribute FSAttr = F.getFnAttribute("target-features");
std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
? CPUAttr.getValueAsString().str()
: TargetCPU;
std::string FS = !FSAttr.hasAttribute(Attribute::None)
? FSAttr.getValueAsString().str()
: TargetFS;
std::string Key = CPU + 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 = RISCVABI::getTargetABI(ABIName);
if (TargetABI != RISCVABI::ABI_Unknown &&
ModuleTargetABI->getString() != ABIName) {
report_fatal_error("-target-abi option != target-abi module flag");
}
ABIName = ModuleTargetABI->getString();
}
I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, FS, ABIName, *this);
}
return I.get();
}
TargetTransformInfo
RISCVTargetMachine::getTargetTransformInfo(const Function &F) {
return TargetTransformInfo(RISCVTTIImpl(this, F));
}
namespace {
class RISCVPassConfig : public TargetPassConfig {
public:
RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
RISCVTargetMachine &getRISCVTargetMachine() const {
return getTM<RISCVTargetMachine>();
}
void addIRPasses() override;
bool addInstSelector() override;
bool addIRTranslator() override;
bool addLegalizeMachineIR() override;
bool addRegBankSelect() override;
bool addGlobalInstructionSelect() override;
void addPreEmitPass() override;
void addPreEmitPass2() override;
void addPreSched2() override;
void addPreRegAlloc() override;
};
}
TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
return new RISCVPassConfig(*this, PM);
}
void RISCVPassConfig::addIRPasses() {
addPass(createAtomicExpandPass());
TargetPassConfig::addIRPasses();
}
bool RISCVPassConfig::addInstSelector() {
addPass(createRISCVISelDag(getRISCVTargetMachine()));
return false;
}
bool RISCVPassConfig::addIRTranslator() {
addPass(new IRTranslator());
return false;
}
bool RISCVPassConfig::addLegalizeMachineIR() {
addPass(new Legalizer());
return false;
}
bool RISCVPassConfig::addRegBankSelect() {
addPass(new RegBankSelect());
return false;
}
bool RISCVPassConfig::addGlobalInstructionSelect() {
addPass(new InstructionSelect());
return false;
}
void RISCVPassConfig::addPreSched2() { }
void RISCVPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
void RISCVPassConfig::addPreEmitPass2() {
addPass(createRISCVExpandPseudoPass());
// Schedule the expansion of AMOs at the last possible moment, avoiding the
// possibility for other passes to break the requirements for forward
// progress in the LR/SC block.
addPass(createRISCVExpandAtomicPseudoPass());
}
void RISCVPassConfig::addPreRegAlloc() {
addPass(createRISCVMergeBaseOffsetOptPass());
}