1480093f4SDimitry Andric //===-- VETargetMachine.cpp - Define TargetMachine for VE -----------------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // 10480093f4SDimitry Andric //===----------------------------------------------------------------------===// 11480093f4SDimitry Andric 12480093f4SDimitry Andric #include "VETargetMachine.h" 135ffd83dbSDimitry Andric #include "TargetInfo/VETargetInfo.h" 14480093f4SDimitry Andric #include "VE.h" 15480093f4SDimitry Andric #include "VETargetTransformInfo.h" 16480093f4SDimitry Andric #include "llvm/CodeGen/Passes.h" 17480093f4SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 18480093f4SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 19480093f4SDimitry Andric #include "llvm/IR/LegacyPassManager.h" 20*349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 21480093f4SDimitry Andric 22480093f4SDimitry Andric using namespace llvm; 23480093f4SDimitry Andric 24480093f4SDimitry Andric #define DEBUG_TYPE "ve" 25480093f4SDimitry Andric 26e8d8bef9SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVETarget() { 27480093f4SDimitry Andric // Register the target. 28480093f4SDimitry Andric RegisterTargetMachine<VETargetMachine> X(getTheVETarget()); 29480093f4SDimitry Andric } 30480093f4SDimitry Andric 31480093f4SDimitry Andric static std::string computeDataLayout(const Triple &T) { 32480093f4SDimitry Andric // Aurora VE is little endian 33480093f4SDimitry Andric std::string Ret = "e"; 34480093f4SDimitry Andric 35480093f4SDimitry Andric // Use ELF mangling 36480093f4SDimitry Andric Ret += "-m:e"; 37480093f4SDimitry Andric 38480093f4SDimitry Andric // Alignments for 64 bit integers. 39480093f4SDimitry Andric Ret += "-i64:64"; 40480093f4SDimitry Andric 41480093f4SDimitry Andric // VE supports 32 bit and 64 bits integer on registers 42480093f4SDimitry Andric Ret += "-n32:64"; 43480093f4SDimitry Andric 445ffd83dbSDimitry Andric // Stack alignment is 128 bits 455ffd83dbSDimitry Andric Ret += "-S128"; 46480093f4SDimitry Andric 47e8d8bef9SDimitry Andric // Vector alignments are 64 bits 48e8d8bef9SDimitry Andric // Need to define all of them. Otherwise, each alignment becomes 49e8d8bef9SDimitry Andric // the size of each data by default. 50e8d8bef9SDimitry Andric Ret += "-v64:64:64"; // for v2f32 51e8d8bef9SDimitry Andric Ret += "-v128:64:64"; 52e8d8bef9SDimitry Andric Ret += "-v256:64:64"; 53e8d8bef9SDimitry Andric Ret += "-v512:64:64"; 54e8d8bef9SDimitry Andric Ret += "-v1024:64:64"; 55e8d8bef9SDimitry Andric Ret += "-v2048:64:64"; 56e8d8bef9SDimitry Andric Ret += "-v4096:64:64"; 57e8d8bef9SDimitry Andric Ret += "-v8192:64:64"; 58e8d8bef9SDimitry Andric Ret += "-v16384:64:64"; // for v256f64 59e8d8bef9SDimitry Andric 60480093f4SDimitry Andric return Ret; 61480093f4SDimitry Andric } 62480093f4SDimitry Andric 63480093f4SDimitry Andric static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) { 64e8d8bef9SDimitry Andric return RM.getValueOr(Reloc::Static); 65480093f4SDimitry Andric } 66480093f4SDimitry Andric 67480093f4SDimitry Andric class VEELFTargetObjectFile : public TargetLoweringObjectFileELF { 68480093f4SDimitry Andric void Initialize(MCContext &Ctx, const TargetMachine &TM) override { 69480093f4SDimitry Andric TargetLoweringObjectFileELF::Initialize(Ctx, TM); 70480093f4SDimitry Andric InitializeELF(TM.Options.UseInitArray); 71480093f4SDimitry Andric } 72480093f4SDimitry Andric }; 73480093f4SDimitry Andric 74480093f4SDimitry Andric static std::unique_ptr<TargetLoweringObjectFile> createTLOF() { 75480093f4SDimitry Andric return std::make_unique<VEELFTargetObjectFile>(); 76480093f4SDimitry Andric } 77480093f4SDimitry Andric 78480093f4SDimitry Andric /// Create an Aurora VE architecture model 79480093f4SDimitry Andric VETargetMachine::VETargetMachine(const Target &T, const Triple &TT, 80480093f4SDimitry Andric StringRef CPU, StringRef FS, 81480093f4SDimitry Andric const TargetOptions &Options, 82480093f4SDimitry Andric Optional<Reloc::Model> RM, 83480093f4SDimitry Andric Optional<CodeModel::Model> CM, 84480093f4SDimitry Andric CodeGenOpt::Level OL, bool JIT) 85480093f4SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, 86480093f4SDimitry Andric getEffectiveRelocModel(RM), 87480093f4SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Small), OL), 885ffd83dbSDimitry Andric TLOF(createTLOF()), 895ffd83dbSDimitry Andric Subtarget(TT, std::string(CPU), std::string(FS), *this) { 90480093f4SDimitry Andric initAsmInfo(); 91480093f4SDimitry Andric } 92480093f4SDimitry Andric 93480093f4SDimitry Andric VETargetMachine::~VETargetMachine() {} 94480093f4SDimitry Andric 95480093f4SDimitry Andric TargetTransformInfo VETargetMachine::getTargetTransformInfo(const Function &F) { 96480093f4SDimitry Andric return TargetTransformInfo(VETTIImpl(this, F)); 97480093f4SDimitry Andric } 98480093f4SDimitry Andric 99480093f4SDimitry Andric namespace { 100480093f4SDimitry Andric /// VE Code Generator Pass Configuration Options. 101480093f4SDimitry Andric class VEPassConfig : public TargetPassConfig { 102480093f4SDimitry Andric public: 103480093f4SDimitry Andric VEPassConfig(VETargetMachine &TM, PassManagerBase &PM) 104480093f4SDimitry Andric : TargetPassConfig(TM, PM) {} 105480093f4SDimitry Andric 106480093f4SDimitry Andric VETargetMachine &getVETargetMachine() const { 107480093f4SDimitry Andric return getTM<VETargetMachine>(); 108480093f4SDimitry Andric } 109480093f4SDimitry Andric 110e8d8bef9SDimitry Andric void addIRPasses() override; 111480093f4SDimitry Andric bool addInstSelector() override; 112e8d8bef9SDimitry Andric void addPreEmitPass() override; 113480093f4SDimitry Andric }; 114480093f4SDimitry Andric } // namespace 115480093f4SDimitry Andric 116480093f4SDimitry Andric TargetPassConfig *VETargetMachine::createPassConfig(PassManagerBase &PM) { 117480093f4SDimitry Andric return new VEPassConfig(*this, PM); 118480093f4SDimitry Andric } 119480093f4SDimitry Andric 120e8d8bef9SDimitry Andric void VEPassConfig::addIRPasses() { 121e8d8bef9SDimitry Andric // VE requires atomic expand pass. 122e8d8bef9SDimitry Andric addPass(createAtomicExpandPass()); 123e8d8bef9SDimitry Andric TargetPassConfig::addIRPasses(); 124e8d8bef9SDimitry Andric } 125e8d8bef9SDimitry Andric 126480093f4SDimitry Andric bool VEPassConfig::addInstSelector() { 127480093f4SDimitry Andric addPass(createVEISelDag(getVETargetMachine())); 128480093f4SDimitry Andric return false; 129480093f4SDimitry Andric } 130e8d8bef9SDimitry Andric 131e8d8bef9SDimitry Andric void VEPassConfig::addPreEmitPass() { 132e8d8bef9SDimitry Andric // LVLGen should be called after scheduling and register allocation 133e8d8bef9SDimitry Andric addPass(createLVLGenPass()); 134e8d8bef9SDimitry Andric } 135