LLVM  17.0.0git
AArch64MIPeepholeOpt.cpp
Go to the documentation of this file.
1 //===- AArch64MIPeepholeOpt.cpp - AArch64 MI peephole optimization pass ---===//
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 //===----------------------------------------------------------------------===//
8 //
9 // This pass performs below peephole optimizations on MIR level.
10 //
11 // 1. MOVi32imm + ANDWrr ==> ANDWri + ANDWri
12 // MOVi64imm + ANDXrr ==> ANDXri + ANDXri
13 //
14 // 2. MOVi32imm + ADDWrr ==> ADDWRi + ADDWRi
15 // MOVi64imm + ADDXrr ==> ANDXri + ANDXri
16 //
17 // 3. MOVi32imm + SUBWrr ==> SUBWRi + SUBWRi
18 // MOVi64imm + SUBXrr ==> SUBXri + SUBXri
19 //
20 // The mov pseudo instruction could be expanded to multiple mov instructions
21 // later. In this case, we could try to split the constant operand of mov
22 // instruction into two immediates which can be directly encoded into
23 // *Wri/*Xri instructions. It makes two AND/ADD/SUB instructions instead of
24 // multiple `mov` + `and/add/sub` instructions.
25 //
26 // 4. Remove redundant ORRWrs which is generated by zero-extend.
27 //
28 // %3:gpr32 = ORRWrs $wzr, %2, 0
29 // %4:gpr64 = SUBREG_TO_REG 0, %3, %subreg.sub_32
30 //
31 // If AArch64's 32-bit form of instruction defines the source operand of
32 // ORRWrs, we can remove the ORRWrs because the upper 32 bits of the source
33 // operand are set to zero.
34 //
35 // 5. %reg = INSERT_SUBREG %reg(tied-def 0), %subreg, subidx
36 // ==> %reg:subidx = SUBREG_TO_REG 0, %subreg, subidx
37 //
38 //===----------------------------------------------------------------------===//
39 
40 #include "AArch64ExpandImm.h"
41 #include "AArch64InstrInfo.h"
45 
46 using namespace llvm;
47 
48 #define DEBUG_TYPE "aarch64-mi-peephole-opt"
49 
50 namespace {
51 
52 struct AArch64MIPeepholeOpt : public MachineFunctionPass {
53  static char ID;
54 
55  AArch64MIPeepholeOpt() : MachineFunctionPass(ID) {
57  }
58 
59  const AArch64InstrInfo *TII;
60  const AArch64RegisterInfo *TRI;
61  MachineLoopInfo *MLI;
63 
64  using OpcodePair = std::pair<unsigned, unsigned>;
65  template <typename T>
66  using SplitAndOpcFunc =
67  std::function<std::optional<OpcodePair>(T, unsigned, T &, T &)>;
68  using BuildMIFunc =
69  std::function<void(MachineInstr &, OpcodePair, unsigned, unsigned,
71 
72  /// For instructions where an immediate operand could be split into two
73  /// separate immediate instructions, use the splitTwoPartImm two handle the
74  /// optimization.
75  ///
76  /// To implement, the following function types must be passed to
77  /// splitTwoPartImm. A SplitAndOpcFunc must be implemented that determines if
78  /// splitting the immediate is valid and returns the associated new opcode. A
79  /// BuildMIFunc must be implemented to build the two immediate instructions.
80  ///
81  /// Example Pattern (where IMM would require 2+ MOV instructions):
82  /// %dst = <Instr>rr %src IMM [...]
83  /// becomes:
84  /// %tmp = <Instr>ri %src (encode half IMM) [...]
85  /// %dst = <Instr>ri %tmp (encode half IMM) [...]
86  template <typename T>
87  bool splitTwoPartImm(MachineInstr &MI,
88  SplitAndOpcFunc<T> SplitAndOpc, BuildMIFunc BuildInstr);
89 
90  bool checkMovImmInstr(MachineInstr &MI, MachineInstr *&MovMI,
91  MachineInstr *&SubregToRegMI);
92 
93  template <typename T>
94  bool visitADDSUB(unsigned PosOpc, unsigned NegOpc, MachineInstr &MI);
95  template <typename T>
96  bool visitADDSSUBS(OpcodePair PosOpcs, OpcodePair NegOpcs, MachineInstr &MI);
97 
98  template <typename T>
99  bool visitAND(unsigned Opc, MachineInstr &MI);
100  bool visitORR(MachineInstr &MI);
101  bool visitINSERT(MachineInstr &MI);
102  bool runOnMachineFunction(MachineFunction &MF) override;
103 
104  StringRef getPassName() const override {
105  return "AArch64 MI Peephole Optimization pass";
106  }
107 
108  void getAnalysisUsage(AnalysisUsage &AU) const override {
109  AU.setPreservesCFG();
112  }
113 };
114 
115 char AArch64MIPeepholeOpt::ID = 0;
116 
117 } // end anonymous namespace
118 
119 INITIALIZE_PASS(AArch64MIPeepholeOpt, "aarch64-mi-peephole-opt",
120  "AArch64 MI Peephole Optimization", false, false)
121 
122 template <typename T>
123 static bool splitBitmaskImm(T Imm, unsigned RegSize, T &Imm1Enc, T &Imm2Enc) {
124  T UImm = static_cast<T>(Imm);
126  return false;
127 
128  // If this immediate can be handled by one instruction, do not split it.
131  if (Insn.size() == 1)
132  return false;
133 
134  // The bitmask immediate consists of consecutive ones. Let's say there is
135  // constant 0b00000000001000000000010000000000 which does not consist of
136  // consecutive ones. We can split it in to two bitmask immediate like
137  // 0b00000000001111111111110000000000 and 0b11111111111000000000011111111111.
138  // If we do AND with these two bitmask immediate, we can see original one.
140  unsigned HighestBitSet = Log2_64(UImm);
141 
142  // Create a mask which is filled with one from the position of lowest bit set
143  // to the position of highest bit set.
144  T NewImm1 = (static_cast<T>(2) << HighestBitSet) -
145  (static_cast<T>(1) << LowestBitSet);
146  // Create a mask which is filled with one outside the position of lowest bit
147  // set and the position of highest bit set.
148  T NewImm2 = UImm | ~NewImm1;
149 
150  // If the split value is not valid bitmask immediate, do not split this
151  // constant.
153  return false;
154 
157  return true;
158 }
159 
160 template <typename T>
161 bool AArch64MIPeepholeOpt::visitAND(
162  unsigned Opc, MachineInstr &MI) {
163  // Try below transformation.
164  //
165  // MOVi32imm + ANDWrr ==> ANDWri + ANDWri
166  // MOVi64imm + ANDXrr ==> ANDXri + ANDXri
167  //
168  // The mov pseudo instruction could be expanded to multiple mov instructions
169  // later. Let's try to split the constant operand of mov instruction into two
170  // bitmask immediates. It makes only two AND instructions intead of multiple
171  // mov + and instructions.
172 
173  return splitTwoPartImm<T>(
174  MI,
175  [Opc](T Imm, unsigned RegSize, T &Imm0,
176  T &Imm1) -> std::optional<OpcodePair> {
177  if (splitBitmaskImm(Imm, RegSize, Imm0, Imm1))
178  return std::make_pair(Opc, Opc);
179  return std::nullopt;
180  },
181  [&TII = TII](MachineInstr &MI, OpcodePair Opcode, unsigned Imm0,
182  unsigned Imm1, Register SrcReg, Register NewTmpReg,
183  Register NewDstReg) {
184  DebugLoc DL = MI.getDebugLoc();
185  MachineBasicBlock *MBB = MI.getParent();
186  BuildMI(*MBB, MI, DL, TII->get(Opcode.first), NewTmpReg)
187  .addReg(SrcReg)
188  .addImm(Imm0);
189  BuildMI(*MBB, MI, DL, TII->get(Opcode.second), NewDstReg)
190  .addReg(NewTmpReg)
191  .addImm(Imm1);
192  });
193 }
194 
195 bool AArch64MIPeepholeOpt::visitORR(MachineInstr &MI) {
196  // Check this ORR comes from below zero-extend pattern.
197  //
198  // def : Pat<(i64 (zext GPR32:$src)),
199  // (SUBREG_TO_REG (i32 0), (ORRWrs WZR, GPR32:$src, 0), sub_32)>;
200  if (MI.getOperand(3).getImm() != 0)
201  return false;
202 
203  if (MI.getOperand(1).getReg() != AArch64::WZR)
204  return false;
205 
206  MachineInstr *SrcMI = MRI->getUniqueVRegDef(MI.getOperand(2).getReg());
207  if (!SrcMI)
208  return false;
209 
210  // From https://developer.arm.com/documentation/dui0801/b/BABBGCAC
211  //
212  // When you use the 32-bit form of an instruction, the upper 32 bits of the
213  // source registers are ignored and the upper 32 bits of the destination
214  // register are set to zero.
215  //
216  // If AArch64's 32-bit form of instruction defines the source operand of
217  // zero-extend, we do not need the zero-extend. Let's check the MI's opcode is
218  // real AArch64 instruction and if it is not, do not process the opcode
219  // conservatively.
220  if (SrcMI->getOpcode() == TargetOpcode::COPY &&
221  SrcMI->getOperand(1).getReg().isVirtual()) {
222  const TargetRegisterClass *RC =
223  MRI->getRegClass(SrcMI->getOperand(1).getReg());
224 
225  // A COPY from an FPR will become a FMOVSWr, so do so now so that we know
226  // that the upper bits are zero.
227  if (RC != &AArch64::FPR32RegClass &&
228  ((RC != &AArch64::FPR64RegClass && RC != &AArch64::FPR128RegClass) ||
229  SrcMI->getOperand(1).getSubReg() != AArch64::ssub))
230  return false;
231  Register CpySrc = SrcMI->getOperand(1).getReg();
232  if (SrcMI->getOperand(1).getSubReg() == AArch64::ssub) {
233  CpySrc = MRI->createVirtualRegister(&AArch64::FPR32RegClass);
234  BuildMI(*SrcMI->getParent(), SrcMI, SrcMI->getDebugLoc(),
235  TII->get(TargetOpcode::COPY), CpySrc)
236  .add(SrcMI->getOperand(1));
237  }
238  BuildMI(*SrcMI->getParent(), SrcMI, SrcMI->getDebugLoc(),
239  TII->get(AArch64::FMOVSWr), SrcMI->getOperand(0).getReg())
240  .addReg(CpySrc);
241  SrcMI->eraseFromParent();
242  }
243  else if (SrcMI->getOpcode() <= TargetOpcode::GENERIC_OP_END)
244  return false;
245 
246  Register DefReg = MI.getOperand(0).getReg();
247  Register SrcReg = MI.getOperand(2).getReg();
248  MRI->replaceRegWith(DefReg, SrcReg);
249  MRI->clearKillFlags(SrcReg);
250  LLVM_DEBUG(dbgs() << "Removed: " << MI << "\n");
251  MI.eraseFromParent();
252 
253  return true;
254 }
255 
256 bool AArch64MIPeepholeOpt::visitINSERT(MachineInstr &MI) {
257  // Check this INSERT_SUBREG comes from below zero-extend pattern.
258  //
259  // From %reg = INSERT_SUBREG %reg(tied-def 0), %subreg, subidx
260  // To %reg:subidx = SUBREG_TO_REG 0, %subreg, subidx
261  //
262  // We're assuming the first operand to INSERT_SUBREG is irrelevant because a
263  // COPY would destroy the upper part of the register anyway
264  if (!MI.isRegTiedToDefOperand(1))
265  return false;
266 
267  Register DstReg = MI.getOperand(0).getReg();
268  const TargetRegisterClass *RC = MRI->getRegClass(DstReg);
269  MachineInstr *SrcMI = MRI->getUniqueVRegDef(MI.getOperand(2).getReg());
270  if (!SrcMI)
271  return false;
272 
273  // From https://developer.arm.com/documentation/dui0801/b/BABBGCAC
274  //
275  // When you use the 32-bit form of an instruction, the upper 32 bits of the
276  // source registers are ignored and the upper 32 bits of the destination
277  // register are set to zero.
278  //
279  // If AArch64's 32-bit form of instruction defines the source operand of
280  // zero-extend, we do not need the zero-extend. Let's check the MI's opcode is
281  // real AArch64 instruction and if it is not, do not process the opcode
282  // conservatively.
283  if ((SrcMI->getOpcode() <= TargetOpcode::GENERIC_OP_END) ||
284  !AArch64::GPR64allRegClass.hasSubClassEq(RC))
285  return false;
286 
287  // Build a SUBREG_TO_REG instruction
288  MachineInstr *SubregMI =
289  BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
290  TII->get(TargetOpcode::SUBREG_TO_REG), DstReg)
291  .addImm(0)
292  .add(MI.getOperand(2))
293  .add(MI.getOperand(3));
294  LLVM_DEBUG(dbgs() << MI << " replace by:\n: " << *SubregMI << "\n");
295  (void)SubregMI;
296  MI.eraseFromParent();
297 
298  return true;
299 }
300 
301 template <typename T>
302 static bool splitAddSubImm(T Imm, unsigned RegSize, T &Imm0, T &Imm1) {
303  // The immediate must be in the form of ((imm0 << 12) + imm1), in which both
304  // imm0 and imm1 are non-zero 12-bit unsigned int.
305  if ((Imm & 0xfff000) == 0 || (Imm & 0xfff) == 0 ||
306  (Imm & ~static_cast<T>(0xffffff)) != 0)
307  return false;
308 
309  // The immediate can not be composed via a single instruction.
312  if (Insn.size() == 1)
313  return false;
314 
315  // Split Imm into (Imm0 << 12) + Imm1;
316  Imm0 = (Imm >> 12) & 0xfff;
317  Imm1 = Imm & 0xfff;
318  return true;
319 }
320 
321 template <typename T>
322 bool AArch64MIPeepholeOpt::visitADDSUB(
323  unsigned PosOpc, unsigned NegOpc, MachineInstr &MI) {
324  // Try below transformation.
325  //
326  // MOVi32imm + ADDWrr ==> ADDWri + ADDWri
327  // MOVi64imm + ADDXrr ==> ADDXri + ADDXri
328  //
329  // MOVi32imm + SUBWrr ==> SUBWri + SUBWri
330  // MOVi64imm + SUBXrr ==> SUBXri + SUBXri
331  //
332  // The mov pseudo instruction could be expanded to multiple mov instructions
333  // later. Let's try to split the constant operand of mov instruction into two
334  // legal add/sub immediates. It makes only two ADD/SUB instructions intead of
335  // multiple `mov` + `and/sub` instructions.
336 
337  return splitTwoPartImm<T>(
338  MI,
339  [PosOpc, NegOpc](T Imm, unsigned RegSize, T &Imm0,
340  T &Imm1) -> std::optional<OpcodePair> {
341  if (splitAddSubImm(Imm, RegSize, Imm0, Imm1))
342  return std::make_pair(PosOpc, PosOpc);
343  if (splitAddSubImm(-Imm, RegSize, Imm0, Imm1))
344  return std::make_pair(NegOpc, NegOpc);
345  return std::nullopt;
346  },
347  [&TII = TII](MachineInstr &MI, OpcodePair Opcode, unsigned Imm0,
348  unsigned Imm1, Register SrcReg, Register NewTmpReg,
349  Register NewDstReg) {
350  DebugLoc DL = MI.getDebugLoc();
351  MachineBasicBlock *MBB = MI.getParent();
352  BuildMI(*MBB, MI, DL, TII->get(Opcode.first), NewTmpReg)
353  .addReg(SrcReg)
354  .addImm(Imm0)
355  .addImm(12);
356  BuildMI(*MBB, MI, DL, TII->get(Opcode.second), NewDstReg)
357  .addReg(NewTmpReg)
358  .addImm(Imm1)
359  .addImm(0);
360  });
361 }
362 
363 template <typename T>
364 bool AArch64MIPeepholeOpt::visitADDSSUBS(
365  OpcodePair PosOpcs, OpcodePair NegOpcs, MachineInstr &MI) {
366  // Try the same transformation as ADDSUB but with additional requirement
367  // that the condition code usages are only for Equal and Not Equal
368  return splitTwoPartImm<T>(
369  MI,
370  [PosOpcs, NegOpcs, &MI, &TRI = TRI,
371  &MRI = MRI](T Imm, unsigned RegSize, T &Imm0,
372  T &Imm1) -> std::optional<OpcodePair> {
373  OpcodePair OP;
374  if (splitAddSubImm(Imm, RegSize, Imm0, Imm1))
375  OP = PosOpcs;
376  else if (splitAddSubImm(-Imm, RegSize, Imm0, Imm1))
377  OP = NegOpcs;
378  else
379  return std::nullopt;
380  // Check conditional uses last since it is expensive for scanning
381  // proceeding instructions
382  MachineInstr &SrcMI = *MRI->getUniqueVRegDef(MI.getOperand(1).getReg());
383  std::optional<UsedNZCV> NZCVUsed = examineCFlagsUse(SrcMI, MI, *TRI);
384  if (!NZCVUsed || NZCVUsed->C || NZCVUsed->V)
385  return std::nullopt;
386  return OP;
387  },
388  [&TII = TII](MachineInstr &MI, OpcodePair Opcode, unsigned Imm0,
389  unsigned Imm1, Register SrcReg, Register NewTmpReg,
390  Register NewDstReg) {
391  DebugLoc DL = MI.getDebugLoc();
392  MachineBasicBlock *MBB = MI.getParent();
393  BuildMI(*MBB, MI, DL, TII->get(Opcode.first), NewTmpReg)
394  .addReg(SrcReg)
395  .addImm(Imm0)
396  .addImm(12);
397  BuildMI(*MBB, MI, DL, TII->get(Opcode.second), NewDstReg)
398  .addReg(NewTmpReg)
399  .addImm(Imm1)
400  .addImm(0);
401  });
402 }
403 
404 // Checks if the corresponding MOV immediate instruction is applicable for
405 // this peephole optimization.
406 bool AArch64MIPeepholeOpt::checkMovImmInstr(MachineInstr &MI,
407  MachineInstr *&MovMI,
408  MachineInstr *&SubregToRegMI) {
409  // Check whether current MBB is in loop and the AND is loop invariant.
410  MachineBasicBlock *MBB = MI.getParent();
411  MachineLoop *L = MLI->getLoopFor(MBB);
412  if (L && !L->isLoopInvariant(MI))
413  return false;
414 
415  // Check whether current MI's operand is MOV with immediate.
416  MovMI = MRI->getUniqueVRegDef(MI.getOperand(2).getReg());
417  if (!MovMI)
418  return false;
419 
420  // If it is SUBREG_TO_REG, check its operand.
421  SubregToRegMI = nullptr;
422  if (MovMI->getOpcode() == TargetOpcode::SUBREG_TO_REG) {
423  SubregToRegMI = MovMI;
424  MovMI = MRI->getUniqueVRegDef(MovMI->getOperand(2).getReg());
425  if (!MovMI)
426  return false;
427  }
428 
429  if (MovMI->getOpcode() != AArch64::MOVi32imm &&
430  MovMI->getOpcode() != AArch64::MOVi64imm)
431  return false;
432 
433  // If the MOV has multiple uses, do not split the immediate because it causes
434  // more instructions.
435  if (!MRI->hasOneUse(MovMI->getOperand(0).getReg()))
436  return false;
437  if (SubregToRegMI && !MRI->hasOneUse(SubregToRegMI->getOperand(0).getReg()))
438  return false;
439 
440  // It is OK to perform this peephole optimization.
441  return true;
442 }
443 
444 template <typename T>
445 bool AArch64MIPeepholeOpt::splitTwoPartImm(
446  MachineInstr &MI,
447  SplitAndOpcFunc<T> SplitAndOpc, BuildMIFunc BuildInstr) {
448  unsigned RegSize = sizeof(T) * 8;
449  assert((RegSize == 32 || RegSize == 64) &&
450  "Invalid RegSize for legal immediate peephole optimization");
451 
452  // Perform several essential checks against current MI.
453  MachineInstr *MovMI, *SubregToRegMI;
454  if (!checkMovImmInstr(MI, MovMI, SubregToRegMI))
455  return false;
456 
457  // Split the immediate to Imm0 and Imm1, and calculate the Opcode.
458  T Imm = static_cast<T>(MovMI->getOperand(1).getImm()), Imm0, Imm1;
459  // For the 32 bit form of instruction, the upper 32 bits of the destination
460  // register are set to zero. If there is SUBREG_TO_REG, set the upper 32 bits
461  // of Imm to zero. This is essential if the Immediate value was a negative
462  // number since it was sign extended when we assign to the 64-bit Imm.
463  if (SubregToRegMI)
464  Imm &= 0xFFFFFFFF;
465  OpcodePair Opcode;
466  if (auto R = SplitAndOpc(Imm, RegSize, Imm0, Imm1))
467  Opcode = *R;
468  else
469  return false;
470 
471  // Create new MIs using the first and second opcodes. Opcodes might differ for
472  // flag setting operations that should only set flags on second instruction.
473  // NewTmpReg = Opcode.first SrcReg Imm0
474  // NewDstReg = Opcode.second NewTmpReg Imm1
475 
476  // Determine register classes for destinations and register operands
477  MachineFunction *MF = MI.getMF();
478  const TargetRegisterClass *FirstInstrDstRC =
479  TII->getRegClass(TII->get(Opcode.first), 0, TRI, *MF);
480  const TargetRegisterClass *FirstInstrOperandRC =
481  TII->getRegClass(TII->get(Opcode.first), 1, TRI, *MF);
482  const TargetRegisterClass *SecondInstrDstRC =
483  (Opcode.first == Opcode.second)
484  ? FirstInstrDstRC
485  : TII->getRegClass(TII->get(Opcode.second), 0, TRI, *MF);
486  const TargetRegisterClass *SecondInstrOperandRC =
487  (Opcode.first == Opcode.second)
488  ? FirstInstrOperandRC
489  : TII->getRegClass(TII->get(Opcode.second), 1, TRI, *MF);
490 
491  // Get old registers destinations and new register destinations
492  Register DstReg = MI.getOperand(0).getReg();
493  Register SrcReg = MI.getOperand(1).getReg();
494  Register NewTmpReg = MRI->createVirtualRegister(FirstInstrDstRC);
495  // In the situation that DstReg is not Virtual (likely WZR or XZR), we want to
496  // reuse that same destination register.
497  Register NewDstReg = DstReg.isVirtual()
498  ? MRI->createVirtualRegister(SecondInstrDstRC)
499  : DstReg;
500 
501  // Constrain registers based on their new uses
502  MRI->constrainRegClass(SrcReg, FirstInstrOperandRC);
503  MRI->constrainRegClass(NewTmpReg, SecondInstrOperandRC);
504  if (DstReg != NewDstReg)
505  MRI->constrainRegClass(NewDstReg, MRI->getRegClass(DstReg));
506 
507  // Call the delegating operation to build the instruction
508  BuildInstr(MI, Opcode, Imm0, Imm1, SrcReg, NewTmpReg, NewDstReg);
509 
510  // replaceRegWith changes MI's definition register. Keep it for SSA form until
511  // deleting MI. Only if we made a new destination register.
512  if (DstReg != NewDstReg) {
513  MRI->replaceRegWith(DstReg, NewDstReg);
514  MI.getOperand(0).setReg(DstReg);
515  }
516 
517  // Record the MIs need to be removed.
518  MI.eraseFromParent();
519  if (SubregToRegMI)
520  SubregToRegMI->eraseFromParent();
521  MovMI->eraseFromParent();
522 
523  return true;
524 }
525 
526 bool AArch64MIPeepholeOpt::runOnMachineFunction(MachineFunction &MF) {
527  if (skipFunction(MF.getFunction()))
528  return false;
529 
530  TII = static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo());
531  TRI = static_cast<const AArch64RegisterInfo *>(
533  MLI = &getAnalysis<MachineLoopInfo>();
534  MRI = &MF.getRegInfo();
535 
536  assert(MRI->isSSA() && "Expected to be run on SSA form!");
537 
538  bool Changed = false;
539 
540  for (MachineBasicBlock &MBB : MF) {
542  switch (MI.getOpcode()) {
543  default:
544  break;
545  case AArch64::INSERT_SUBREG:
546  Changed = visitINSERT(MI);
547  break;
548  case AArch64::ANDWrr:
549  Changed = visitAND<uint32_t>(AArch64::ANDWri, MI);
550  break;
551  case AArch64::ANDXrr:
552  Changed = visitAND<uint64_t>(AArch64::ANDXri, MI);
553  break;
554  case AArch64::ORRWrs:
555  Changed = visitORR(MI);
556  break;
557  case AArch64::ADDWrr:
558  Changed = visitADDSUB<uint32_t>(AArch64::ADDWri, AArch64::SUBWri, MI);
559  break;
560  case AArch64::SUBWrr:
561  Changed = visitADDSUB<uint32_t>(AArch64::SUBWri, AArch64::ADDWri, MI);
562  break;
563  case AArch64::ADDXrr:
564  Changed = visitADDSUB<uint64_t>(AArch64::ADDXri, AArch64::SUBXri, MI);
565  break;
566  case AArch64::SUBXrr:
567  Changed = visitADDSUB<uint64_t>(AArch64::SUBXri, AArch64::ADDXri, MI);
568  break;
569  case AArch64::ADDSWrr:
570  Changed = visitADDSSUBS<uint32_t>({AArch64::ADDWri, AArch64::ADDSWri},
571  {AArch64::SUBWri, AArch64::SUBSWri},
572  MI);
573  break;
574  case AArch64::SUBSWrr:
575  Changed = visitADDSSUBS<uint32_t>({AArch64::SUBWri, AArch64::SUBSWri},
576  {AArch64::ADDWri, AArch64::ADDSWri},
577  MI);
578  break;
579  case AArch64::ADDSXrr:
580  Changed = visitADDSSUBS<uint64_t>({AArch64::ADDXri, AArch64::ADDSXri},
581  {AArch64::SUBXri, AArch64::SUBSXri},
582  MI);
583  break;
584  case AArch64::SUBSXrr:
585  Changed = visitADDSSUBS<uint64_t>({AArch64::SUBXri, AArch64::SUBSXri},
586  {AArch64::ADDXri, AArch64::ADDSXri},
587  MI);
588  break;
589  }
590  }
591  }
592 
593  return Changed;
594 }
595 
597  return new AArch64MIPeepholeOpt();
598 }
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:109
llvm::MachineInstrBuilder::addImm
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Definition: MachineInstrBuilder.h:131
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::AArch64PACKey::ID
ID
Definition: AArch64BaseInfo.h:824
llvm::MachineRegisterInfo::createVirtualRegister
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Definition: MachineRegisterInfo.cpp:157
llvm::MachineRegisterInfo
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Definition: MachineRegisterInfo.h:51
T
RegSize
unsigned RegSize
Definition: AArch64MIPeepholeOpt.cpp:123
llvm::MachineInstrBuilder::add
const MachineInstrBuilder & add(const MachineOperand &MO) const
Definition: MachineInstrBuilder.h:224
llvm::TargetSubtargetInfo::getInstrInfo
virtual const TargetInstrInfo * getInstrInfo() const
Definition: TargetSubtargetInfo.h:95
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::MachineRegisterInfo::getUniqueVRegDef
MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
Definition: MachineRegisterInfo.cpp:409
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::TargetSubtargetInfo::getRegisterInfo
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
Definition: TargetSubtargetInfo.h:127
TRI
unsigned const TargetRegisterInfo * TRI
Definition: MachineSink.cpp:1628
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:167
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::MachineLoopInfo
Definition: MachineLoopInfo.h:89
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::examineCFlagsUse
std::optional< UsedNZCV > examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > *CCUseInstrs=nullptr)
Definition: AArch64InstrInfo.cpp:1650
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition: MachineFunction.h:682
llvm::Log2_64
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:379
MachineLoopInfo.h
Imm1Enc
unsigned T & Imm1Enc
Definition: AArch64MIPeepholeOpt.cpp:123
AArch64InstrInfo.h
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:24
llvm::AArch64InstrInfo
Definition: AArch64InstrInfo.h:35
llvm::AArch64_AM::isLogicalImmediate
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
Definition: AArch64AddressingModes.h:276
llvm::MachineOperand::getImm
int64_t getImm() const
Definition: MachineOperand.h:553
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:526
llvm::TargetRegisterClass
Definition: TargetRegisterInfo.h:45
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:125
splitAddSubImm
static bool splitAddSubImm(T Imm, unsigned RegSize, T &Imm0, T &Imm1)
Definition: AArch64MIPeepholeOpt.cpp:302
INITIALIZE_PASS
INITIALIZE_PASS(AArch64MIPeepholeOpt, "aarch64-mi-peephole-opt", "AArch64 MI Peephole Optimization", false, false) template< typename T > static bool splitBitmaskImm(T Imm
llvm::countTrailingZeros
unsigned countTrailingZeros(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition: MathExtras.h:69
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:94
llvm::MachineRegisterInfo::getRegClass
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
Definition: MachineRegisterInfo.h:661
llvm::MachineRegisterInfo::isSSA
bool isSSA() const
Definition: MachineRegisterInfo.h:197
AArch64AddressingModes.h
llvm::Register::isVirtual
bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:91
llvm::MachineRegisterInfo::clearKillFlags
void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
Definition: MachineRegisterInfo.cpp:435
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:672
llvm::MachineInstr::getDebugLoc
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:445
llvm::MachineLoop
Definition: MachineLoopInfo.h:44
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
Imm2Enc
unsigned T T & Imm2Enc
Definition: AArch64MIPeepholeOpt.cpp:123
AArch64ExpandImm.h
NewImm2
T NewImm2
Definition: AArch64MIPeepholeOpt.cpp:148
llvm::make_early_inc_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:721
llvm::createAArch64MIPeepholeOptPass
FunctionPass * createAArch64MIPeepholeOptPass()
Definition: AArch64MIPeepholeOpt.cpp:596
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
llvm::MachineInstrBuilder::addReg
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Definition: MachineInstrBuilder.h:97
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:366
OP
#define OP(n)
Definition: regex2.h:73
HighestBitSet
unsigned HighestBitSet
Definition: AArch64MIPeepholeOpt.cpp:140
llvm::MachineFunction
Definition: MachineFunction.h:258
llvm::AArch64_AM::encodeLogicalImmediate
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
Definition: AArch64AddressingModes.h:283
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:265
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:516
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::AArch64RegisterInfo
Definition: AArch64RegisterInfo.h:26
llvm::MachineInstr::getParent
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:313
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::MachineOperand::getSubReg
unsigned getSubReg() const
Definition: MachineOperand.h:371
llvm::MachineRegisterInfo::replaceRegWith
void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Definition: MachineRegisterInfo.cpp:380
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::initializeAArch64MIPeepholeOptPass
void initializeAArch64MIPeepholeOptPass(PassRegistry &)
Insn
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
Definition: AArch64MIPeepholeOpt.cpp:129
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:638
llvm::AArch64_IMM::expandMOVImm
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
Definition: AArch64ExpandImm.cpp:303
llvm::RISCVMatInt::Imm
@ Imm
Definition: RISCVMatInt.h:23
NewImm1
T NewImm1
Definition: AArch64MIPeepholeOpt.cpp:144
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:357
llvm::MachineRegisterInfo::hasOneUse
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
Definition: MachineRegisterInfo.h:532
llvm::MachineRegisterInfo::constrainRegClass
const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
Definition: MachineRegisterInfo.cpp:83
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::MachineLoop::isLoopInvariant
bool isLoopInvariant(MachineInstr &I) const
Returns true if the instruction is loop invariant.
Definition: MachineLoopInfo.cpp:154
llvm::MachineInstr::eraseFromParent
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Definition: MachineInstr.cpp:705
LowestBitSet
unsigned LowestBitSet
Definition: AArch64MIPeepholeOpt.cpp:139
MachineDominators.h