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