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/MachineRegisterInfo.h" |
14 | #include "llvm/CodeGen/TargetInstrInfo.h" |
15 | #include "llvm/Target/TargetMachine.h" |
16 | |
17 | using namespace llvm; |
18 | |
19 | #define DEBUG_TYPE "lvl-gen" |
20 | |
21 | namespace { |
22 | struct LVLGen : public MachineFunctionPass { |
23 | const TargetInstrInfo *TII; |
24 | const TargetRegisterInfo *TRI; |
25 | |
26 | static char ID; |
27 | LVLGen() : MachineFunctionPass(ID) {} |
28 | bool runOnMachineBasicBlock(MachineBasicBlock &MBB); |
29 | bool runOnMachineFunction(MachineFunction &F) override; |
30 | |
31 | unsigned getVL(const MachineInstr &MI); |
32 | int getVLIndex(unsigned Opcode); |
33 | }; |
34 | char LVLGen::ID = 0; |
35 | |
36 | } // end of anonymous namespace |
37 | |
38 | FunctionPass *llvm::createLVLGenPass() { return new LVLGen; } |
39 | |
40 | int LVLGen::getVLIndex(unsigned Opcode) { |
41 | const MCInstrDesc &MCID = TII->get(Opcode); |
42 | |
43 | // If an instruction has VLIndex information, return it. |
44 | if (HAS_VLINDEX(MCID.TSFlags)) |
45 | return GET_VLINDEX(MCID.TSFlags); |
46 | |
47 | return -1; |
48 | } |
49 | |
50 | // returns a register holding a vector length. NoRegister is returned when |
51 | // this MI does not have a vector length. |
52 | unsigned LVLGen::getVL(const MachineInstr &MI) { |
53 | int Index = getVLIndex(Opcode: MI.getOpcode()); |
54 | if (Index >= 0) |
55 | return MI.getOperand(i: Index).getReg(); |
56 | |
57 | return VE::NoRegister; |
58 | } |
59 | |
60 | bool LVLGen::runOnMachineBasicBlock(MachineBasicBlock &MBB) { |
61 | #define RegName(no) \ |
62 | (MBB.getParent()->getSubtarget<VESubtarget>().getRegisterInfo()->getName(no)) |
63 | |
64 | bool Changed = false; |
65 | bool HasRegForVL = false; |
66 | unsigned RegForVL; |
67 | |
68 | for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { |
69 | MachineBasicBlock::iterator MI = I; |
70 | |
71 | // Check whether MI uses a vector length operand. If so, we prepare for VL |
72 | // register. We would like to reuse VL register as much as possible. We |
73 | // also would like to keep the number of LEA instructions as fewer as |
74 | // possible. Therefore, we use a regular scalar register to hold immediate |
75 | // values to load VL register. And try to reuse identical scalar registers |
76 | // to avoid new LVLr instructions as much as possible. |
77 | unsigned Reg = getVL(MI: *MI); |
78 | if (Reg != VE::NoRegister) { |
79 | LLVM_DEBUG(dbgs() << "Vector instruction found: " ); |
80 | LLVM_DEBUG(MI->dump()); |
81 | LLVM_DEBUG(dbgs() << "Vector length is " << RegName(Reg) << ". " ); |
82 | LLVM_DEBUG(dbgs() << "Current VL is " |
83 | << (HasRegForVL ? RegName(RegForVL) : "unknown" ) |
84 | << ". " ); |
85 | |
86 | if (!HasRegForVL || RegForVL != Reg) { |
87 | // Use VL, but a different value in a different scalar register. |
88 | // So, generate new LVL instruction just before the current instruction. |
89 | LLVM_DEBUG(dbgs() << "Generate a LVL instruction to load " |
90 | << RegName(Reg) << ".\n" ); |
91 | BuildMI(BB&: MBB, I, MIMD: MI->getDebugLoc(), MCID: TII->get(Opcode: VE::LVLr)).addReg(RegNo: Reg); |
92 | HasRegForVL = true; |
93 | RegForVL = Reg; |
94 | Changed = true; |
95 | } else { |
96 | LLVM_DEBUG(dbgs() << "Reuse current VL.\n" ); |
97 | } |
98 | } |
99 | // Check the update of a given scalar register holding an immediate value |
100 | // for VL register. Also, a call doesn't preserve VL register. |
101 | if (HasRegForVL) { |
102 | if (MI->definesRegister(Reg: RegForVL, TRI) || |
103 | MI->modifiesRegister(Reg: RegForVL, TRI) || |
104 | MI->killsRegister(Reg: RegForVL, TRI) || MI->isCall()) { |
105 | // The latest VL is needed to be updated, so disable HasRegForVL. |
106 | LLVM_DEBUG(dbgs() << RegName(RegForVL) << " is needed to be updated: " ); |
107 | LLVM_DEBUG(MI->dump()); |
108 | HasRegForVL = false; |
109 | } |
110 | } |
111 | |
112 | ++I; |
113 | } |
114 | return Changed; |
115 | } |
116 | |
117 | bool LVLGen::runOnMachineFunction(MachineFunction &F) { |
118 | LLVM_DEBUG(dbgs() << "********** Begin LVLGen **********\n" ); |
119 | LLVM_DEBUG(dbgs() << "********** Function: " << F.getName() << '\n'); |
120 | LLVM_DEBUG(F.dump()); |
121 | |
122 | bool Changed = false; |
123 | |
124 | const VESubtarget &Subtarget = F.getSubtarget<VESubtarget>(); |
125 | TII = Subtarget.getInstrInfo(); |
126 | TRI = Subtarget.getRegisterInfo(); |
127 | |
128 | for (MachineBasicBlock &MBB : F) |
129 | Changed |= runOnMachineBasicBlock(MBB); |
130 | |
131 | if (Changed) { |
132 | LLVM_DEBUG(dbgs() << "\n" ); |
133 | LLVM_DEBUG(F.dump()); |
134 | } |
135 | LLVM_DEBUG(dbgs() << "********** End LVLGen **********\n" ); |
136 | return Changed; |
137 | } |
138 | |