LLVM  4.0.0
HexagonPeephole.cpp
Go to the documentation of this file.
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 // %vreg170<def> = SXTW %vreg166
12 // ...
13 // %vreg176<def> = COPY %vreg170:isub_lo
14 //
15 // Into
16 // %vreg176<def> = COPY vreg166
17 //
18 // 2. Optimizes redundant negation of predicates.
19 // %vreg15<def> = CMPGTrr %vreg6, %vreg2
20 // ...
21 // %vreg16<def> = NOT_p %vreg15<kill>
22 // ...
23 // JMP_c %vreg16<kill>, <BB#1>, %PC<imp-def,dead>
24 //
25 // Into
26 // %vreg15<def> = CMPGTrr %vreg6, %vreg2;
27 // ...
28 // JMP_cNot %vreg15<kill>, <BB#1>, %PC<imp-def,dead>;
29 //
30 // Note: The peephole pass makes the instrucstions like
31 // %vreg170<def> = SXTW %vreg166 or %vreg16<def> = NOT_p %vreg15<kill>
32 // redundant and relies on some form of dead removal instructions, like
33 // DCE or DIE to actually eliminate them.
34 
35 
36 //===----------------------------------------------------------------------===//
37 
38 #include "Hexagon.h"
39 #include "HexagonTargetMachine.h"
40 #include "llvm/ADT/DenseMap.h"
41 #include "llvm/ADT/Statistic.h"
46 #include "llvm/CodeGen/Passes.h"
47 #include "llvm/IR/Constants.h"
48 #include "llvm/PassSupport.h"
50 #include "llvm/Support/Debug.h"
55 #include <algorithm>
56 
57 using namespace llvm;
58 
59 #define DEBUG_TYPE "hexagon-peephole"
60 
61 static cl::opt<bool> DisableHexagonPeephole("disable-hexagon-peephole",
63  cl::desc("Disable Peephole Optimization"));
64 
65 static cl::opt<bool> DisablePNotP("disable-hexagon-pnotp",
67  cl::desc("Disable Optimization of PNotP"));
68 
69 static cl::opt<bool> DisableOptSZExt("disable-hexagon-optszext",
71  cl::desc("Disable Optimization of Sign/Zero Extends"));
72 
73 static cl::opt<bool> DisableOptExtTo64("disable-hexagon-opt-ext-to-64",
75  cl::desc("Disable Optimization of extensions to i64."));
76 
77 namespace llvm {
80 }
81 
82 namespace {
83  struct HexagonPeephole : public MachineFunctionPass {
84  const HexagonInstrInfo *QII;
85  const HexagonRegisterInfo *QRI;
86  const MachineRegisterInfo *MRI;
87 
88  public:
89  static char ID;
90  HexagonPeephole() : MachineFunctionPass(ID) {
92  }
93 
94  bool runOnMachineFunction(MachineFunction &MF) override;
95 
96  StringRef getPassName() const override {
97  return "Hexagon optimize redundant zero and size extends";
98  }
99 
100  void getAnalysisUsage(AnalysisUsage &AU) const override {
102  }
103 
104  private:
105  void ChangeOpInto(MachineOperand &Dst, MachineOperand &Src);
106  };
107 }
108 
109 char HexagonPeephole::ID = 0;
110 
111 INITIALIZE_PASS(HexagonPeephole, "hexagon-peephole", "Hexagon Peephole",
112  false, false)
113 
114 bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) {
115  if (skipFunction(*MF.getFunction()))
116  return false;
117 
118  QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
119  QRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
120  MRI = &MF.getRegInfo();
121 
122  DenseMap<unsigned, unsigned> PeepholeMap;
123  DenseMap<unsigned, std::pair<unsigned, unsigned> > PeepholeDoubleRegsMap;
124 
125  if (DisableHexagonPeephole) return false;
126 
127  // Loop over all of the basic blocks.
128  for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end();
129  MBBb != MBBe; ++MBBb) {
130  MachineBasicBlock *MBB = &*MBBb;
131  PeepholeMap.clear();
132  PeepholeDoubleRegsMap.clear();
133 
134  // Traverse the basic block.
135  for (MachineInstr &MI : *MBB) {
136  // Look for sign extends:
137  // %vreg170<def> = SXTW %vreg166
138  if (!DisableOptSZExt && MI.getOpcode() == Hexagon::A2_sxtw) {
139  assert(MI.getNumOperands() == 2);
140  MachineOperand &Dst = MI.getOperand(0);
141  MachineOperand &Src = MI.getOperand(1);
142  unsigned DstReg = Dst.getReg();
143  unsigned SrcReg = Src.getReg();
144  // Just handle virtual registers.
147  // Map the following:
148  // %vreg170<def> = SXTW %vreg166
149  // PeepholeMap[170] = vreg166
150  PeepholeMap[DstReg] = SrcReg;
151  }
152  }
153 
154  // Look for %vreg170<def> = COMBINE_ir_V4 (0, %vreg169)
155  // %vreg170:DoublRegs, %vreg169:IntRegs
156  if (!DisableOptExtTo64 && MI.getOpcode() == Hexagon::A4_combineir) {
157  assert(MI.getNumOperands() == 3);
158  MachineOperand &Dst = MI.getOperand(0);
159  MachineOperand &Src1 = MI.getOperand(1);
160  MachineOperand &Src2 = MI.getOperand(2);
161  if (Src1.getImm() != 0)
162  continue;
163  unsigned DstReg = Dst.getReg();
164  unsigned SrcReg = Src2.getReg();
165  PeepholeMap[DstReg] = SrcReg;
166  }
167 
168  // Look for this sequence below
169  // %vregDoubleReg1 = LSRd_ri %vregDoubleReg0, 32
170  // %vregIntReg = COPY %vregDoubleReg1:isub_lo.
171  // and convert into
172  // %vregIntReg = COPY %vregDoubleReg0:isub_hi.
173  if (MI.getOpcode() == Hexagon::S2_lsr_i_p) {
174  assert(MI.getNumOperands() == 3);
175  MachineOperand &Dst = MI.getOperand(0);
176  MachineOperand &Src1 = MI.getOperand(1);
177  MachineOperand &Src2 = MI.getOperand(2);
178  if (Src2.getImm() != 32)
179  continue;
180  unsigned DstReg = Dst.getReg();
181  unsigned SrcReg = Src1.getReg();
182  PeepholeDoubleRegsMap[DstReg] =
183  std::make_pair(*&SrcReg, Hexagon::isub_hi);
184  }
185 
186  // Look for P=NOT(P).
187  if (!DisablePNotP && MI.getOpcode() == Hexagon::C2_not) {
188  assert(MI.getNumOperands() == 2);
189  MachineOperand &Dst = MI.getOperand(0);
190  MachineOperand &Src = MI.getOperand(1);
191  unsigned DstReg = Dst.getReg();
192  unsigned SrcReg = Src.getReg();
193  // Just handle virtual registers.
196  // Map the following:
197  // %vreg170<def> = NOT_xx %vreg166
198  // PeepholeMap[170] = vreg166
199  PeepholeMap[DstReg] = SrcReg;
200  }
201  }
202 
203  // Look for copy:
204  // %vreg176<def> = COPY %vreg170:isub_lo
205  if (!DisableOptSZExt && MI.isCopy()) {
206  assert(MI.getNumOperands() == 2);
207  MachineOperand &Dst = MI.getOperand(0);
208  MachineOperand &Src = MI.getOperand(1);
209 
210  // Make sure we are copying the lower 32 bits.
211  if (Src.getSubReg() != Hexagon::isub_lo)
212  continue;
213 
214  unsigned DstReg = Dst.getReg();
215  unsigned SrcReg = Src.getReg();
218  // Try to find in the map.
219  if (unsigned PeepholeSrc = PeepholeMap.lookup(SrcReg)) {
220  // Change the 1st operand.
221  MI.RemoveOperand(1);
222  MI.addOperand(MachineOperand::CreateReg(PeepholeSrc, false));
223  } else {
225  PeepholeDoubleRegsMap.find(SrcReg);
226  if (DI != PeepholeDoubleRegsMap.end()) {
227  std::pair<unsigned,unsigned> PeepholeSrc = DI->second;
228  MI.RemoveOperand(1);
229  MI.addOperand(MachineOperand::CreateReg(
230  PeepholeSrc.first, false /*isDef*/, false /*isImp*/,
231  false /*isKill*/, false /*isDead*/, false /*isUndef*/,
232  false /*isEarlyClobber*/, PeepholeSrc.second));
233  }
234  }
235  }
236  }
237 
238  // Look for Predicated instructions.
239  if (!DisablePNotP) {
240  bool Done = false;
241  if (QII->isPredicated(MI)) {
242  MachineOperand &Op0 = MI.getOperand(0);
243  unsigned Reg0 = Op0.getReg();
244  const TargetRegisterClass *RC0 = MRI->getRegClass(Reg0);
245  if (RC0->getID() == Hexagon::PredRegsRegClassID) {
246  // Handle instructions that have a prediate register in op0
247  // (most cases of predicable instructions).
249  // Try to find in the map.
250  if (unsigned PeepholeSrc = PeepholeMap.lookup(Reg0)) {
251  // Change the 1st operand and, flip the opcode.
252  MI.getOperand(0).setReg(PeepholeSrc);
253  MRI->clearKillFlags(PeepholeSrc);
254  int NewOp = QII->getInvertedPredicatedOpcode(MI.getOpcode());
255  MI.setDesc(QII->get(NewOp));
256  Done = true;
257  }
258  }
259  }
260  }
261 
262  if (!Done) {
263  // Handle special instructions.
264  unsigned Op = MI.getOpcode();
265  unsigned NewOp = 0;
266  unsigned PR = 1, S1 = 2, S2 = 3; // Operand indices.
267 
268  switch (Op) {
269  case Hexagon::C2_mux:
270  case Hexagon::C2_muxii:
271  NewOp = Op;
272  break;
273  case Hexagon::C2_muxri:
274  NewOp = Hexagon::C2_muxir;
275  break;
276  case Hexagon::C2_muxir:
277  NewOp = Hexagon::C2_muxri;
278  break;
279  }
280  if (NewOp) {
281  unsigned PSrc = MI.getOperand(PR).getReg();
282  if (unsigned POrig = PeepholeMap.lookup(PSrc)) {
283  MI.getOperand(PR).setReg(POrig);
284  MRI->clearKillFlags(POrig);
285  MI.setDesc(QII->get(NewOp));
286  // Swap operands S1 and S2.
287  MachineOperand Op1 = MI.getOperand(S1);
288  MachineOperand Op2 = MI.getOperand(S2);
289  ChangeOpInto(MI.getOperand(S1), Op2);
290  ChangeOpInto(MI.getOperand(S2), Op1);
291  }
292  } // if (NewOp)
293  } // if (!Done)
294 
295  } // if (!DisablePNotP)
296 
297  } // Instruction
298  } // Basic Block
299  return true;
300 }
301 
302 void HexagonPeephole::ChangeOpInto(MachineOperand &Dst, MachineOperand &Src) {
303  assert (&Dst != &Src && "Cannot duplicate into itself");
304  switch (Dst.getType()) {
306  if (Src.isReg()) {
307  Dst.setReg(Src.getReg());
308  Dst.setSubReg(Src.getSubReg());
309  MRI->clearKillFlags(Src.getReg());
310  } else if (Src.isImm()) {
311  Dst.ChangeToImmediate(Src.getImm());
312  } else {
313  llvm_unreachable("Unexpected src operand type");
314  }
315  break;
316 
318  if (Src.isImm()) {
319  Dst.setImm(Src.getImm());
320  } else if (Src.isReg()) {
321  Dst.ChangeToRegister(Src.getReg(), Src.isDef(), Src.isImplicit(),
322  false, Src.isDead(), Src.isUndef(),
323  Src.isDebug());
324  Dst.setSubReg(Src.getSubReg());
325  } else {
326  llvm_unreachable("Unexpected src operand type");
327  }
328  break;
329 
330  default:
331  llvm_unreachable("Unexpected dst operand type");
332  break;
333  }
334 }
335 
337  return new HexagonPeephole();
338 }
bool isImplicit() const
INITIALIZE_PASS(HexagonPeephole,"hexagon-peephole","Hexagon Peephole", false, false) bool HexagonPeephole
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition: DenseMap.h:162
void ChangeToRegister(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value...
bool isDead() const
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
unsigned getID() const
Return the register class ID number.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isUndef() const
static cl::opt< bool > DisablePNotP("disable-hexagon-pnotp", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable Optimization of PNotP"))
MachineBasicBlock * MBB
static cl::opt< bool > DisableOptSZExt("disable-hexagon-optszext", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::desc("Disable Optimization of Sign/Zero Extends"))
int64_t getImm() const
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:395
unsigned const MachineRegisterInfo * MRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Represent the analysis usage information of a pass.
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
unsigned getSubReg() const
void initializeHexagonPeepholePass(PassRegistry &)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
MachineOperand class - Representation of each machine instruction operand.
FunctionPass * createHexagonPeephole()
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:52
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static cl::opt< bool > DisableHexagonPeephole("disable-hexagon-peephole", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable Peephole Optimization"))
void setReg(unsigned Reg)
Change the register this operand corresponds to.
void setSubReg(unsigned subReg)
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isDebug() const
static cl::opt< bool > DisableOptExtTo64("disable-hexagon-opt-ext-to-64", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::desc("Disable Optimization of extensions to i64."))
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:40