xref: /llvm-project/llvm/lib/Target/Hexagon/HexagonPeephole.cpp (revision 7e8bc5cf77bdda9e32b984b3fa91953361f24abb)
1 //===-- HexagonPeephole.cpp - Hexagon Peephole Optimiztions ---------------===//
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(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(true),
69                       cl::desc("Disable Optimization of extensions to i64."));
70 
71 namespace llvm {
72   FunctionPass *createHexagonPeephole();
73   void initializeHexagonPeepholePass(PassRegistry&);
74 }
75 
76 namespace {
77   struct HexagonPeephole : public MachineFunctionPass {
78     const HexagonInstrInfo    *QII;
79     const HexagonRegisterInfo *QRI;
80     const MachineRegisterInfo *MRI;
81 
82   public:
83     static char ID;
84     HexagonPeephole() : MachineFunctionPass(ID) {
85       initializeHexagonPeepholePass(*PassRegistry::getPassRegistry());
86     }
87 
88     bool runOnMachineFunction(MachineFunction &MF) override;
89 
90     StringRef getPassName() const override {
91       return "Hexagon optimize redundant zero and size extends";
92     }
93 
94     void getAnalysisUsage(AnalysisUsage &AU) const override {
95       MachineFunctionPass::getAnalysisUsage(AU);
96     }
97   };
98 }
99 
100 char HexagonPeephole::ID = 0;
101 
102 INITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole",
103                 false, false)
104 
105 bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) {
106   if (skipFunction(MF.getFunction()))
107     return false;
108 
109   QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
110   QRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
111   MRI = &MF.getRegInfo();
112 
113   DenseMap<unsigned, unsigned> PeepholeMap;
114   DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap;
115 
116   if (DisableHexagonPeephole) return false;
117 
118   // Loop over all of the basic blocks.
119   for (MachineBasicBlock &MBB : MF) {
120     PeepholeMap.clear();
121     PeepholeDoubleRegsMap.clear();
122 
123     // Traverse the basic block.
124     for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
125       // Look for sign extends:
126       // %170 = SXTW %166
127       if (!DisableOptSZExt && MI.getOpcode() == Hexagon::A2_sxtw) {
128         assert(MI.getNumOperands() == 2);
129         MachineOperand &Dst = MI.getOperand(0);
130         MachineOperand &Src = MI.getOperand(1);
131         Register DstReg = Dst.getReg();
132         Register SrcReg = Src.getReg();
133         // Just handle virtual registers.
134         if (DstReg.isVirtual() && SrcReg.isVirtual()) {
135           // Map the following:
136           // %170 = SXTW %166
137           // PeepholeMap[170] = %166
138           PeepholeMap[DstReg] = SrcReg;
139         }
140       }
141 
142       // Look for  %170 = COMBINE_ir_V4 (0, %169)
143       // %170:DoublRegs, %169:IntRegs
144       if (!DisableOptExtTo64 && MI.getOpcode() == Hexagon::A4_combineir) {
145         assert(MI.getNumOperands() == 3);
146         MachineOperand &Dst = MI.getOperand(0);
147         MachineOperand &Src1 = MI.getOperand(1);
148         MachineOperand &Src2 = MI.getOperand(2);
149         if (Src1.getImm() != 0)
150           continue;
151         Register DstReg = Dst.getReg();
152         Register SrcReg = Src2.getReg();
153         PeepholeMap[DstReg] = SrcReg;
154       }
155 
156       // Look for this sequence below
157       // %DoubleReg1 = LSRd_ri %DoubleReg0, 32
158       // %IntReg = COPY %DoubleReg1:isub_lo.
159       // and convert into
160       // %IntReg = COPY %DoubleReg0:isub_hi.
161       if (MI.getOpcode() == Hexagon::S2_lsr_i_p) {
162         assert(MI.getNumOperands() == 3);
163         MachineOperand &Dst = MI.getOperand(0);
164         MachineOperand &Src1 = MI.getOperand(1);
165         MachineOperand &Src2 = MI.getOperand(2);
166         if (Src2.getImm() != 32)
167           continue;
168         Register DstReg = Dst.getReg();
169         Register SrcReg = Src1.getReg();
170         PeepholeDoubleRegsMap[DstReg] =
171           std::make_pair(*&SrcReg, Hexagon::isub_hi);
172       }
173 
174       // Look for P=NOT(P).
175       if (!DisablePNotP && MI.getOpcode() == Hexagon::C2_not) {
176         assert(MI.getNumOperands() == 2);
177         MachineOperand &Dst = MI.getOperand(0);
178         MachineOperand &Src = MI.getOperand(1);
179         Register DstReg = Dst.getReg();
180         Register SrcReg = Src.getReg();
181         // Just handle virtual registers.
182         if (DstReg.isVirtual() && SrcReg.isVirtual()) {
183           // Map the following:
184           // %170 = NOT_xx %166
185           // PeepholeMap[170] = %166
186           PeepholeMap[DstReg] = SrcReg;
187         }
188       }
189 
190       // Look for copy:
191       // %176 = COPY %170:isub_lo
192       if (!DisableOptSZExt && MI.isCopy()) {
193         assert(MI.getNumOperands() == 2);
194         MachineOperand &Dst = MI.getOperand(0);
195         MachineOperand &Src = MI.getOperand(1);
196 
197         // Make sure we are copying the lower 32 bits.
198         if (Src.getSubReg() != Hexagon::isub_lo)
199           continue;
200 
201         Register DstReg = Dst.getReg();
202         Register SrcReg = Src.getReg();
203         if (DstReg.isVirtual() && SrcReg.isVirtual()) {
204           // Try to find in the map.
205           if (unsigned PeepholeSrc = PeepholeMap.lookup(SrcReg)) {
206             // Change the 1st operand.
207             MI.removeOperand(1);
208             MI.addOperand(MachineOperand::CreateReg(PeepholeSrc, false));
209           } else  {
210             DenseMap<unsigned, std::pair<unsigned, unsigned> >::iterator DI =
211               PeepholeDoubleRegsMap.find(SrcReg);
212             if (DI != PeepholeDoubleRegsMap.end()) {
213               std::pair<unsigned,unsigned> PeepholeSrc = DI->second;
214               MI.removeOperand(1);
215               MI.addOperand(MachineOperand::CreateReg(
216                   PeepholeSrc.first, false /*isDef*/, false /*isImp*/,
217                   false /*isKill*/, false /*isDead*/, false /*isUndef*/,
218                   false /*isEarlyClobber*/, PeepholeSrc.second));
219             }
220           }
221         }
222       }
223 
224       // Look for Predicated instructions.
225       if (!DisablePNotP) {
226         bool Done = false;
227         if (QII->isPredicated(MI)) {
228           MachineOperand &Op0 = MI.getOperand(0);
229           Register Reg0 = Op0.getReg();
230           const TargetRegisterClass *RC0 = MRI->getRegClass(Reg0);
231           if (RC0->getID() == Hexagon::PredRegsRegClassID) {
232             // Handle instructions that have a prediate register in op0
233             // (most cases of predicable instructions).
234             if (Reg0.isVirtual()) {
235               // Try to find in the map.
236               if (unsigned PeepholeSrc = PeepholeMap.lookup(Reg0)) {
237                 // Change the 1st operand and, flip the opcode.
238                 MI.getOperand(0).setReg(PeepholeSrc);
239                 MRI->clearKillFlags(PeepholeSrc);
240                 int NewOp = QII->getInvertedPredicatedOpcode(MI.getOpcode());
241                 MI.setDesc(QII->get(NewOp));
242                 Done = true;
243               }
244             }
245           }
246         }
247 
248         if (!Done) {
249           // Handle special instructions.
250           unsigned Op = MI.getOpcode();
251           unsigned NewOp = 0;
252           unsigned PR = 1, S1 = 2, S2 = 3;   // Operand indices.
253 
254           switch (Op) {
255             case Hexagon::C2_mux:
256             case Hexagon::C2_muxii:
257               NewOp = Op;
258               break;
259             case Hexagon::C2_muxri:
260               NewOp = Hexagon::C2_muxir;
261               break;
262             case Hexagon::C2_muxir:
263               NewOp = Hexagon::C2_muxri;
264               break;
265           }
266           if (NewOp) {
267             Register PSrc = MI.getOperand(PR).getReg();
268             if (unsigned POrig = PeepholeMap.lookup(PSrc)) {
269               BuildMI(MBB, MI.getIterator(), MI.getDebugLoc(), QII->get(NewOp),
270                       MI.getOperand(0).getReg())
271                   .addReg(POrig)
272                   .add(MI.getOperand(S2))
273                   .add(MI.getOperand(S1));
274               MRI->clearKillFlags(POrig);
275               MI.eraseFromParent();
276             }
277           } // if (NewOp)
278         } // if (!Done)
279 
280       } // if (!DisablePNotP)
281 
282     } // Instruction
283   } // Basic Block
284   return true;
285 }
286 
287 FunctionPass *llvm::createHexagonPeephole() {
288   return new HexagonPeephole();
289 }
290