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
46using namespace llvm;
47
48#define DEBUG_TYPE "aarch64-mi-peephole-opt"
49
50namespace {
51
52struct AArch64MIPeepholeOpt : public MachineFunctionPass {
53 static char ID;
54
55 AArch64MIPeepholeOpt() : MachineFunctionPass(ID) {
57 }
58
59 const AArch64InstrInfo *TII;
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
115char AArch64MIPeepholeOpt::ID = 0;
116
117} // end anonymous namespace
118
119INITIALIZE_PASS(AArch64MIPeepholeOpt, "aarch64-mi-peephole-opt",
120 "AArch64 MI Peephole Optimization", false, false)
121
122template <typename T>
123static 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
160template <typename T>
161bool 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
195bool 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
256bool 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
301template <typename T>
302static 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
321template <typename T>
322bool 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
363template <typename T>
364bool 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.
406bool 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
444template <typename T>
445bool AArch64MIPeepholeOpt::splitTwoPartImm(
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
526bool 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}
unsigned const MachineRegisterInfo * MRI
unsigned HighestBitSet
unsigned T T & Imm2Enc
unsigned T & Imm1Enc
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
unsigned RegSize
static bool splitAddSubImm(T Imm, unsigned RegSize, T &Imm0, T &Imm1)
unsigned LowestBitSet
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DEBUG(X)
Definition: Debug.h:101
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:265
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:516
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:313
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:445
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:526
bool isLoopInvariant(MachineInstr &I) const
Returns true if the instruction is loop invariant.
unsigned getSubReg() const
int64_t getImm() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:91
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
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...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createAArch64MIPeepholeOptPass()
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
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
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition: bit.h:179
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
std::optional< UsedNZCV > examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > *CCUseInstrs=nullptr)
void initializeAArch64MIPeepholeOptPass(PassRegistry &)
#define OP(n)
Definition: regex2.h:73