1 | //===-- HexagonPeephole.cpp - Hexagon Peephole Optimizations --------------===// |
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 | // This peephole pass optimizes in the following cases. |
8 | // 1. Optimizes redundant sign extends for the following case |
9 | // Transform the following pattern |
10 | // %170 = SXTW %166 |
11 | // ... |
12 | // %176 = COPY %170:isub_lo |
13 | // |
14 | // Into |
15 | // %176 = COPY %166 |
16 | // |
17 | // 2. Optimizes redundant negation of predicates. |
18 | // %15 = CMPGTrr %6, %2 |
19 | // ... |
20 | // %16 = NOT_p killed %15 |
21 | // ... |
22 | // JMP_c killed %16, <%bb.1>, implicit dead %pc |
23 | // |
24 | // Into |
25 | // %15 = CMPGTrr %6, %2; |
26 | // ... |
27 | // JMP_cNot killed %15, <%bb.1>, implicit dead %pc; |
28 | // |
29 | // Note: The peephole pass makes the instrucstions like |
30 | // %170 = SXTW %166 or %16 = NOT_p killed %15 |
31 | // redundant and relies on some form of dead removal instructions, like |
32 | // DCE or DIE to actually eliminate them. |
33 | |
34 | //===----------------------------------------------------------------------===// |
35 | |
36 | #include "Hexagon.h" |
37 | #include "HexagonTargetMachine.h" |
38 | #include "llvm/ADT/DenseMap.h" |
39 | #include "llvm/ADT/Statistic.h" |
40 | #include "llvm/CodeGen/MachineFunction.h" |
41 | #include "llvm/CodeGen/MachineFunctionPass.h" |
42 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
43 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
44 | #include "llvm/CodeGen/Passes.h" |
45 | #include "llvm/CodeGen/TargetInstrInfo.h" |
46 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
47 | #include "llvm/Pass.h" |
48 | #include "llvm/Support/CommandLine.h" |
49 | #include "llvm/Target/TargetMachine.h" |
50 | |
51 | using namespace llvm; |
52 | |
53 | #define DEBUG_TYPE "hexagon-peephole" |
54 | |
55 | static cl::opt<bool> |
56 | DisableHexagonPeephole("disable-hexagon-peephole" , cl::Hidden, |
57 | cl::desc("Disable Peephole Optimization" )); |
58 | |
59 | static cl::opt<bool> DisablePNotP("disable-hexagon-pnotp" , cl::Hidden, |
60 | cl::desc("Disable Optimization of PNotP" )); |
61 | |
62 | static cl::opt<bool> |
63 | DisableOptSZExt("disable-hexagon-optszext" , cl::Hidden, cl::init(Val: true), |
64 | cl::desc("Disable Optimization of Sign/Zero Extends" )); |
65 | |
66 | static cl::opt<bool> |
67 | DisableOptExtTo64("disable-hexagon-opt-ext-to-64" , cl::Hidden, |
68 | cl::init(Val: true), |
69 | cl::desc("Disable Optimization of extensions to i64." )); |
70 | |
71 | namespace { |
72 | struct HexagonPeephole : public MachineFunctionPass { |
73 | const HexagonInstrInfo *QII; |
74 | const HexagonRegisterInfo *QRI; |
75 | const MachineRegisterInfo *MRI; |
76 | |
77 | public: |
78 | static char ID; |
79 | HexagonPeephole() : MachineFunctionPass(ID) {} |
80 | |
81 | bool runOnMachineFunction(MachineFunction &MF) override; |
82 | |
83 | StringRef getPassName() const override { |
84 | return "Hexagon optimize redundant zero and size extends" ; |
85 | } |
86 | |
87 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
88 | MachineFunctionPass::getAnalysisUsage(AU); |
89 | } |
90 | }; |
91 | } |
92 | |
93 | char HexagonPeephole::ID = 0; |
94 | |
95 | INITIALIZE_PASS(HexagonPeephole, "hexagon-peephole" , "Hexagon Peephole" , |
96 | false, false) |
97 | |
98 | bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) { |
99 | if (skipFunction(F: MF.getFunction())) |
100 | return false; |
101 | |
102 | QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); |
103 | QRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); |
104 | MRI = &MF.getRegInfo(); |
105 | |
106 | DenseMap<unsigned, unsigned> PeepholeMap; |
107 | DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap; |
108 | |
109 | if (DisableHexagonPeephole) return false; |
110 | |
111 | // Loop over all of the basic blocks. |
112 | for (MachineBasicBlock &MBB : MF) { |
113 | PeepholeMap.clear(); |
114 | PeepholeDoubleRegsMap.clear(); |
115 | |
116 | // Traverse the basic block. |
117 | for (MachineInstr &MI : llvm::make_early_inc_range(Range&: MBB)) { |
118 | // Look for sign extends: |
119 | // %170 = SXTW %166 |
120 | if (!DisableOptSZExt && MI.getOpcode() == Hexagon::A2_sxtw) { |
121 | assert(MI.getNumOperands() == 2); |
122 | MachineOperand &Dst = MI.getOperand(i: 0); |
123 | MachineOperand &Src = MI.getOperand(i: 1); |
124 | Register DstReg = Dst.getReg(); |
125 | Register SrcReg = Src.getReg(); |
126 | // Just handle virtual registers. |
127 | if (DstReg.isVirtual() && SrcReg.isVirtual()) { |
128 | // Map the following: |
129 | // %170 = SXTW %166 |
130 | // PeepholeMap[170] = %166 |
131 | PeepholeMap[DstReg] = SrcReg; |
132 | } |
133 | } |
134 | |
135 | // Look for %170 = COMBINE_ir_V4 (0, %169) |
136 | // %170:DoublRegs, %169:IntRegs |
137 | if (!DisableOptExtTo64 && MI.getOpcode() == Hexagon::A4_combineir) { |
138 | assert(MI.getNumOperands() == 3); |
139 | MachineOperand &Dst = MI.getOperand(i: 0); |
140 | MachineOperand &Src1 = MI.getOperand(i: 1); |
141 | MachineOperand &Src2 = MI.getOperand(i: 2); |
142 | if (Src1.getImm() != 0) |
143 | continue; |
144 | Register DstReg = Dst.getReg(); |
145 | Register SrcReg = Src2.getReg(); |
146 | PeepholeMap[DstReg] = SrcReg; |
147 | } |
148 | |
149 | // Look for this sequence below |
150 | // %DoubleReg1 = LSRd_ri %DoubleReg0, 32 |
151 | // %IntReg = COPY %DoubleReg1:isub_lo. |
152 | // and convert into |
153 | // %IntReg = COPY %DoubleReg0:isub_hi. |
154 | if (MI.getOpcode() == Hexagon::S2_lsr_i_p) { |
155 | assert(MI.getNumOperands() == 3); |
156 | MachineOperand &Dst = MI.getOperand(i: 0); |
157 | MachineOperand &Src1 = MI.getOperand(i: 1); |
158 | MachineOperand &Src2 = MI.getOperand(i: 2); |
159 | if (Src2.getImm() != 32) |
160 | continue; |
161 | Register DstReg = Dst.getReg(); |
162 | Register SrcReg = Src1.getReg(); |
163 | PeepholeDoubleRegsMap[DstReg] = |
164 | std::make_pair(x&: *&SrcReg, y: Hexagon::isub_hi); |
165 | } |
166 | |
167 | // Look for P=NOT(P). |
168 | if (!DisablePNotP && MI.getOpcode() == Hexagon::C2_not) { |
169 | assert(MI.getNumOperands() == 2); |
170 | MachineOperand &Dst = MI.getOperand(i: 0); |
171 | MachineOperand &Src = MI.getOperand(i: 1); |
172 | Register DstReg = Dst.getReg(); |
173 | Register SrcReg = Src.getReg(); |
174 | // Just handle virtual registers. |
175 | if (DstReg.isVirtual() && SrcReg.isVirtual()) { |
176 | // Map the following: |
177 | // %170 = NOT_xx %166 |
178 | // PeepholeMap[170] = %166 |
179 | PeepholeMap[DstReg] = SrcReg; |
180 | } |
181 | } |
182 | |
183 | // Look for copy: |
184 | // %176 = COPY %170:isub_lo |
185 | if (!DisableOptSZExt && MI.isCopy()) { |
186 | assert(MI.getNumOperands() == 2); |
187 | MachineOperand &Dst = MI.getOperand(i: 0); |
188 | MachineOperand &Src = MI.getOperand(i: 1); |
189 | |
190 | // Make sure we are copying the lower 32 bits. |
191 | if (Src.getSubReg() != Hexagon::isub_lo) |
192 | continue; |
193 | |
194 | Register DstReg = Dst.getReg(); |
195 | Register SrcReg = Src.getReg(); |
196 | if (DstReg.isVirtual() && SrcReg.isVirtual()) { |
197 | // Try to find in the map. |
198 | if (unsigned PeepholeSrc = PeepholeMap.lookup(Val: SrcReg)) { |
199 | // Change the 1st operand. |
200 | MI.removeOperand(OpNo: 1); |
201 | MI.addOperand(Op: MachineOperand::CreateReg(Reg: PeepholeSrc, isDef: false)); |
202 | } else { |
203 | DenseMap<unsigned, std::pair<unsigned, unsigned> >::iterator DI = |
204 | PeepholeDoubleRegsMap.find(Val: SrcReg); |
205 | if (DI != PeepholeDoubleRegsMap.end()) { |
206 | std::pair<unsigned,unsigned> PeepholeSrc = DI->second; |
207 | MI.removeOperand(OpNo: 1); |
208 | MI.addOperand(Op: MachineOperand::CreateReg( |
209 | Reg: PeepholeSrc.first, isDef: false /*isDef*/, isImp: false /*isImp*/, |
210 | isKill: false /*isKill*/, isDead: false /*isDead*/, isUndef: false /*isUndef*/, |
211 | isEarlyClobber: false /*isEarlyClobber*/, SubReg: PeepholeSrc.second)); |
212 | } |
213 | } |
214 | } |
215 | } |
216 | |
217 | // Look for Predicated instructions. |
218 | if (!DisablePNotP) { |
219 | bool Done = false; |
220 | if (QII->isPredicated(MI)) { |
221 | MachineOperand &Op0 = MI.getOperand(i: 0); |
222 | Register Reg0 = Op0.getReg(); |
223 | const TargetRegisterClass *RC0 = MRI->getRegClass(Reg: Reg0); |
224 | if (RC0->getID() == Hexagon::PredRegsRegClassID) { |
225 | // Handle instructions that have a prediate register in op0 |
226 | // (most cases of predicable instructions). |
227 | if (Reg0.isVirtual()) { |
228 | // Try to find in the map. |
229 | if (unsigned PeepholeSrc = PeepholeMap.lookup(Val: Reg0)) { |
230 | // Change the 1st operand and, flip the opcode. |
231 | MI.getOperand(i: 0).setReg(PeepholeSrc); |
232 | MRI->clearKillFlags(Reg: PeepholeSrc); |
233 | int NewOp = QII->getInvertedPredicatedOpcode(Opc: MI.getOpcode()); |
234 | MI.setDesc(QII->get(Opcode: NewOp)); |
235 | Done = true; |
236 | } |
237 | } |
238 | } |
239 | } |
240 | |
241 | if (!Done) { |
242 | // Handle special instructions. |
243 | unsigned Op = MI.getOpcode(); |
244 | unsigned NewOp = 0; |
245 | unsigned PR = 1, S1 = 2, S2 = 3; // Operand indices. |
246 | |
247 | switch (Op) { |
248 | case Hexagon::C2_mux: |
249 | case Hexagon::C2_muxii: |
250 | NewOp = Op; |
251 | break; |
252 | case Hexagon::C2_muxri: |
253 | NewOp = Hexagon::C2_muxir; |
254 | break; |
255 | case Hexagon::C2_muxir: |
256 | NewOp = Hexagon::C2_muxri; |
257 | break; |
258 | } |
259 | if (NewOp) { |
260 | Register PSrc = MI.getOperand(i: PR).getReg(); |
261 | if (unsigned POrig = PeepholeMap.lookup(Val: PSrc)) { |
262 | BuildMI(BB&: MBB, I: MI.getIterator(), MIMD: MI.getDebugLoc(), MCID: QII->get(Opcode: NewOp), |
263 | DestReg: MI.getOperand(i: 0).getReg()) |
264 | .addReg(RegNo: POrig) |
265 | .add(MO: MI.getOperand(i: S2)) |
266 | .add(MO: MI.getOperand(i: S1)); |
267 | MRI->clearKillFlags(Reg: POrig); |
268 | MI.eraseFromParent(); |
269 | } |
270 | } // if (NewOp) |
271 | } // if (!Done) |
272 | |
273 | } // if (!DisablePNotP) |
274 | |
275 | } // Instruction |
276 | } // Basic Block |
277 | return true; |
278 | } |
279 | |
280 | FunctionPass *llvm::createHexagonPeephole() { |
281 | return new HexagonPeephole(); |
282 | } |
283 | |