xref: /llvm-project/llvm/lib/Target/VE/LVLGen.cpp (revision ed8019d9fbed2e6a6b08f8f73e9fa54a24f3ed52)
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