|  | //===-- LVLGen.cpp - LVL instruction generator ----------------------------===// | 
|  | // | 
|  | // 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 "VE.h" | 
|  | #include "VESubtarget.h" | 
|  | #include "llvm/CodeGen/MachineFunctionPass.h" | 
|  | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
|  | #include "llvm/CodeGen/TargetInstrInfo.h" | 
|  | #include "llvm/Target/TargetMachine.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | #define DEBUG_TYPE "lvl-gen" | 
|  |  | 
|  | namespace { | 
|  | struct LVLGen : public MachineFunctionPass { | 
|  | const TargetInstrInfo *TII; | 
|  | const TargetRegisterInfo *TRI; | 
|  |  | 
|  | static char ID; | 
|  | LVLGen() : MachineFunctionPass(ID) {} | 
|  | bool runOnMachineBasicBlock(MachineBasicBlock &MBB); | 
|  | bool runOnMachineFunction(MachineFunction &F) override; | 
|  |  | 
|  | unsigned getVL(const MachineInstr &MI); | 
|  | int getVLIndex(unsigned Opcode); | 
|  | }; | 
|  | char LVLGen::ID = 0; | 
|  |  | 
|  | } // end of anonymous namespace | 
|  |  | 
|  | FunctionPass *llvm::createLVLGenPass() { return new LVLGen; } | 
|  |  | 
|  | int LVLGen::getVLIndex(unsigned Opcode) { | 
|  | const MCInstrDesc &MCID = TII->get(Opcode); | 
|  |  | 
|  | // If an instruction has VLIndex information, return it. | 
|  | if (HAS_VLINDEX(MCID.TSFlags)) | 
|  | return GET_VLINDEX(MCID.TSFlags); | 
|  |  | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | // returns a register holding a vector length. NoRegister is returned when | 
|  | // this MI does not have a vector length. | 
|  | unsigned LVLGen::getVL(const MachineInstr &MI) { | 
|  | int Index = getVLIndex(MI.getOpcode()); | 
|  | if (Index >= 0) | 
|  | return MI.getOperand(Index).getReg(); | 
|  |  | 
|  | return VE::NoRegister; | 
|  | } | 
|  |  | 
|  | bool LVLGen::runOnMachineBasicBlock(MachineBasicBlock &MBB) { | 
|  | #define RegName(no)                                                            \ | 
|  | (MBB.getParent()->getSubtarget<VESubtarget>().getRegisterInfo()->getName(no)) | 
|  |  | 
|  | bool Changed = false; | 
|  | bool HasRegForVL = false; | 
|  | unsigned RegForVL; | 
|  |  | 
|  | for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { | 
|  | MachineBasicBlock::iterator MI = I; | 
|  |  | 
|  | // Check whether MI uses a vector length operand.  If so, we prepare for VL | 
|  | // register.  We would like to reuse VL register as much as possible.  We | 
|  | // also would like to keep the number of LEA instructions as fewer as | 
|  | // possible.  Therefore, we use a regular scalar register to hold immediate | 
|  | // values to load VL register.  And try to reuse identical scalar registers | 
|  | // to avoid new LVLr instructions as much as possible. | 
|  | unsigned Reg = getVL(*MI); | 
|  | if (Reg != VE::NoRegister) { | 
|  | LLVM_DEBUG(dbgs() << "Vector instruction found: "); | 
|  | LLVM_DEBUG(MI->dump()); | 
|  | LLVM_DEBUG(dbgs() << "Vector length is " << RegName(Reg) << ". "); | 
|  | LLVM_DEBUG(dbgs() << "Current VL is " | 
|  | << (HasRegForVL ? RegName(RegForVL) : "unknown") | 
|  | << ". "); | 
|  |  | 
|  | if (!HasRegForVL || RegForVL != Reg) { | 
|  | // Use VL, but a different value in a different scalar register. | 
|  | // So, generate new LVL instruction just before the current instruction. | 
|  | LLVM_DEBUG(dbgs() << "Generate a LVL instruction to load " | 
|  | << RegName(Reg) << ".\n"); | 
|  | BuildMI(MBB, I, MI->getDebugLoc(), TII->get(VE::LVLr)).addReg(Reg); | 
|  | HasRegForVL = true; | 
|  | RegForVL = Reg; | 
|  | Changed = true; | 
|  | } else { | 
|  | LLVM_DEBUG(dbgs() << "Reuse current VL.\n"); | 
|  | } | 
|  | } | 
|  | // Check the update of a given scalar register holding an immediate value | 
|  | // for VL register.  Also, a call doesn't preserve VL register. | 
|  | if (HasRegForVL) { | 
|  | if (MI->definesRegister(RegForVL, TRI) || | 
|  | MI->modifiesRegister(RegForVL, TRI) || | 
|  | MI->killsRegister(RegForVL, TRI) || MI->isCall()) { | 
|  | // The latest VL is needed to be updated, so disable HasRegForVL. | 
|  | LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is needed to be updated: "); | 
|  | LLVM_DEBUG(MI->dump()); | 
|  | HasRegForVL = false; | 
|  | } | 
|  | } | 
|  |  | 
|  | ++I; | 
|  | } | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | bool LVLGen::runOnMachineFunction(MachineFunction &F) { | 
|  | LLVM_DEBUG(dbgs() << "********** Begin LVLGen **********\n"); | 
|  | LLVM_DEBUG(dbgs() << "********** Function: " << F.getName() << '\n'); | 
|  | LLVM_DEBUG(F.dump()); | 
|  |  | 
|  | bool Changed = false; | 
|  |  | 
|  | const VESubtarget &Subtarget = F.getSubtarget<VESubtarget>(); | 
|  | TII = Subtarget.getInstrInfo(); | 
|  | TRI = Subtarget.getRegisterInfo(); | 
|  |  | 
|  | for (MachineBasicBlock &MBB : F) | 
|  | Changed |= runOnMachineBasicBlock(MBB); | 
|  |  | 
|  | if (Changed) { | 
|  | LLVM_DEBUG(dbgs() << "\n"); | 
|  | LLVM_DEBUG(F.dump()); | 
|  | } | 
|  | LLVM_DEBUG(dbgs() << "********** End LVLGen **********\n"); | 
|  | return Changed; | 
|  | } |