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