xref: /openbsd-src/gnu/llvm/llvm/lib/Target/VE/LVLGen.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
173471bf0Spatrick //===-- LVLGen.cpp - LVL instruction generator ----------------------------===//
273471bf0Spatrick //
373471bf0Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
473471bf0Spatrick // See https://llvm.org/LICENSE.txt for license information.
573471bf0Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
673471bf0Spatrick //
773471bf0Spatrick //===----------------------------------------------------------------------===//
873471bf0Spatrick 
973471bf0Spatrick #include "VE.h"
1073471bf0Spatrick #include "VESubtarget.h"
1173471bf0Spatrick #include "llvm/CodeGen/MachineFunctionPass.h"
1273471bf0Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
1373471bf0Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
1473471bf0Spatrick #include "llvm/CodeGen/TargetInstrInfo.h"
1573471bf0Spatrick #include "llvm/Target/TargetMachine.h"
1673471bf0Spatrick 
1773471bf0Spatrick using namespace llvm;
1873471bf0Spatrick 
1973471bf0Spatrick #define DEBUG_TYPE "lvl-gen"
2073471bf0Spatrick 
2173471bf0Spatrick namespace {
2273471bf0Spatrick struct LVLGen : public MachineFunctionPass {
2373471bf0Spatrick   const TargetInstrInfo *TII;
2473471bf0Spatrick   const TargetRegisterInfo *TRI;
2573471bf0Spatrick 
2673471bf0Spatrick   static char ID;
LVLGen__anon5c3b7d2f0111::LVLGen2773471bf0Spatrick   LVLGen() : MachineFunctionPass(ID) {}
2873471bf0Spatrick   bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
2973471bf0Spatrick   bool runOnMachineFunction(MachineFunction &F) override;
3073471bf0Spatrick 
3173471bf0Spatrick   unsigned getVL(const MachineInstr &MI);
3273471bf0Spatrick   int getVLIndex(unsigned Opcode);
3373471bf0Spatrick };
3473471bf0Spatrick char LVLGen::ID = 0;
3573471bf0Spatrick 
3673471bf0Spatrick } // end of anonymous namespace
3773471bf0Spatrick 
createLVLGenPass()3873471bf0Spatrick FunctionPass *llvm::createLVLGenPass() { return new LVLGen; }
3973471bf0Spatrick 
getVLIndex(unsigned Opcode)4073471bf0Spatrick int LVLGen::getVLIndex(unsigned Opcode) {
4173471bf0Spatrick   const MCInstrDesc &MCID = TII->get(Opcode);
4273471bf0Spatrick 
4373471bf0Spatrick   // If an instruction has VLIndex information, return it.
4473471bf0Spatrick   if (HAS_VLINDEX(MCID.TSFlags))
4573471bf0Spatrick     return GET_VLINDEX(MCID.TSFlags);
4673471bf0Spatrick 
4773471bf0Spatrick   return -1;
4873471bf0Spatrick }
4973471bf0Spatrick 
5073471bf0Spatrick // returns a register holding a vector length. NoRegister is returned when
5173471bf0Spatrick // this MI does not have a vector length.
getVL(const MachineInstr & MI)5273471bf0Spatrick unsigned LVLGen::getVL(const MachineInstr &MI) {
5373471bf0Spatrick   int Index = getVLIndex(MI.getOpcode());
5473471bf0Spatrick   if (Index >= 0)
5573471bf0Spatrick     return MI.getOperand(Index).getReg();
5673471bf0Spatrick 
5773471bf0Spatrick   return VE::NoRegister;
5873471bf0Spatrick }
5973471bf0Spatrick 
runOnMachineBasicBlock(MachineBasicBlock & MBB)6073471bf0Spatrick bool LVLGen::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
6173471bf0Spatrick #define RegName(no)                                                            \
6273471bf0Spatrick   (MBB.getParent()->getSubtarget<VESubtarget>().getRegisterInfo()->getName(no))
6373471bf0Spatrick 
6473471bf0Spatrick   bool Changed = false;
6573471bf0Spatrick   bool HasRegForVL = false;
6673471bf0Spatrick   unsigned RegForVL;
6773471bf0Spatrick 
6873471bf0Spatrick   for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) {
6973471bf0Spatrick     MachineBasicBlock::iterator MI = I;
7073471bf0Spatrick 
7173471bf0Spatrick     // Check whether MI uses a vector length operand.  If so, we prepare for VL
7273471bf0Spatrick     // register.  We would like to reuse VL register as much as possible.  We
7373471bf0Spatrick     // also would like to keep the number of LEA instructions as fewer as
7473471bf0Spatrick     // possible.  Therefore, we use a regular scalar register to hold immediate
7573471bf0Spatrick     // values to load VL register.  And try to reuse identical scalar registers
7673471bf0Spatrick     // to avoid new LVLr instructions as much as possible.
7773471bf0Spatrick     unsigned Reg = getVL(*MI);
7873471bf0Spatrick     if (Reg != VE::NoRegister) {
7973471bf0Spatrick       LLVM_DEBUG(dbgs() << "Vector instruction found: ");
8073471bf0Spatrick       LLVM_DEBUG(MI->dump());
8173471bf0Spatrick       LLVM_DEBUG(dbgs() << "Vector length is " << RegName(Reg) << ". ");
8273471bf0Spatrick       LLVM_DEBUG(dbgs() << "Current VL is "
8373471bf0Spatrick                         << (HasRegForVL ? RegName(RegForVL) : "unknown")
8473471bf0Spatrick                         << ". ");
8573471bf0Spatrick 
8673471bf0Spatrick       if (!HasRegForVL || RegForVL != Reg) {
8773471bf0Spatrick         // Use VL, but a different value in a different scalar register.
8873471bf0Spatrick         // So, generate new LVL instruction just before the current instruction.
8973471bf0Spatrick         LLVM_DEBUG(dbgs() << "Generate a LVL instruction to load "
9073471bf0Spatrick                           << RegName(Reg) << ".\n");
9173471bf0Spatrick         BuildMI(MBB, I, MI->getDebugLoc(), TII->get(VE::LVLr)).addReg(Reg);
9273471bf0Spatrick         HasRegForVL = true;
9373471bf0Spatrick         RegForVL = Reg;
9473471bf0Spatrick         Changed = true;
9573471bf0Spatrick       } else {
9673471bf0Spatrick         LLVM_DEBUG(dbgs() << "Reuse current VL.\n");
9773471bf0Spatrick       }
9873471bf0Spatrick     }
9973471bf0Spatrick     // Check the update of a given scalar register holding an immediate value
10073471bf0Spatrick     // for VL register.  Also, a call doesn't preserve VL register.
10173471bf0Spatrick     if (HasRegForVL) {
10273471bf0Spatrick       if (MI->definesRegister(RegForVL, TRI) ||
10373471bf0Spatrick           MI->modifiesRegister(RegForVL, TRI) ||
10473471bf0Spatrick           MI->killsRegister(RegForVL, TRI) || MI->isCall()) {
10573471bf0Spatrick         // The latest VL is needed to be updated, so disable HasRegForVL.
10673471bf0Spatrick         LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is needed to be updated: ");
10773471bf0Spatrick         LLVM_DEBUG(MI->dump());
10873471bf0Spatrick         HasRegForVL = false;
10973471bf0Spatrick       }
11073471bf0Spatrick     }
11173471bf0Spatrick 
11273471bf0Spatrick     ++I;
11373471bf0Spatrick   }
11473471bf0Spatrick   return Changed;
11573471bf0Spatrick }
11673471bf0Spatrick 
runOnMachineFunction(MachineFunction & F)11773471bf0Spatrick bool LVLGen::runOnMachineFunction(MachineFunction &F) {
11873471bf0Spatrick   LLVM_DEBUG(dbgs() << "********** Begin LVLGen **********\n");
11973471bf0Spatrick   LLVM_DEBUG(dbgs() << "********** Function: " << F.getName() << '\n');
12073471bf0Spatrick   LLVM_DEBUG(F.dump());
12173471bf0Spatrick 
12273471bf0Spatrick   bool Changed = false;
12373471bf0Spatrick 
12473471bf0Spatrick   const VESubtarget &Subtarget = F.getSubtarget<VESubtarget>();
12573471bf0Spatrick   TII = Subtarget.getInstrInfo();
12673471bf0Spatrick   TRI = Subtarget.getRegisterInfo();
12773471bf0Spatrick 
128*d415bd75Srobert   for (MachineBasicBlock &MBB : F)
129*d415bd75Srobert     Changed |= runOnMachineBasicBlock(MBB);
13073471bf0Spatrick 
13173471bf0Spatrick   if (Changed) {
13273471bf0Spatrick     LLVM_DEBUG(dbgs() << "\n");
13373471bf0Spatrick     LLVM_DEBUG(F.dump());
13473471bf0Spatrick   }
13573471bf0Spatrick   LLVM_DEBUG(dbgs() << "********** End LVLGen **********\n");
13673471bf0Spatrick   return Changed;
13773471bf0Spatrick }
138