blob: 8f761d2d4805c09378eb1e714e30ac792c30d516 [file] [log] [blame]
Sirish Pande30804c22012-02-15 18:52:27 +00001//===-- HexagonPeephole.cpp - Hexagon Peephole Optimiztions ---------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Sirish Pande30804c22012-02-15 18:52:27 +00006//
7// This peephole pass optimizes in the following cases.
8// 1. Optimizes redundant sign extends for the following case
9// Transform the following pattern
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000010// %170 = SXTW %166
Sirish Pande30804c22012-02-15 18:52:27 +000011// ...
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000012// %176 = COPY %170:isub_lo
Sirish Pande30804c22012-02-15 18:52:27 +000013//
14// Into
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000015// %176 = COPY %166
Sirish Pande30804c22012-02-15 18:52:27 +000016//
17// 2. Optimizes redundant negation of predicates.
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000018// %15 = CMPGTrr %6, %2
Sirish Pande30804c22012-02-15 18:52:27 +000019// ...
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000020// %16 = NOT_p killed %15
Sirish Pande30804c22012-02-15 18:52:27 +000021// ...
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000022// JMP_c killed %16, <%bb.1>, implicit dead %pc
Sirish Pande30804c22012-02-15 18:52:27 +000023//
24// Into
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000025// %15 = CMPGTrr %6, %2;
Sirish Pande30804c22012-02-15 18:52:27 +000026// ...
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000027// JMP_cNot killed %15, <%bb.1>, implicit dead %pc;
Sirish Pande30804c22012-02-15 18:52:27 +000028//
29// Note: The peephole pass makes the instrucstions like
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000030// %170 = SXTW %166 or %16 = NOT_p killed %15
Robert Wilhelm2788d3e2013-09-28 13:42:22 +000031// redundant and relies on some form of dead removal instructions, like
Sirish Pande30804c22012-02-15 18:52:27 +000032// DCE or DIE to actually eliminate them.
33
Sirish Pande30804c22012-02-15 18:52:27 +000034//===----------------------------------------------------------------------===//
35
Craig Topperb25fda92012-03-17 18:46:09 +000036#include "Hexagon.h"
37#include "HexagonTargetMachine.h"
Sirish Pande30804c22012-02-15 18:52:27 +000038#include "llvm/ADT/DenseMap.h"
39#include "llvm/ADT/Statistic.h"
Sirish Pande30804c22012-02-15 18:52:27 +000040#include "llvm/CodeGen/MachineFunction.h"
41#include "llvm/CodeGen/MachineFunctionPass.h"
42#include "llvm/CodeGen/MachineInstrBuilder.h"
43#include "llvm/CodeGen/MachineRegisterInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000044#include "llvm/CodeGen/Passes.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000045#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000046#include "llvm/CodeGen/TargetRegisterInfo.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000047#include "llvm/IR/Constants.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000048#include "llvm/PassSupport.h"
Craig Topperb25fda92012-03-17 18:46:09 +000049#include "llvm/Support/CommandLine.h"
Sirish Pande30804c22012-02-15 18:52:27 +000050#include "llvm/Support/Debug.h"
51#include "llvm/Support/raw_ostream.h"
52#include "llvm/Target/TargetMachine.h"
Sirish Pande30804c22012-02-15 18:52:27 +000053#include <algorithm>
Sirish Pande30804c22012-02-15 18:52:27 +000054
55using namespace llvm;
56
Chandler Carruth84e68b22014-04-22 02:41:26 +000057#define DEBUG_TYPE "hexagon-peephole"
58
Sirish Pande30804c22012-02-15 18:52:27 +000059static cl::opt<bool> DisableHexagonPeephole("disable-hexagon-peephole",
60 cl::Hidden, cl::ZeroOrMore, cl::init(false),
61 cl::desc("Disable Peephole Optimization"));
62
Sirish Pande30804c22012-02-15 18:52:27 +000063static cl::opt<bool> DisablePNotP("disable-hexagon-pnotp",
64 cl::Hidden, cl::ZeroOrMore, cl::init(false),
65 cl::desc("Disable Optimization of PNotP"));
66
67static cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext",
Krzysztof Parzyszek3af70c12016-04-19 21:36:24 +000068 cl::Hidden, cl::ZeroOrMore, cl::init(true),
Sirish Pande30804c22012-02-15 18:52:27 +000069 cl::desc("Disable Optimization of Sign/Zero Extends"));
70
Pranav Bhandarkar7dda9122013-05-02 20:22:51 +000071static cl::opt<bool> DisableOptExtTo64("disable-hexagon-opt-ext-to-64",
Krzysztof Parzyszek3af70c12016-04-19 21:36:24 +000072 cl::Hidden, cl::ZeroOrMore, cl::init(true),
Pranav Bhandarkar7dda9122013-05-02 20:22:51 +000073 cl::desc("Disable Optimization of extensions to i64."));
74
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +000075namespace llvm {
Colin LeMahieu56efafc2015-06-15 19:05:35 +000076 FunctionPass *createHexagonPeephole();
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +000077 void initializeHexagonPeepholePass(PassRegistry&);
78}
79
Sirish Pande30804c22012-02-15 18:52:27 +000080namespace {
81 struct HexagonPeephole : public MachineFunctionPass {
82 const HexagonInstrInfo *QII;
83 const HexagonRegisterInfo *QRI;
84 const MachineRegisterInfo *MRI;
85
86 public:
87 static char ID;
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +000088 HexagonPeephole() : MachineFunctionPass(ID) {
89 initializeHexagonPeepholePass(*PassRegistry::getPassRegistry());
90 }
Sirish Pande30804c22012-02-15 18:52:27 +000091
Craig Topper906c2cd2014-04-29 07:58:16 +000092 bool runOnMachineFunction(MachineFunction &MF) override;
Sirish Pande30804c22012-02-15 18:52:27 +000093
Mehdi Amini117296c2016-10-01 02:56:57 +000094 StringRef getPassName() const override {
Sirish Pande30804c22012-02-15 18:52:27 +000095 return "Hexagon optimize redundant zero and size extends";
96 }
97
Craig Topper906c2cd2014-04-29 07:58:16 +000098 void getAnalysisUsage(AnalysisUsage &AU) const override {
Sirish Pande30804c22012-02-15 18:52:27 +000099 MachineFunctionPass::getAnalysisUsage(AU);
100 }
Sirish Pande30804c22012-02-15 18:52:27 +0000101 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000102}
Sirish Pande30804c22012-02-15 18:52:27 +0000103
104char HexagonPeephole::ID = 0;
105
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +0000106INITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole",
107 false, false)
Sirish Pande30804c22012-02-15 18:52:27 +0000108
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +0000109bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) {
Matthias Braunf1caa282017-12-15 22:22:58 +0000110 if (skipFunction(MF.getFunction()))
Andrew Kaylor5b444a22016-04-26 19:46:28 +0000111 return false;
112
Eric Christopherfc6de422014-08-05 02:39:49 +0000113 QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
Eric Christopherd5c235d2015-02-02 22:40:56 +0000114 QRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
Sirish Pande30804c22012-02-15 18:52:27 +0000115 MRI = &MF.getRegInfo();
116
117 DenseMap<unsigned, unsigned> PeepholeMap;
Pranav Bhandarkar823f9eb2012-09-05 16:01:40 +0000118 DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap;
Sirish Pande30804c22012-02-15 18:52:27 +0000119
120 if (DisableHexagonPeephole) return false;
121
122 // Loop over all of the basic blocks.
123 for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end();
124 MBBb != MBBe; ++MBBb) {
Duncan P. N. Exon Smitha72c6e22015-10-20 00:46:39 +0000125 MachineBasicBlock *MBB = &*MBBb;
Sirish Pande30804c22012-02-15 18:52:27 +0000126 PeepholeMap.clear();
Pranav Bhandarkar823f9eb2012-09-05 16:01:40 +0000127 PeepholeDoubleRegsMap.clear();
Sirish Pande30804c22012-02-15 18:52:27 +0000128
129 // Traverse the basic block.
Krzysztof Parzyszek5b933fe2017-06-21 21:03:34 +0000130 for (auto I = MBB->begin(), E = MBB->end(), NextI = I; I != E; I = NextI) {
131 NextI = std::next(I);
132 MachineInstr &MI = *I;
Sirish Pande30804c22012-02-15 18:52:27 +0000133 // Look for sign extends:
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +0000134 // %170 = SXTW %166
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000135 if (!DisableOptSZExt && MI.getOpcode() == Hexagon::A2_sxtw) {
136 assert(MI.getNumOperands() == 2);
137 MachineOperand &Dst = MI.getOperand(0);
138 MachineOperand &Src = MI.getOperand(1);
Sirish Pande30804c22012-02-15 18:52:27 +0000139 unsigned DstReg = Dst.getReg();
140 unsigned SrcReg = Src.getReg();
141 // Just handle virtual registers.
142 if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
143 TargetRegisterInfo::isVirtualRegister(SrcReg)) {
144 // Map the following:
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +0000145 // %170 = SXTW %166
Francis Visoiu Mistrih93ef1452017-11-30 12:12:19 +0000146 // PeepholeMap[170] = %166
Sirish Pande30804c22012-02-15 18:52:27 +0000147 PeepholeMap[DstReg] = SrcReg;
148 }
149 }
150
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +0000151 // Look for %170 = COMBINE_ir_V4 (0, %169)
Francis Visoiu Mistrih93ef1452017-11-30 12:12:19 +0000152 // %170:DoublRegs, %169:IntRegs
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000153 if (!DisableOptExtTo64 && MI.getOpcode() == Hexagon::A4_combineir) {
154 assert(MI.getNumOperands() == 3);
155 MachineOperand &Dst = MI.getOperand(0);
156 MachineOperand &Src1 = MI.getOperand(1);
157 MachineOperand &Src2 = MI.getOperand(2);
Pranav Bhandarkar7dda9122013-05-02 20:22:51 +0000158 if (Src1.getImm() != 0)
159 continue;
160 unsigned DstReg = Dst.getReg();
161 unsigned SrcReg = Src2.getReg();
162 PeepholeMap[DstReg] = SrcReg;
163 }
164
Pranav Bhandarkar823f9eb2012-09-05 16:01:40 +0000165 // Look for this sequence below
Francis Visoiu Mistrih93ef1452017-11-30 12:12:19 +0000166 // %DoubleReg1 = LSRd_ri %DoubleReg0, 32
167 // %IntReg = COPY %DoubleReg1:isub_lo.
Pranav Bhandarkar823f9eb2012-09-05 16:01:40 +0000168 // and convert into
Francis Visoiu Mistrih93ef1452017-11-30 12:12:19 +0000169 // %IntReg = COPY %DoubleReg0:isub_hi.
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000170 if (MI.getOpcode() == Hexagon::S2_lsr_i_p) {
171 assert(MI.getNumOperands() == 3);
172 MachineOperand &Dst = MI.getOperand(0);
173 MachineOperand &Src1 = MI.getOperand(1);
174 MachineOperand &Src2 = MI.getOperand(2);
Pranav Bhandarkar823f9eb2012-09-05 16:01:40 +0000175 if (Src2.getImm() != 32)
176 continue;
177 unsigned DstReg = Dst.getReg();
178 unsigned SrcReg = Src1.getReg();
179 PeepholeDoubleRegsMap[DstReg] =
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000180 std::make_pair(*&SrcReg, Hexagon::isub_hi);
Pranav Bhandarkar823f9eb2012-09-05 16:01:40 +0000181 }
182
Sirish Pande30804c22012-02-15 18:52:27 +0000183 // Look for P=NOT(P).
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000184 if (!DisablePNotP && MI.getOpcode() == Hexagon::C2_not) {
185 assert(MI.getNumOperands() == 2);
186 MachineOperand &Dst = MI.getOperand(0);
187 MachineOperand &Src = MI.getOperand(1);
Sirish Pande30804c22012-02-15 18:52:27 +0000188 unsigned DstReg = Dst.getReg();
189 unsigned SrcReg = Src.getReg();
190 // Just handle virtual registers.
191 if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
192 TargetRegisterInfo::isVirtualRegister(SrcReg)) {
193 // Map the following:
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +0000194 // %170 = NOT_xx %166
Francis Visoiu Mistrih93ef1452017-11-30 12:12:19 +0000195 // PeepholeMap[170] = %166
Sirish Pande30804c22012-02-15 18:52:27 +0000196 PeepholeMap[DstReg] = SrcReg;
197 }
198 }
199
200 // Look for copy:
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +0000201 // %176 = COPY %170:isub_lo
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000202 if (!DisableOptSZExt && MI.isCopy()) {
203 assert(MI.getNumOperands() == 2);
204 MachineOperand &Dst = MI.getOperand(0);
205 MachineOperand &Src = MI.getOperand(1);
Sirish Pande30804c22012-02-15 18:52:27 +0000206
207 // Make sure we are copying the lower 32 bits.
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000208 if (Src.getSubReg() != Hexagon::isub_lo)
Sirish Pande30804c22012-02-15 18:52:27 +0000209 continue;
210
211 unsigned DstReg = Dst.getReg();
212 unsigned SrcReg = Src.getReg();
213 if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
214 TargetRegisterInfo::isVirtualRegister(SrcReg)) {
215 // Try to find in the map.
216 if (unsigned PeepholeSrc = PeepholeMap.lookup(SrcReg)) {
217 // Change the 1st operand.
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000218 MI.RemoveOperand(1);
219 MI.addOperand(MachineOperand::CreateReg(PeepholeSrc, false));
Pranav Bhandarkar823f9eb2012-09-05 16:01:40 +0000220 } else {
221 DenseMap<unsigned, std::pair<unsigned, unsigned> >::iterator DI =
222 PeepholeDoubleRegsMap.find(SrcReg);
223 if (DI != PeepholeDoubleRegsMap.end()) {
224 std::pair<unsigned,unsigned> PeepholeSrc = DI->second;
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000225 MI.RemoveOperand(1);
226 MI.addOperand(MachineOperand::CreateReg(
227 PeepholeSrc.first, false /*isDef*/, false /*isImp*/,
228 false /*isKill*/, false /*isDead*/, false /*isUndef*/,
229 false /*isEarlyClobber*/, PeepholeSrc.second));
Pranav Bhandarkar823f9eb2012-09-05 16:01:40 +0000230 }
Sirish Pande30804c22012-02-15 18:52:27 +0000231 }
232 }
233 }
234
235 // Look for Predicated instructions.
236 if (!DisablePNotP) {
237 bool Done = false;
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000238 if (QII->isPredicated(MI)) {
239 MachineOperand &Op0 = MI.getOperand(0);
Sirish Pande30804c22012-02-15 18:52:27 +0000240 unsigned Reg0 = Op0.getReg();
241 const TargetRegisterClass *RC0 = MRI->getRegClass(Reg0);
242 if (RC0->getID() == Hexagon::PredRegsRegClassID) {
243 // Handle instructions that have a prediate register in op0
244 // (most cases of predicable instructions).
245 if (TargetRegisterInfo::isVirtualRegister(Reg0)) {
246 // Try to find in the map.
247 if (unsigned PeepholeSrc = PeepholeMap.lookup(Reg0)) {
248 // Change the 1st operand and, flip the opcode.
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000249 MI.getOperand(0).setReg(PeepholeSrc);
Krzysztof Parzyszek7773c582016-08-04 14:17:16 +0000250 MRI->clearKillFlags(PeepholeSrc);
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000251 int NewOp = QII->getInvertedPredicatedOpcode(MI.getOpcode());
252 MI.setDesc(QII->get(NewOp));
Sirish Pande30804c22012-02-15 18:52:27 +0000253 Done = true;
254 }
255 }
256 }
257 }
258
259 if (!Done) {
260 // Handle special instructions.
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000261 unsigned Op = MI.getOpcode();
Sirish Pande30804c22012-02-15 18:52:27 +0000262 unsigned NewOp = 0;
263 unsigned PR = 1, S1 = 2, S2 = 3; // Operand indices.
264
265 switch (Op) {
Colin LeMahieue83bc742014-11-25 20:20:09 +0000266 case Hexagon::C2_mux:
Colin LeMahieu9665f982014-12-05 21:09:27 +0000267 case Hexagon::C2_muxii:
Sirish Pande30804c22012-02-15 18:52:27 +0000268 NewOp = Op;
269 break;
Colin LeMahieu9665f982014-12-05 21:09:27 +0000270 case Hexagon::C2_muxri:
271 NewOp = Hexagon::C2_muxir;
Sirish Pande30804c22012-02-15 18:52:27 +0000272 break;
Colin LeMahieu9665f982014-12-05 21:09:27 +0000273 case Hexagon::C2_muxir:
274 NewOp = Hexagon::C2_muxri;
Sirish Pande30804c22012-02-15 18:52:27 +0000275 break;
276 }
277 if (NewOp) {
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000278 unsigned PSrc = MI.getOperand(PR).getReg();
Sirish Pande30804c22012-02-15 18:52:27 +0000279 if (unsigned POrig = PeepholeMap.lookup(PSrc)) {
Krzysztof Parzyszek5b933fe2017-06-21 21:03:34 +0000280 BuildMI(*MBB, MI.getIterator(), MI.getDebugLoc(),
281 QII->get(NewOp), MI.getOperand(0).getReg())
282 .addReg(POrig)
283 .add(MI.getOperand(S2))
284 .add(MI.getOperand(S1));
Krzysztof Parzyszek7773c582016-08-04 14:17:16 +0000285 MRI->clearKillFlags(POrig);
Krzysztof Parzyszek5b933fe2017-06-21 21:03:34 +0000286 MI.eraseFromParent();
Sirish Pande30804c22012-02-15 18:52:27 +0000287 }
288 } // if (NewOp)
289 } // if (!Done)
290
291 } // if (!DisablePNotP)
292
293 } // Instruction
294 } // Basic Block
295 return true;
296}
297
Sirish Pande30804c22012-02-15 18:52:27 +0000298FunctionPass *llvm::createHexagonPeephole() {
299 return new HexagonPeephole();
300}