Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/LVLGen.cpp
35294 views
//===-- LVLGen.cpp - LVL instruction generator ----------------------------===//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//===----------------------------------------------------------------------===//78#include "VE.h"9#include "VESubtarget.h"10#include "llvm/CodeGen/MachineFunctionPass.h"11#include "llvm/CodeGen/MachineInstrBuilder.h"12#include "llvm/CodeGen/MachineRegisterInfo.h"13#include "llvm/CodeGen/TargetInstrInfo.h"14#include "llvm/Target/TargetMachine.h"1516using namespace llvm;1718#define DEBUG_TYPE "lvl-gen"1920namespace {21struct LVLGen : public MachineFunctionPass {22const TargetInstrInfo *TII;23const TargetRegisterInfo *TRI;2425static char ID;26LVLGen() : MachineFunctionPass(ID) {}27bool runOnMachineBasicBlock(MachineBasicBlock &MBB);28bool runOnMachineFunction(MachineFunction &F) override;2930unsigned getVL(const MachineInstr &MI);31int getVLIndex(unsigned Opcode);32};33char LVLGen::ID = 0;3435} // end of anonymous namespace3637FunctionPass *llvm::createLVLGenPass() { return new LVLGen; }3839int LVLGen::getVLIndex(unsigned Opcode) {40const MCInstrDesc &MCID = TII->get(Opcode);4142// If an instruction has VLIndex information, return it.43if (HAS_VLINDEX(MCID.TSFlags))44return GET_VLINDEX(MCID.TSFlags);4546return -1;47}4849// returns a register holding a vector length. NoRegister is returned when50// this MI does not have a vector length.51unsigned LVLGen::getVL(const MachineInstr &MI) {52int Index = getVLIndex(MI.getOpcode());53if (Index >= 0)54return MI.getOperand(Index).getReg();5556return VE::NoRegister;57}5859bool LVLGen::runOnMachineBasicBlock(MachineBasicBlock &MBB) {60#define RegName(no) \61(MBB.getParent()->getSubtarget<VESubtarget>().getRegisterInfo()->getName(no))6263bool Changed = false;64bool HasRegForVL = false;65unsigned RegForVL;6667for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) {68MachineBasicBlock::iterator MI = I;6970// Check whether MI uses a vector length operand. If so, we prepare for VL71// register. We would like to reuse VL register as much as possible. We72// also would like to keep the number of LEA instructions as fewer as73// possible. Therefore, we use a regular scalar register to hold immediate74// values to load VL register. And try to reuse identical scalar registers75// to avoid new LVLr instructions as much as possible.76unsigned Reg = getVL(*MI);77if (Reg != VE::NoRegister) {78LLVM_DEBUG(dbgs() << "Vector instruction found: ");79LLVM_DEBUG(MI->dump());80LLVM_DEBUG(dbgs() << "Vector length is " << RegName(Reg) << ". ");81LLVM_DEBUG(dbgs() << "Current VL is "82<< (HasRegForVL ? RegName(RegForVL) : "unknown")83<< ". ");8485if (!HasRegForVL || RegForVL != Reg) {86// Use VL, but a different value in a different scalar register.87// So, generate new LVL instruction just before the current instruction.88LLVM_DEBUG(dbgs() << "Generate a LVL instruction to load "89<< RegName(Reg) << ".\n");90BuildMI(MBB, I, MI->getDebugLoc(), TII->get(VE::LVLr)).addReg(Reg);91HasRegForVL = true;92RegForVL = Reg;93Changed = true;94} else {95LLVM_DEBUG(dbgs() << "Reuse current VL.\n");96}97}98// Check the update of a given scalar register holding an immediate value99// for VL register. Also, a call doesn't preserve VL register.100if (HasRegForVL) {101if (MI->definesRegister(RegForVL, TRI) ||102MI->modifiesRegister(RegForVL, TRI) ||103MI->killsRegister(RegForVL, TRI) || MI->isCall()) {104// The latest VL is needed to be updated, so disable HasRegForVL.105LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is needed to be updated: ");106LLVM_DEBUG(MI->dump());107HasRegForVL = false;108}109}110111++I;112}113return Changed;114}115116bool LVLGen::runOnMachineFunction(MachineFunction &F) {117LLVM_DEBUG(dbgs() << "********** Begin LVLGen **********\n");118LLVM_DEBUG(dbgs() << "********** Function: " << F.getName() << '\n');119LLVM_DEBUG(F.dump());120121bool Changed = false;122123const VESubtarget &Subtarget = F.getSubtarget<VESubtarget>();124TII = Subtarget.getInstrInfo();125TRI = Subtarget.getRegisterInfo();126127for (MachineBasicBlock &MBB : F)128Changed |= runOnMachineBasicBlock(MBB);129130if (Changed) {131LLVM_DEBUG(dbgs() << "\n");132LLVM_DEBUG(F.dump());133}134LLVM_DEBUG(dbgs() << "********** End LVLGen **********\n");135return Changed;136}137138139