136 lines · cpp
1//===-- LVLGen.cpp - LVL instruction generator ----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "VE.h"10#include "VESubtarget.h"11#include "llvm/CodeGen/MachineFunctionPass.h"12#include "llvm/CodeGen/MachineInstrBuilder.h"13#include "llvm/CodeGen/TargetInstrInfo.h"14 15using namespace llvm;16 17#define DEBUG_TYPE "lvl-gen"18 19namespace {20struct LVLGen : public MachineFunctionPass {21 const TargetInstrInfo *TII;22 const TargetRegisterInfo *TRI;23 24 static char ID;25 LVLGen() : MachineFunctionPass(ID) {}26 bool runOnMachineBasicBlock(MachineBasicBlock &MBB);27 bool runOnMachineFunction(MachineFunction &F) override;28 29 unsigned getVL(const MachineInstr &MI);30 int getVLIndex(unsigned Opcode);31};32char LVLGen::ID = 0;33 34} // end of anonymous namespace35 36FunctionPass *llvm::createLVLGenPass() { return new LVLGen; }37 38int LVLGen::getVLIndex(unsigned Opcode) {39 const MCInstrDesc &MCID = TII->get(Opcode);40 41 // If an instruction has VLIndex information, return it.42 if (HAS_VLINDEX(MCID.TSFlags))43 return GET_VLINDEX(MCID.TSFlags);44 45 return -1;46}47 48// returns a register holding a vector length. NoRegister is returned when49// this MI does not have a vector length.50unsigned LVLGen::getVL(const MachineInstr &MI) {51 int Index = getVLIndex(MI.getOpcode());52 if (Index >= 0)53 return MI.getOperand(Index).getReg();54 55 return VE::NoRegister;56}57 58bool LVLGen::runOnMachineBasicBlock(MachineBasicBlock &MBB) {59#define RegName(no) \60 (MBB.getParent()->getSubtarget<VESubtarget>().getRegisterInfo()->getName(no))61 62 bool Changed = false;63 bool HasRegForVL = false;64 unsigned RegForVL;65 66 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) {67 MachineBasicBlock::iterator MI = I;68 69 // Check whether MI uses a vector length operand. If so, we prepare for VL70 // register. We would like to reuse VL register as much as possible. We71 // also would like to keep the number of LEA instructions as fewer as72 // possible. Therefore, we use a regular scalar register to hold immediate73 // values to load VL register. And try to reuse identical scalar registers74 // to avoid new LVLr instructions as much as possible.75 unsigned Reg = getVL(*MI);76 if (Reg != VE::NoRegister) {77 LLVM_DEBUG(dbgs() << "Vector instruction found: ");78 LLVM_DEBUG(MI->dump());79 LLVM_DEBUG(dbgs() << "Vector length is " << RegName(Reg) << ". ");80 LLVM_DEBUG(dbgs() << "Current VL is "81 << (HasRegForVL ? RegName(RegForVL) : "unknown")82 << ". ");83 84 if (!HasRegForVL || RegForVL != Reg) {85 // Use VL, but a different value in a different scalar register.86 // So, generate new LVL instruction just before the current instruction.87 LLVM_DEBUG(dbgs() << "Generate a LVL instruction to load "88 << RegName(Reg) << ".\n");89 BuildMI(MBB, I, MI->getDebugLoc(), TII->get(VE::LVLr)).addReg(Reg);90 HasRegForVL = true;91 RegForVL = Reg;92 Changed = true;93 } else {94 LLVM_DEBUG(dbgs() << "Reuse current VL.\n");95 }96 }97 // Check the update of a given scalar register holding an immediate value98 // for VL register. Also, a call doesn't preserve VL register.99 if (HasRegForVL) {100 if (MI->definesRegister(RegForVL, TRI) ||101 MI->modifiesRegister(RegForVL, TRI) ||102 MI->killsRegister(RegForVL, TRI) || MI->isCall()) {103 // The latest VL is needed to be updated, so disable HasRegForVL.104 LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is needed to be updated: ");105 LLVM_DEBUG(MI->dump());106 HasRegForVL = false;107 }108 }109 110 ++I;111 }112 return Changed;113}114 115bool LVLGen::runOnMachineFunction(MachineFunction &F) {116 LLVM_DEBUG(dbgs() << "********** Begin LVLGen **********\n");117 LLVM_DEBUG(dbgs() << "********** Function: " << F.getName() << '\n');118 LLVM_DEBUG(F.dump());119 120 bool Changed = false;121 122 const VESubtarget &Subtarget = F.getSubtarget<VESubtarget>();123 TII = Subtarget.getInstrInfo();124 TRI = Subtarget.getRegisterInfo();125 126 for (MachineBasicBlock &MBB : F)127 Changed |= runOnMachineBasicBlock(MBB);128 129 if (Changed) {130 LLVM_DEBUG(dbgs() << "\n");131 LLVM_DEBUG(F.dump());132 }133 LLVM_DEBUG(dbgs() << "********** End LVLGen **********\n");134 return Changed;135}136