The VE backend represents vector instructions with an explicit 'i32' vector length operand. In the VE ISA, the vector length is always read from the VL hardware register. The LVLGen pass inserts 'lvl' instructions as necessary to set VL to the right value before each vector instruction. Reviewed By: kaz7 Differential Revision: https://reviews.llvm.org/D91416
124 lines
3.6 KiB
C++
124 lines
3.6 KiB
C++
//===-- VETargetMachine.cpp - Define TargetMachine for VE -----------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "VETargetMachine.h"
|
|
#include "TargetInfo/VETargetInfo.h"
|
|
#include "VE.h"
|
|
#include "VETargetTransformInfo.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
|
#include "llvm/IR/LegacyPassManager.h"
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "ve"
|
|
|
|
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVETarget() {
|
|
// Register the target.
|
|
RegisterTargetMachine<VETargetMachine> X(getTheVETarget());
|
|
}
|
|
|
|
static std::string computeDataLayout(const Triple &T) {
|
|
// Aurora VE is little endian
|
|
std::string Ret = "e";
|
|
|
|
// Use ELF mangling
|
|
Ret += "-m:e";
|
|
|
|
// Alignments for 64 bit integers.
|
|
Ret += "-i64:64";
|
|
|
|
// VE supports 32 bit and 64 bits integer on registers
|
|
Ret += "-n32:64";
|
|
|
|
// Stack alignment is 128 bits
|
|
Ret += "-S128";
|
|
|
|
return Ret;
|
|
}
|
|
|
|
static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
|
|
if (!RM.hasValue())
|
|
return Reloc::Static;
|
|
return *RM;
|
|
}
|
|
|
|
class VEELFTargetObjectFile : public TargetLoweringObjectFileELF {
|
|
void Initialize(MCContext &Ctx, const TargetMachine &TM) override {
|
|
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
|
InitializeELF(TM.Options.UseInitArray);
|
|
}
|
|
};
|
|
|
|
static std::unique_ptr<TargetLoweringObjectFile> createTLOF() {
|
|
return std::make_unique<VEELFTargetObjectFile>();
|
|
}
|
|
|
|
/// Create an Aurora VE architecture model
|
|
VETargetMachine::VETargetMachine(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(RM),
|
|
getEffectiveCodeModel(CM, CodeModel::Small), OL),
|
|
TLOF(createTLOF()),
|
|
Subtarget(TT, std::string(CPU), std::string(FS), *this) {
|
|
initAsmInfo();
|
|
}
|
|
|
|
VETargetMachine::~VETargetMachine() {}
|
|
|
|
TargetTransformInfo VETargetMachine::getTargetTransformInfo(const Function &F) {
|
|
return TargetTransformInfo(VETTIImpl(this, F));
|
|
}
|
|
|
|
namespace {
|
|
/// VE Code Generator Pass Configuration Options.
|
|
class VEPassConfig : public TargetPassConfig {
|
|
public:
|
|
VEPassConfig(VETargetMachine &TM, PassManagerBase &PM)
|
|
: TargetPassConfig(TM, PM) {}
|
|
|
|
VETargetMachine &getVETargetMachine() const {
|
|
return getTM<VETargetMachine>();
|
|
}
|
|
|
|
void addIRPasses() override;
|
|
bool addInstSelector() override;
|
|
void addPreEmitPass() override;
|
|
};
|
|
} // namespace
|
|
|
|
TargetPassConfig *VETargetMachine::createPassConfig(PassManagerBase &PM) {
|
|
return new VEPassConfig(*this, PM);
|
|
}
|
|
|
|
void VEPassConfig::addIRPasses() {
|
|
// VE requires atomic expand pass.
|
|
addPass(createAtomicExpandPass());
|
|
TargetPassConfig::addIRPasses();
|
|
}
|
|
|
|
bool VEPassConfig::addInstSelector() {
|
|
addPass(createVEISelDag(getVETargetMachine()));
|
|
return false;
|
|
}
|
|
|
|
void VEPassConfig::addPreEmitPass() {
|
|
// LVLGen should be called after scheduling and register allocation
|
|
addPass(createLVLGenPass());
|
|
}
|