| //===-- LVLGen.cpp - LVL instruction generator ----------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "VE.h" |
| #include "VESubtarget.h" |
| #include "llvm/CodeGen/MachineFunctionPass.h" |
| #include "llvm/CodeGen/MachineInstrBuilder.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/CodeGen/TargetInstrInfo.h" |
| #include "llvm/Target/TargetMachine.h" |
| |
| using namespace llvm; |
| |
| #define DEBUG_TYPE "lvl-gen" |
| |
| namespace { |
| struct LVLGen : public MachineFunctionPass { |
| const TargetInstrInfo *TII; |
| const TargetRegisterInfo *TRI; |
| |
| static char ID; |
| LVLGen() : MachineFunctionPass(ID) {} |
| bool runOnMachineBasicBlock(MachineBasicBlock &MBB); |
| bool runOnMachineFunction(MachineFunction &F) override; |
| |
| unsigned getVL(const MachineInstr &MI); |
| int getVLIndex(unsigned Opcode); |
| }; |
| char LVLGen::ID = 0; |
| |
| } // end of anonymous namespace |
| |
| FunctionPass *llvm::createLVLGenPass() { return new LVLGen; } |
| |
| int LVLGen::getVLIndex(unsigned Opcode) { |
| const MCInstrDesc &MCID = TII->get(Opcode); |
| |
| // If an instruction has VLIndex information, return it. |
| if (HAS_VLINDEX(MCID.TSFlags)) |
| return GET_VLINDEX(MCID.TSFlags); |
| |
| return -1; |
| } |
| |
| // returns a register holding a vector length. NoRegister is returned when |
| // this MI does not have a vector length. |
| unsigned LVLGen::getVL(const MachineInstr &MI) { |
| int Index = getVLIndex(MI.getOpcode()); |
| if (Index >= 0) |
| return MI.getOperand(Index).getReg(); |
| |
| return VE::NoRegister; |
| } |
| |
| bool LVLGen::runOnMachineBasicBlock(MachineBasicBlock &MBB) { |
| #define RegName(no) \ |
| (MBB.getParent()->getSubtarget<VESubtarget>().getRegisterInfo()->getName(no)) |
| |
| bool Changed = false; |
| bool HasRegForVL = false; |
| unsigned RegForVL; |
| |
| for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { |
| MachineBasicBlock::iterator MI = I; |
| |
| // Check whether MI uses a vector length operand. If so, we prepare for VL |
| // register. We would like to reuse VL register as much as possible. We |
| // also would like to keep the number of LEA instructions as fewer as |
| // possible. Therefore, we use a regular scalar register to hold immediate |
| // values to load VL register. And try to reuse identical scalar registers |
| // to avoid new LVLr instructions as much as possible. |
| unsigned Reg = getVL(*MI); |
| if (Reg != VE::NoRegister) { |
| LLVM_DEBUG(dbgs() << "Vector instruction found: "); |
| LLVM_DEBUG(MI->dump()); |
| LLVM_DEBUG(dbgs() << "Vector length is " << RegName(Reg) << ". "); |
| LLVM_DEBUG(dbgs() << "Current VL is " |
| << (HasRegForVL ? RegName(RegForVL) : "unknown") |
| << ". "); |
| |
| if (!HasRegForVL || RegForVL != Reg) { |
| // Use VL, but a different value in a different scalar register. |
| // So, generate new LVL instruction just before the current instruction. |
| LLVM_DEBUG(dbgs() << "Generate a LVL instruction to load " |
| << RegName(Reg) << ".\n"); |
| BuildMI(MBB, I, MI->getDebugLoc(), TII->get(VE::LVLr)).addReg(Reg); |
| HasRegForVL = true; |
| RegForVL = Reg; |
| Changed = true; |
| } else { |
| LLVM_DEBUG(dbgs() << "Reuse current VL.\n"); |
| } |
| } |
| // Check the update of a given scalar register holding an immediate value |
| // for VL register. Also, a call doesn't preserve VL register. |
| if (HasRegForVL) { |
| if (MI->definesRegister(RegForVL, TRI) || |
| MI->modifiesRegister(RegForVL, TRI) || |
| MI->killsRegister(RegForVL, TRI) || MI->isCall()) { |
| // The latest VL is needed to be updated, so disable HasRegForVL. |
| LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is needed to be updated: "); |
| LLVM_DEBUG(MI->dump()); |
| HasRegForVL = false; |
| } |
| } |
| |
| ++I; |
| } |
| return Changed; |
| } |
| |
| bool LVLGen::runOnMachineFunction(MachineFunction &F) { |
| LLVM_DEBUG(dbgs() << "********** Begin LVLGen **********\n"); |
| LLVM_DEBUG(dbgs() << "********** Function: " << F.getName() << '\n'); |
| LLVM_DEBUG(F.dump()); |
| |
| bool Changed = false; |
| |
| const VESubtarget &Subtarget = F.getSubtarget<VESubtarget>(); |
| TII = Subtarget.getInstrInfo(); |
| TRI = Subtarget.getRegisterInfo(); |
| |
| for (MachineFunction::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) |
| Changed |= runOnMachineBasicBlock(*FI); |
| |
| if (Changed) { |
| LLVM_DEBUG(dbgs() << "\n"); |
| LLVM_DEBUG(F.dump()); |
| } |
| LLVM_DEBUG(dbgs() << "********** End LVLGen **********\n"); |
| return Changed; |
| } |