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