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-exception 6 // 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 15 using namespace llvm; 16 17 #define DEBUG_TYPE "lvl-gen" 18 19 namespace { 20 struct 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 }; 32 char LVLGen::ID = 0; 33 34 } // end of anonymous namespace 35 36 FunctionPass *llvm::createLVLGenPass() { return new LVLGen; } 37 38 int 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 when 49 // this MI does not have a vector length. 50 unsigned 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 58 bool 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 VL 70 // register. We would like to reuse VL register as much as possible. We 71 // also would like to keep the number of LEA instructions as fewer as 72 // possible. Therefore, we use a regular scalar register to hold immediate 73 // values to load VL register. And try to reuse identical scalar registers 74 // 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 value 98 // 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 115 bool 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