11c00d096SSimon Moll //===-- LVLGen.cpp - LVL instruction generator ----------------------------===// 21c00d096SSimon Moll // 31c00d096SSimon Moll // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41c00d096SSimon Moll // See https://llvm.org/LICENSE.txt for license information. 51c00d096SSimon Moll // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61c00d096SSimon Moll // 71c00d096SSimon Moll //===----------------------------------------------------------------------===// 81c00d096SSimon Moll 91c00d096SSimon Moll #include "VE.h" 101c00d096SSimon Moll #include "VESubtarget.h" 111c00d096SSimon Moll #include "llvm/CodeGen/MachineFunctionPass.h" 121c00d096SSimon Moll #include "llvm/CodeGen/MachineInstrBuilder.h" 131c00d096SSimon Moll #include "llvm/CodeGen/TargetInstrInfo.h" 141c00d096SSimon Moll 151c00d096SSimon Moll using namespace llvm; 161c00d096SSimon Moll 171c00d096SSimon Moll #define DEBUG_TYPE "lvl-gen" 181c00d096SSimon Moll 191c00d096SSimon Moll namespace { 201c00d096SSimon Moll struct LVLGen : public MachineFunctionPass { 211c00d096SSimon Moll const TargetInstrInfo *TII; 221c00d096SSimon Moll const TargetRegisterInfo *TRI; 231c00d096SSimon Moll 241c00d096SSimon Moll static char ID; 251c00d096SSimon Moll LVLGen() : MachineFunctionPass(ID) {} 261c00d096SSimon Moll bool runOnMachineBasicBlock(MachineBasicBlock &MBB); 271c00d096SSimon Moll bool runOnMachineFunction(MachineFunction &F) override; 281c00d096SSimon Moll 291c00d096SSimon Moll unsigned getVL(const MachineInstr &MI); 301c00d096SSimon Moll int getVLIndex(unsigned Opcode); 311c00d096SSimon Moll }; 321c00d096SSimon Moll char LVLGen::ID = 0; 331c00d096SSimon Moll 341c00d096SSimon Moll } // end of anonymous namespace 351c00d096SSimon Moll 361c00d096SSimon Moll FunctionPass *llvm::createLVLGenPass() { return new LVLGen; } 371c00d096SSimon Moll 381c00d096SSimon Moll int LVLGen::getVLIndex(unsigned Opcode) { 391c00d096SSimon Moll const MCInstrDesc &MCID = TII->get(Opcode); 401c00d096SSimon Moll 411c00d096SSimon Moll // If an instruction has VLIndex information, return it. 421c00d096SSimon Moll if (HAS_VLINDEX(MCID.TSFlags)) 431c00d096SSimon Moll return GET_VLINDEX(MCID.TSFlags); 441c00d096SSimon Moll 451c00d096SSimon Moll return -1; 461c00d096SSimon Moll } 471c00d096SSimon Moll 481c00d096SSimon Moll // returns a register holding a vector length. NoRegister is returned when 491c00d096SSimon Moll // this MI does not have a vector length. 501c00d096SSimon Moll unsigned LVLGen::getVL(const MachineInstr &MI) { 511c00d096SSimon Moll int Index = getVLIndex(MI.getOpcode()); 521c00d096SSimon Moll if (Index >= 0) 531c00d096SSimon Moll return MI.getOperand(Index).getReg(); 541c00d096SSimon Moll 551c00d096SSimon Moll return VE::NoRegister; 561c00d096SSimon Moll } 571c00d096SSimon Moll 581c00d096SSimon Moll bool LVLGen::runOnMachineBasicBlock(MachineBasicBlock &MBB) { 591c00d096SSimon Moll #define RegName(no) \ 601c00d096SSimon Moll (MBB.getParent()->getSubtarget<VESubtarget>().getRegisterInfo()->getName(no)) 611c00d096SSimon Moll 621c00d096SSimon Moll bool Changed = false; 631c00d096SSimon Moll bool HasRegForVL = false; 641c00d096SSimon Moll unsigned RegForVL; 651c00d096SSimon Moll 661c00d096SSimon Moll for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { 671c00d096SSimon Moll MachineBasicBlock::iterator MI = I; 681c00d096SSimon Moll 6995ea50e4SKazushi (Jam) Marukawa // Check whether MI uses a vector length operand. If so, we prepare for VL 7095ea50e4SKazushi (Jam) Marukawa // register. We would like to reuse VL register as much as possible. We 7195ea50e4SKazushi (Jam) Marukawa // also would like to keep the number of LEA instructions as fewer as 7295ea50e4SKazushi (Jam) Marukawa // possible. Therefore, we use a regular scalar register to hold immediate 7395ea50e4SKazushi (Jam) Marukawa // values to load VL register. And try to reuse identical scalar registers 7495ea50e4SKazushi (Jam) Marukawa // to avoid new LVLr instructions as much as possible. 751c00d096SSimon Moll unsigned Reg = getVL(*MI); 761c00d096SSimon Moll if (Reg != VE::NoRegister) { 771c00d096SSimon Moll LLVM_DEBUG(dbgs() << "Vector instruction found: "); 781c00d096SSimon Moll LLVM_DEBUG(MI->dump()); 791c00d096SSimon Moll LLVM_DEBUG(dbgs() << "Vector length is " << RegName(Reg) << ". "); 801c00d096SSimon Moll LLVM_DEBUG(dbgs() << "Current VL is " 811c00d096SSimon Moll << (HasRegForVL ? RegName(RegForVL) : "unknown") 821c00d096SSimon Moll << ". "); 831c00d096SSimon Moll 841c00d096SSimon Moll if (!HasRegForVL || RegForVL != Reg) { 8595ea50e4SKazushi (Jam) Marukawa // Use VL, but a different value in a different scalar register. 8695ea50e4SKazushi (Jam) Marukawa // So, generate new LVL instruction just before the current instruction. 871c00d096SSimon Moll LLVM_DEBUG(dbgs() << "Generate a LVL instruction to load " 881c00d096SSimon Moll << RegName(Reg) << ".\n"); 891c00d096SSimon Moll BuildMI(MBB, I, MI->getDebugLoc(), TII->get(VE::LVLr)).addReg(Reg); 901c00d096SSimon Moll HasRegForVL = true; 911c00d096SSimon Moll RegForVL = Reg; 921c00d096SSimon Moll Changed = true; 931c00d096SSimon Moll } else { 941c00d096SSimon Moll LLVM_DEBUG(dbgs() << "Reuse current VL.\n"); 951c00d096SSimon Moll } 961c00d096SSimon Moll } 9795ea50e4SKazushi (Jam) Marukawa // Check the update of a given scalar register holding an immediate value 9895ea50e4SKazushi (Jam) Marukawa // for VL register. Also, a call doesn't preserve VL register. 991c00d096SSimon Moll if (HasRegForVL) { 10095ea50e4SKazushi (Jam) Marukawa if (MI->definesRegister(RegForVL, TRI) || 10195ea50e4SKazushi (Jam) Marukawa MI->modifiesRegister(RegForVL, TRI) || 10295ea50e4SKazushi (Jam) Marukawa MI->killsRegister(RegForVL, TRI) || MI->isCall()) { 10395ea50e4SKazushi (Jam) Marukawa // The latest VL is needed to be updated, so disable HasRegForVL. 10495ea50e4SKazushi (Jam) Marukawa LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is needed to be updated: "); 1051c00d096SSimon Moll LLVM_DEBUG(MI->dump()); 1061c00d096SSimon Moll HasRegForVL = false; 1071c00d096SSimon Moll } 1081c00d096SSimon Moll } 1091c00d096SSimon Moll 1101c00d096SSimon Moll ++I; 1111c00d096SSimon Moll } 1121c00d096SSimon Moll return Changed; 1131c00d096SSimon Moll } 1141c00d096SSimon Moll 1151c00d096SSimon Moll bool LVLGen::runOnMachineFunction(MachineFunction &F) { 1161c00d096SSimon Moll LLVM_DEBUG(dbgs() << "********** Begin LVLGen **********\n"); 1171c00d096SSimon Moll LLVM_DEBUG(dbgs() << "********** Function: " << F.getName() << '\n'); 1181c00d096SSimon Moll LLVM_DEBUG(F.dump()); 1191c00d096SSimon Moll 1201c00d096SSimon Moll bool Changed = false; 1211c00d096SSimon Moll 1221c00d096SSimon Moll const VESubtarget &Subtarget = F.getSubtarget<VESubtarget>(); 1231c00d096SSimon Moll TII = Subtarget.getInstrInfo(); 1241c00d096SSimon Moll TRI = Subtarget.getRegisterInfo(); 1251c00d096SSimon Moll 126*bf039a86SKazu Hirata for (MachineBasicBlock &MBB : F) 127*bf039a86SKazu Hirata Changed |= runOnMachineBasicBlock(MBB); 1281c00d096SSimon Moll 1291c00d096SSimon Moll if (Changed) { 1301c00d096SSimon Moll LLVM_DEBUG(dbgs() << "\n"); 1311c00d096SSimon Moll LLVM_DEBUG(F.dump()); 1321c00d096SSimon Moll } 1331c00d096SSimon Moll LLVM_DEBUG(dbgs() << "********** End LVLGen **********\n"); 1341c00d096SSimon Moll return Changed; 1351c00d096SSimon Moll } 136