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(Opcode: MI.getOpcode()); |
52 | if (Index >= 0) |
53 | return MI.getOperand(i: 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: *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(BB&: MBB, I, MIMD: MI->getDebugLoc(), MCID: TII->get(Opcode: VE::LVLr)).addReg(RegNo: 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(Reg: RegForVL, TRI) || |
101 | MI->modifiesRegister(Reg: RegForVL, TRI) || |
102 | MI->killsRegister(Reg: 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 | |