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/MachineRegisterInfo.h" 14 #include "llvm/CodeGen/TargetInstrInfo.h" 15 #include "llvm/Target/TargetMachine.h" 16 17 using namespace llvm; 18 19 #define DEBUG_TYPE "lvl-gen" 20 21 namespace { 22 struct LVLGen : public MachineFunctionPass { 23 const TargetInstrInfo *TII; 24 const TargetRegisterInfo *TRI; 25 26 static char ID; 27 LVLGen() : MachineFunctionPass(ID) {} 28 bool runOnMachineBasicBlock(MachineBasicBlock &MBB); 29 bool runOnMachineFunction(MachineFunction &F) override; 30 31 unsigned getVL(const MachineInstr &MI); 32 int getVLIndex(unsigned Opcode); 33 }; 34 char LVLGen::ID = 0; 35 36 } // end of anonymous namespace 37 38 FunctionPass *llvm::createLVLGenPass() { return new LVLGen; } 39 40 int LVLGen::getVLIndex(unsigned Opcode) { 41 const MCInstrDesc &MCID = TII->get(Opcode); 42 43 // If an instruction has VLIndex information, return it. 44 if (HAS_VLINDEX(MCID.TSFlags)) 45 return GET_VLINDEX(MCID.TSFlags); 46 47 return -1; 48 } 49 50 // returns a register holding a vector length. NoRegister is returned when 51 // this MI does not have a vector length. 52 unsigned LVLGen::getVL(const MachineInstr &MI) { 53 int Index = getVLIndex(MI.getOpcode()); 54 if (Index >= 0) 55 return MI.getOperand(Index).getReg(); 56 57 return VE::NoRegister; 58 } 59 60 bool LVLGen::runOnMachineBasicBlock(MachineBasicBlock &MBB) { 61 #define RegName(no) \ 62 (MBB.getParent()->getSubtarget<VESubtarget>().getRegisterInfo()->getName(no)) 63 64 bool Changed = false; 65 bool HasRegForVL = false; 66 unsigned RegForVL; 67 68 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { 69 MachineBasicBlock::iterator MI = I; 70 71 unsigned Reg = getVL(*MI); 72 if (Reg != VE::NoRegister) { 73 LLVM_DEBUG(dbgs() << "Vector instruction found: "); 74 LLVM_DEBUG(MI->dump()); 75 LLVM_DEBUG(dbgs() << "Vector length is " << RegName(Reg) << ". "); 76 LLVM_DEBUG(dbgs() << "Current VL is " 77 << (HasRegForVL ? RegName(RegForVL) : "unknown") 78 << ". "); 79 80 if (!HasRegForVL || RegForVL != Reg) { 81 LLVM_DEBUG(dbgs() << "Generate a LVL instruction to load " 82 << RegName(Reg) << ".\n"); 83 BuildMI(MBB, I, MI->getDebugLoc(), TII->get(VE::LVLr)).addReg(Reg); 84 HasRegForVL = true; 85 RegForVL = Reg; 86 Changed = true; 87 } else { 88 LLVM_DEBUG(dbgs() << "Reuse current VL.\n"); 89 } 90 } else if (HasRegForVL) { 91 // Old VL is overwritten, so disable HasRegForVL. 92 if (MI->findRegisterDefOperandIdx(RegForVL, false, false, TRI) != -1) { 93 LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is killed: "); 94 LLVM_DEBUG(MI->dump()); 95 HasRegForVL = false; 96 } 97 } 98 if (HasRegForVL) { 99 // The latest VL is killed, so disable HasRegForVL. 100 if (MI->killsRegister(RegForVL, TRI)) { 101 LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is killed: "); 102 LLVM_DEBUG(MI->dump()); 103 HasRegForVL = false; 104 } 105 } 106 107 ++I; 108 } 109 return Changed; 110 } 111 112 bool LVLGen::runOnMachineFunction(MachineFunction &F) { 113 LLVM_DEBUG(dbgs() << "********** Begin LVLGen **********\n"); 114 LLVM_DEBUG(dbgs() << "********** Function: " << F.getName() << '\n'); 115 LLVM_DEBUG(F.dump()); 116 117 bool Changed = false; 118 119 const VESubtarget &Subtarget = F.getSubtarget<VESubtarget>(); 120 TII = Subtarget.getInstrInfo(); 121 TRI = Subtarget.getRegisterInfo(); 122 123 for (MachineFunction::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) 124 Changed |= runOnMachineBasicBlock(*FI); 125 126 if (Changed) { 127 LLVM_DEBUG(dbgs() << "\n"); 128 LLVM_DEBUG(F.dump()); 129 } 130 LLVM_DEBUG(dbgs() << "********** End LVLGen **********\n"); 131 return Changed; 132 } 133