LLVM  9.0.0svn
AArch64ExpandPseudoInsts.cpp
Go to the documentation of this file.
1 //===- AArch64ExpandPseudoInsts.cpp - Expand pseudo instructions ----------===//
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 file contains a pass that expands pseudo instructions into target
10 // instructions to allow proper scheduling and other late optimizations. This
11 // pass should be run after register allocation but before the post-regalloc
12 // scheduling pass.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "AArch64ExpandImm.h"
17 #include "AArch64InstrInfo.h"
18 #include "AArch64Subtarget.h"
20 #include "Utils/AArch64BaseInfo.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/Triple.h"
31 #include "llvm/IR/DebugLoc.h"
32 #include "llvm/MC/MCInstrDesc.h"
33 #include "llvm/Pass.h"
34 #include "llvm/Support/CodeGen.h"
37 #include <cassert>
38 #include <cstdint>
39 #include <iterator>
40 #include <limits>
41 #include <utility>
42 
43 using namespace llvm;
44 
45 #define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
46 
47 namespace {
48 
49 class AArch64ExpandPseudo : public MachineFunctionPass {
50 public:
51  const AArch64InstrInfo *TII;
52 
53  static char ID;
54 
55  AArch64ExpandPseudo() : MachineFunctionPass(ID) {
57  }
58 
59  bool runOnMachineFunction(MachineFunction &Fn) override;
60 
61  StringRef getPassName() const override { return AARCH64_EXPAND_PSEUDO_NAME; }
62 
63 private:
64  bool expandMBB(MachineBasicBlock &MBB);
65  bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
66  MachineBasicBlock::iterator &NextMBBI);
68  unsigned BitSize);
69 
70  bool expandCMP_SWAP(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
71  unsigned LdarOp, unsigned StlrOp, unsigned CmpOp,
72  unsigned ExtendImm, unsigned ZeroReg,
73  MachineBasicBlock::iterator &NextMBBI);
74  bool expandCMP_SWAP_128(MachineBasicBlock &MBB,
76  MachineBasicBlock::iterator &NextMBBI);
77 };
78 
79 } // end anonymous namespace
80 
82 
83 INITIALIZE_PASS(AArch64ExpandPseudo, "aarch64-expand-pseudo",
84  AARCH64_EXPAND_PSEUDO_NAME, false, false)
85 
86 /// Transfer implicit operands on the pseudo instruction to the
87 /// instructions created from the expansion.
88 static void transferImpOps(MachineInstr &OldMI, MachineInstrBuilder &UseMI,
90  const MCInstrDesc &Desc = OldMI.getDesc();
91  for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands(); i != e;
92  ++i) {
93  const MachineOperand &MO = OldMI.getOperand(i);
94  assert(MO.isReg() && MO.getReg());
95  if (MO.isUse())
96  UseMI.add(MO);
97  else
98  DefMI.add(MO);
99  }
100 }
101 
102 /// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more
103 /// real move-immediate instructions to synthesize the immediate.
106  unsigned BitSize) {
107  MachineInstr &MI = *MBBI;
108  unsigned DstReg = MI.getOperand(0).getReg();
109  uint64_t Imm = MI.getOperand(1).getImm();
110 
111  if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
112  // Useless def, and we don't want to risk creating an invalid ORR (which
113  // would really write to sp).
114  MI.eraseFromParent();
115  return true;
116  }
117 
119  AArch64_IMM::expandMOVImm(Imm, BitSize, Insn);
120  assert(Insn.size() != 0);
121 
123  for (auto I = Insn.begin(), E = Insn.end(); I != E; ++I) {
124  bool LastItem = std::next(I) == E;
125  switch (I->Opcode)
126  {
127  default: llvm_unreachable("unhandled!"); break;
128 
129  case AArch64::ORRWri:
130  case AArch64::ORRXri:
131  MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
132  .add(MI.getOperand(0))
133  .addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
134  .addImm(I->Op2));
135  break;
136  case AArch64::MOVNWi:
137  case AArch64::MOVNXi:
138  case AArch64::MOVZWi:
139  case AArch64::MOVZXi: {
140  bool DstIsDead = MI.getOperand(0).isDead();
141  MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
142  .addReg(DstReg, RegState::Define |
143  getDeadRegState(DstIsDead && LastItem))
144  .addImm(I->Op1)
145  .addImm(I->Op2));
146  } break;
147  case AArch64::MOVKWi:
148  case AArch64::MOVKXi: {
149  unsigned DstReg = MI.getOperand(0).getReg();
150  bool DstIsDead = MI.getOperand(0).isDead();
151  MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
152  .addReg(DstReg,
154  getDeadRegState(DstIsDead && LastItem))
155  .addReg(DstReg)
156  .addImm(I->Op1)
157  .addImm(I->Op2));
158  } break;
159  }
160  }
161  transferImpOps(MI, MIBS.front(), MIBS.back());
162  MI.eraseFromParent();
163  return true;
164 }
165 
166 bool AArch64ExpandPseudo::expandCMP_SWAP(
167  MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned LdarOp,
168  unsigned StlrOp, unsigned CmpOp, unsigned ExtendImm, unsigned ZeroReg,
169  MachineBasicBlock::iterator &NextMBBI) {
170  MachineInstr &MI = *MBBI;
171  DebugLoc DL = MI.getDebugLoc();
172  const MachineOperand &Dest = MI.getOperand(0);
173  unsigned StatusReg = MI.getOperand(1).getReg();
174  bool StatusDead = MI.getOperand(1).isDead();
175  // Duplicating undef operands into 2 instructions does not guarantee the same
176  // value on both; However undef should be replaced by xzr anyway.
177  assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
178  unsigned AddrReg = MI.getOperand(2).getReg();
179  unsigned DesiredReg = MI.getOperand(3).getReg();
180  unsigned NewReg = MI.getOperand(4).getReg();
181 
182  MachineFunction *MF = MBB.getParent();
183  auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
184  auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
185  auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
186 
187  MF->insert(++MBB.getIterator(), LoadCmpBB);
188  MF->insert(++LoadCmpBB->getIterator(), StoreBB);
189  MF->insert(++StoreBB->getIterator(), DoneBB);
190 
191  // .Lloadcmp:
192  // mov wStatus, 0
193  // ldaxr xDest, [xAddr]
194  // cmp xDest, xDesired
195  // b.ne .Ldone
196  if (!StatusDead)
197  BuildMI(LoadCmpBB, DL, TII->get(AArch64::MOVZWi), StatusReg)
198  .addImm(0).addImm(0);
199  BuildMI(LoadCmpBB, DL, TII->get(LdarOp), Dest.getReg())
200  .addReg(AddrReg);
201  BuildMI(LoadCmpBB, DL, TII->get(CmpOp), ZeroReg)
202  .addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
203  .addReg(DesiredReg)
204  .addImm(ExtendImm);
205  BuildMI(LoadCmpBB, DL, TII->get(AArch64::Bcc))
206  .addImm(AArch64CC::NE)
207  .addMBB(DoneBB)
208  .addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
209  LoadCmpBB->addSuccessor(DoneBB);
210  LoadCmpBB->addSuccessor(StoreBB);
211 
212  // .Lstore:
213  // stlxr wStatus, xNew, [xAddr]
214  // cbnz wStatus, .Lloadcmp
215  BuildMI(StoreBB, DL, TII->get(StlrOp), StatusReg)
216  .addReg(NewReg)
217  .addReg(AddrReg);
218  BuildMI(StoreBB, DL, TII->get(AArch64::CBNZW))
219  .addReg(StatusReg, getKillRegState(StatusDead))
220  .addMBB(LoadCmpBB);
221  StoreBB->addSuccessor(LoadCmpBB);
222  StoreBB->addSuccessor(DoneBB);
223 
224  DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
225  DoneBB->transferSuccessors(&MBB);
226 
227  MBB.addSuccessor(LoadCmpBB);
228 
229  NextMBBI = MBB.end();
230  MI.eraseFromParent();
231 
232  // Recompute livein lists.
233  LivePhysRegs LiveRegs;
234  computeAndAddLiveIns(LiveRegs, *DoneBB);
235  computeAndAddLiveIns(LiveRegs, *StoreBB);
236  computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
237  // Do an extra pass around the loop to get loop carried registers right.
238  StoreBB->clearLiveIns();
239  computeAndAddLiveIns(LiveRegs, *StoreBB);
240  LoadCmpBB->clearLiveIns();
241  computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
242 
243  return true;
244 }
245 
246 bool AArch64ExpandPseudo::expandCMP_SWAP_128(
248  MachineBasicBlock::iterator &NextMBBI) {
249  MachineInstr &MI = *MBBI;
250  DebugLoc DL = MI.getDebugLoc();
251  MachineOperand &DestLo = MI.getOperand(0);
252  MachineOperand &DestHi = MI.getOperand(1);
253  unsigned StatusReg = MI.getOperand(2).getReg();
254  bool StatusDead = MI.getOperand(2).isDead();
255  // Duplicating undef operands into 2 instructions does not guarantee the same
256  // value on both; However undef should be replaced by xzr anyway.
257  assert(!MI.getOperand(3).isUndef() && "cannot handle undef");
258  unsigned AddrReg = MI.getOperand(3).getReg();
259  unsigned DesiredLoReg = MI.getOperand(4).getReg();
260  unsigned DesiredHiReg = MI.getOperand(5).getReg();
261  unsigned NewLoReg = MI.getOperand(6).getReg();
262  unsigned NewHiReg = MI.getOperand(7).getReg();
263 
264  MachineFunction *MF = MBB.getParent();
265  auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
266  auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
267  auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
268 
269  MF->insert(++MBB.getIterator(), LoadCmpBB);
270  MF->insert(++LoadCmpBB->getIterator(), StoreBB);
271  MF->insert(++StoreBB->getIterator(), DoneBB);
272 
273  // .Lloadcmp:
274  // ldaxp xDestLo, xDestHi, [xAddr]
275  // cmp xDestLo, xDesiredLo
276  // sbcs xDestHi, xDesiredHi
277  // b.ne .Ldone
278  BuildMI(LoadCmpBB, DL, TII->get(AArch64::LDAXPX))
279  .addReg(DestLo.getReg(), RegState::Define)
280  .addReg(DestHi.getReg(), RegState::Define)
281  .addReg(AddrReg);
282  BuildMI(LoadCmpBB, DL, TII->get(AArch64::SUBSXrs), AArch64::XZR)
283  .addReg(DestLo.getReg(), getKillRegState(DestLo.isDead()))
284  .addReg(DesiredLoReg)
285  .addImm(0);
286  BuildMI(LoadCmpBB, DL, TII->get(AArch64::CSINCWr), StatusReg)
287  .addUse(AArch64::WZR)
288  .addUse(AArch64::WZR)
290  BuildMI(LoadCmpBB, DL, TII->get(AArch64::SUBSXrs), AArch64::XZR)
291  .addReg(DestHi.getReg(), getKillRegState(DestHi.isDead()))
292  .addReg(DesiredHiReg)
293  .addImm(0);
294  BuildMI(LoadCmpBB, DL, TII->get(AArch64::CSINCWr), StatusReg)
295  .addUse(StatusReg, RegState::Kill)
296  .addUse(StatusReg, RegState::Kill)
298  BuildMI(LoadCmpBB, DL, TII->get(AArch64::CBNZW))
299  .addUse(StatusReg, getKillRegState(StatusDead))
300  .addMBB(DoneBB);
301  LoadCmpBB->addSuccessor(DoneBB);
302  LoadCmpBB->addSuccessor(StoreBB);
303 
304  // .Lstore:
305  // stlxp wStatus, xNewLo, xNewHi, [xAddr]
306  // cbnz wStatus, .Lloadcmp
307  BuildMI(StoreBB, DL, TII->get(AArch64::STLXPX), StatusReg)
308  .addReg(NewLoReg)
309  .addReg(NewHiReg)
310  .addReg(AddrReg);
311  BuildMI(StoreBB, DL, TII->get(AArch64::CBNZW))
312  .addReg(StatusReg, getKillRegState(StatusDead))
313  .addMBB(LoadCmpBB);
314  StoreBB->addSuccessor(LoadCmpBB);
315  StoreBB->addSuccessor(DoneBB);
316 
317  DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
318  DoneBB->transferSuccessors(&MBB);
319 
320  MBB.addSuccessor(LoadCmpBB);
321 
322  NextMBBI = MBB.end();
323  MI.eraseFromParent();
324 
325  // Recompute liveness bottom up.
326  LivePhysRegs LiveRegs;
327  computeAndAddLiveIns(LiveRegs, *DoneBB);
328  computeAndAddLiveIns(LiveRegs, *StoreBB);
329  computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
330  // Do an extra pass in the loop to get the loop carried dependencies right.
331  StoreBB->clearLiveIns();
332  computeAndAddLiveIns(LiveRegs, *StoreBB);
333  LoadCmpBB->clearLiveIns();
334  computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
335 
336  return true;
337 }
338 
339 /// If MBBI references a pseudo instruction that should be expanded here,
340 /// do the expansion and return true. Otherwise return false.
341 bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
343  MachineBasicBlock::iterator &NextMBBI) {
344  MachineInstr &MI = *MBBI;
345  unsigned Opcode = MI.getOpcode();
346  switch (Opcode) {
347  default:
348  break;
349 
350  case AArch64::ADDWrr:
351  case AArch64::SUBWrr:
352  case AArch64::ADDXrr:
353  case AArch64::SUBXrr:
354  case AArch64::ADDSWrr:
355  case AArch64::SUBSWrr:
356  case AArch64::ADDSXrr:
357  case AArch64::SUBSXrr:
358  case AArch64::ANDWrr:
359  case AArch64::ANDXrr:
360  case AArch64::BICWrr:
361  case AArch64::BICXrr:
362  case AArch64::ANDSWrr:
363  case AArch64::ANDSXrr:
364  case AArch64::BICSWrr:
365  case AArch64::BICSXrr:
366  case AArch64::EONWrr:
367  case AArch64::EONXrr:
368  case AArch64::EORWrr:
369  case AArch64::EORXrr:
370  case AArch64::ORNWrr:
371  case AArch64::ORNXrr:
372  case AArch64::ORRWrr:
373  case AArch64::ORRXrr: {
374  unsigned Opcode;
375  switch (MI.getOpcode()) {
376  default:
377  return false;
378  case AArch64::ADDWrr: Opcode = AArch64::ADDWrs; break;
379  case AArch64::SUBWrr: Opcode = AArch64::SUBWrs; break;
380  case AArch64::ADDXrr: Opcode = AArch64::ADDXrs; break;
381  case AArch64::SUBXrr: Opcode = AArch64::SUBXrs; break;
382  case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs; break;
383  case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs; break;
384  case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs; break;
385  case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs; break;
386  case AArch64::ANDWrr: Opcode = AArch64::ANDWrs; break;
387  case AArch64::ANDXrr: Opcode = AArch64::ANDXrs; break;
388  case AArch64::BICWrr: Opcode = AArch64::BICWrs; break;
389  case AArch64::BICXrr: Opcode = AArch64::BICXrs; break;
390  case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs; break;
391  case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs; break;
392  case AArch64::BICSWrr: Opcode = AArch64::BICSWrs; break;
393  case AArch64::BICSXrr: Opcode = AArch64::BICSXrs; break;
394  case AArch64::EONWrr: Opcode = AArch64::EONWrs; break;
395  case AArch64::EONXrr: Opcode = AArch64::EONXrs; break;
396  case AArch64::EORWrr: Opcode = AArch64::EORWrs; break;
397  case AArch64::EORXrr: Opcode = AArch64::EORXrs; break;
398  case AArch64::ORNWrr: Opcode = AArch64::ORNWrs; break;
399  case AArch64::ORNXrr: Opcode = AArch64::ORNXrs; break;
400  case AArch64::ORRWrr: Opcode = AArch64::ORRWrs; break;
401  case AArch64::ORRXrr: Opcode = AArch64::ORRXrs; break;
402  }
403  MachineInstrBuilder MIB1 =
404  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opcode),
405  MI.getOperand(0).getReg())
406  .add(MI.getOperand(1))
407  .add(MI.getOperand(2))
409  transferImpOps(MI, MIB1, MIB1);
410  MI.eraseFromParent();
411  return true;
412  }
413 
414  case AArch64::LOADgot: {
415  MachineFunction *MF = MBB.getParent();
416  unsigned DstReg = MI.getOperand(0).getReg();
417  const MachineOperand &MO1 = MI.getOperand(1);
418  unsigned Flags = MO1.getTargetFlags();
419 
420  if (MF->getTarget().getCodeModel() == CodeModel::Tiny) {
421  // Tiny codemodel expand to LDR
422  MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
423  TII->get(AArch64::LDRXl), DstReg);
424 
425  if (MO1.isGlobal()) {
426  MIB.addGlobalAddress(MO1.getGlobal(), 0, Flags);
427  } else if (MO1.isSymbol()) {
428  MIB.addExternalSymbol(MO1.getSymbolName(), Flags);
429  } else {
430  assert(MO1.isCPI() &&
431  "Only expect globals, externalsymbols, or constant pools");
432  MIB.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(), Flags);
433  }
434  } else {
435  // Small codemodel expand into ADRP + LDR.
436  MachineInstrBuilder MIB1 =
437  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg);
438  MachineInstrBuilder MIB2 =
439  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRXui))
440  .add(MI.getOperand(0))
441  .addReg(DstReg);
442 
443  if (MO1.isGlobal()) {
444  MIB1.addGlobalAddress(MO1.getGlobal(), 0, Flags | AArch64II::MO_PAGE);
445  MIB2.addGlobalAddress(MO1.getGlobal(), 0,
447  } else if (MO1.isSymbol()) {
449  MIB2.addExternalSymbol(MO1.getSymbolName(), Flags |
452  } else {
453  assert(MO1.isCPI() &&
454  "Only expect globals, externalsymbols, or constant pools");
455  MIB1.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
456  Flags | AArch64II::MO_PAGE);
457  MIB2.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
458  Flags | AArch64II::MO_PAGEOFF |
460  }
461 
462  transferImpOps(MI, MIB1, MIB2);
463  }
464  MI.eraseFromParent();
465  return true;
466  }
467 
468  case AArch64::MOVaddr:
469  case AArch64::MOVaddrJT:
470  case AArch64::MOVaddrCP:
471  case AArch64::MOVaddrBA:
472  case AArch64::MOVaddrTLS:
473  case AArch64::MOVaddrEXT: {
474  // Expand into ADRP + ADD.
475  unsigned DstReg = MI.getOperand(0).getReg();
476  MachineInstrBuilder MIB1 =
477  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
478  .add(MI.getOperand(1));
479 
480  MachineInstrBuilder MIB2 =
481  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
482  .add(MI.getOperand(0))
483  .addReg(DstReg)
484  .add(MI.getOperand(2))
485  .addImm(0);
486 
487  transferImpOps(MI, MIB1, MIB2);
488  MI.eraseFromParent();
489  return true;
490  }
491  case AArch64::ADDlowTLS:
492  // Produce a plain ADD
493  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
494  .add(MI.getOperand(0))
495  .add(MI.getOperand(1))
496  .add(MI.getOperand(2))
497  .addImm(0);
498  MI.eraseFromParent();
499  return true;
500 
501  case AArch64::MOVbaseTLS: {
502  unsigned DstReg = MI.getOperand(0).getReg();
503  auto SysReg = AArch64SysReg::TPIDR_EL0;
504  MachineFunction *MF = MBB.getParent();
505  if (MF->getTarget().getTargetTriple().isOSFuchsia() &&
507  SysReg = AArch64SysReg::TPIDR_EL1;
508  else if (MF->getSubtarget<AArch64Subtarget>().useEL3ForTP())
509  SysReg = AArch64SysReg::TPIDR_EL3;
510  else if (MF->getSubtarget<AArch64Subtarget>().useEL2ForTP())
511  SysReg = AArch64SysReg::TPIDR_EL2;
512  else if (MF->getSubtarget<AArch64Subtarget>().useEL1ForTP())
513  SysReg = AArch64SysReg::TPIDR_EL1;
514  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MRS), DstReg)
515  .addImm(SysReg);
516  MI.eraseFromParent();
517  return true;
518  }
519 
520  case AArch64::MOVi32imm:
521  return expandMOVImm(MBB, MBBI, 32);
522  case AArch64::MOVi64imm:
523  return expandMOVImm(MBB, MBBI, 64);
524  case AArch64::RET_ReallyLR: {
525  // Hiding the LR use with RET_ReallyLR may lead to extra kills in the
526  // function and missing live-ins. We are fine in practice because callee
527  // saved register handling ensures the register value is restored before
528  // RET, but we need the undef flag here to appease the MachineVerifier
529  // liveness checks.
530  MachineInstrBuilder MIB =
531  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::RET))
532  .addReg(AArch64::LR, RegState::Undef);
533  transferImpOps(MI, MIB, MIB);
534  MI.eraseFromParent();
535  return true;
536  }
537  case AArch64::CMP_SWAP_8:
538  return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRB, AArch64::STLXRB,
539  AArch64::SUBSWrx,
541  AArch64::WZR, NextMBBI);
542  case AArch64::CMP_SWAP_16:
543  return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRH, AArch64::STLXRH,
544  AArch64::SUBSWrx,
546  AArch64::WZR, NextMBBI);
547  case AArch64::CMP_SWAP_32:
548  return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRW, AArch64::STLXRW,
549  AArch64::SUBSWrs,
551  AArch64::WZR, NextMBBI);
552  case AArch64::CMP_SWAP_64:
553  return expandCMP_SWAP(MBB, MBBI,
554  AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
556  AArch64::XZR, NextMBBI);
557  case AArch64::CMP_SWAP_128:
558  return expandCMP_SWAP_128(MBB, MBBI, NextMBBI);
559 
560  case AArch64::AESMCrrTied:
561  case AArch64::AESIMCrrTied: {
562  MachineInstrBuilder MIB =
563  BuildMI(MBB, MBBI, MI.getDebugLoc(),
564  TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
565  AArch64::AESIMCrr))
566  .add(MI.getOperand(0))
567  .add(MI.getOperand(1));
568  transferImpOps(MI, MIB, MIB);
569  MI.eraseFromParent();
570  return true;
571  }
572  }
573  return false;
574 }
575 
576 /// Iterate over the instructions in basic block MBB and expand any
577 /// pseudo instructions. Return true if anything was modified.
578 bool AArch64ExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
579  bool Modified = false;
580 
581  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
582  while (MBBI != E) {
583  MachineBasicBlock::iterator NMBBI = std::next(MBBI);
584  Modified |= expandMI(MBB, MBBI, NMBBI);
585  MBBI = NMBBI;
586  }
587 
588  return Modified;
589 }
590 
591 bool AArch64ExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
592  TII = static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo());
593 
594  bool Modified = false;
595  for (auto &MBB : MF)
596  Modified |= expandMBB(MBB);
597  return Modified;
598 }
599 
600 /// Returns an instance of the pseudo instruction expansion pass.
602  return new AArch64ExpandPseudo();
603 }
unsigned getTargetFlags() const
const MachineInstrBuilder & add(const MachineOperand &MO) const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:385
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:164
A debug info location.
Definition: DebugLoc.h:33
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isOSFuchsia() const
Definition: Triple.h:505
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:211
const HexagonInstrInfo * TII
INITIALIZE_PASS(AArch64ExpandPseudo, "aarch64-expand-pseudo", AARCH64_EXPAND_PSEUDO_NAME, false, false) static void transferImpOps(MachineInstr &OldMI
Transfer implicit operands on the pseudo instruction to the instructions created from the expansion...
const MachineInstrBuilder & addUse(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:411
const char * getSymbolName() const
virtual const TargetInstrInfo * getInstrInfo() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
unsigned getKillRegState(bool B)
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
unsigned getDeadRegState(bool B)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void initializeAArch64ExpandPseudoPass(PassRegistry &)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineInstrBuilder & UseMI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const GlobalValue * getGlobal() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
const Triple & getTargetTriple() const
self_iterator getIterator()
Definition: ilist_node.h:81
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
size_t size() const
Definition: SmallVector.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
Definition: FileCheck.cpp:218
MachineOperand class - Representation of each machine instruction operand.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
MachineInstrBuilder MachineInstrBuilder & DefMI
FunctionPass * createAArch64ExpandPseudoPass()
Returns an instance of the pseudo instruction expansion pass.
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned char TargetFlags=0) const
int64_t getImm() const
CodeModel::Model getCodeModel() const
Returns the code model.
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
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...
Representation of each machine instruction.
Definition: MachineInstr.h:64
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
A set of physical registers with utility functions to track liveness when walking backward/forward th...
Definition: LivePhysRegs.h:48
int64_t getOffset() const
Return the offset from the symbol in this operand.
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned char TargetFlags=0) const
#define I(x, y, z)
Definition: MD5.cpp:58
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
#define AARCH64_EXPAND_PSEUDO_NAME
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void insert(iterator MBBI, MachineBasicBlock *MBB)
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow...
Register getReg() const
getReg - Returns the register number.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:416