1dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines//==-- AArch64ExpandPseudoInsts.cpp - Expand pseudo instructions --*- C++ -*-=//
236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//                     The LLVM Compiler Infrastructure
436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file is distributed under the University of Illinois Open Source
636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// License. See LICENSE.TXT for details.
736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===//
936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file contains a pass that expands pseudo instructions into target
1136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// instructions to allow proper scheduling and other late optimizations.  This
1236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// pass should be run after register allocation but before the post-regalloc
1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// scheduling pass.
1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===//
1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
17dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "MCTargetDesc/AArch64AddressingModes.h"
18dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "AArch64InstrInfo.h"
1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/CodeGen/MachineFunctionPass.h"
2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/CodeGen/MachineInstrBuilder.h"
2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/MathExtras.h"
2236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesusing namespace llvm;
2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace {
25dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass AArch64ExpandPseudo : public MachineFunctionPass {
2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinespublic:
2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  static char ID;
28dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  AArch64ExpandPseudo() : MachineFunctionPass(ID) {}
2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
30dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  const AArch64InstrInfo *TII;
3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
32dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  bool runOnMachineFunction(MachineFunction &Fn) override;
3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
34dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  const char *getPassName() const override {
35dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return "AArch64 pseudo instruction expansion pass";
3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesprivate:
3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool expandMBB(MachineBasicBlock &MBB);
4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool expandMOVImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                    unsigned BitSize);
4336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines};
44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hineschar AArch64ExpandPseudo::ID = 0;
4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Transfer implicit operands on the pseudo instruction to the
4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// instructions created from the expansion.
4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void transferImpOps(MachineInstr &OldMI, MachineInstrBuilder &UseMI,
5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                           MachineInstrBuilder &DefMI) {
5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const MCInstrDesc &Desc = OldMI.getDesc();
5236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands(); i != e;
5336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines       ++i) {
5436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MachineOperand &MO = OldMI.getOperand(i);
5536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    assert(MO.isReg() && MO.getReg());
5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (MO.isUse())
5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      UseMI.addOperand(MO);
5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    else
5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      DefMI.addOperand(MO);
6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Helper function which extracts the specified 16-bit chunk from a
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// 64-bit value.
6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic uint64_t getChunk(uint64_t Imm, unsigned ChunkIdx) {
6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  assert(ChunkIdx < 4 && "Out of range chunk index specified!");
6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return (Imm >> (ChunkIdx * 16)) & 0xFFFF;
6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Helper function which replicates a 16-bit chunk within a 64-bit
7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// value. Indices correspond to element numbers in a v4i16.
7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic uint64_t replicateChunk(uint64_t Imm, unsigned FromIdx, unsigned ToIdx) {
7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  assert((FromIdx < 4) && (ToIdx < 4) && "Out of range chunk index specified!");
7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const unsigned ShiftAmt = ToIdx * 16;
7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Replicate the source chunk to the destination position.
7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const uint64_t Chunk = getChunk(Imm, FromIdx) << ShiftAmt;
7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Clear the destination chunk.
8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  Imm &= ~(0xFFFFLL << ShiftAmt);
8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Insert the replicated chunk.
8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return Imm | Chunk;
8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Helper function which tries to materialize a 64-bit value with an
8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// ORR + MOVK instruction sequence.
8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool tryOrrMovk(uint64_t UImm, uint64_t OrrImm, MachineInstr &MI,
8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                       MachineBasicBlock &MBB,
8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                       MachineBasicBlock::iterator &MBBI,
90dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                       const AArch64InstrInfo *TII, unsigned ChunkIdx) {
9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  assert(ChunkIdx < 4 && "Out of range chunk index specified!");
9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const unsigned ShiftAmt = ChunkIdx * 16;
9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t Encoding;
95dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (AArch64_AM::processLogicalImmediate(OrrImm, 64, Encoding)) {
9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Create the ORR-immediate instruction.
9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB =
98dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXri))
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(0))
100dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            .addReg(AArch64::XZR)
10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addImm(Encoding);
10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Create the MOVK instruction.
10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const unsigned Imm16 = getChunk(UImm, ChunkIdx);
10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const unsigned DstReg = MI.getOperand(0).getReg();
10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const bool DstIsDead = MI.getOperand(0).isDead();
10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB1 =
108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi))
10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addReg(DstReg)
11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addImm(Imm16)
112dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt));
11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB, MIB1);
11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return false;
12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Check whether the given 16-bit chunk replicated to full 64-bit width
12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// can be materialized with an ORR instruction.
12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool canUseOrr(uint64_t Chunk, uint64_t &Encoding) {
12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  Chunk = (Chunk << 48) | (Chunk << 32) | (Chunk << 16) | Chunk;
12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
127dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return AArch64_AM::processLogicalImmediate(Chunk, 64, Encoding);
12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Check for identical 16-bit chunks within the constant and if so
13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// materialize them with a single ORR instruction. The remaining one or two
13236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// 16-bit chunks will be materialized with MOVK instructions.
13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// This allows us to materialize constants like |A|B|A|A| or |A|B|C|A| (order
13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// of the chunks doesn't matter), assuming |A|A|A|A| can be materialized with
13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// an ORR instruction.
13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
13836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool tryToreplicateChunks(uint64_t UImm, MachineInstr &MI,
13936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                 MachineBasicBlock &MBB,
14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                 MachineBasicBlock::iterator &MBBI,
141dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                 const AArch64InstrInfo *TII) {
14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  typedef DenseMap<uint64_t, unsigned> CountMap;
14336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  CountMap Counts;
14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
14536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Scan the constant and count how often every chunk occurs.
14636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (unsigned Idx = 0; Idx < 4; ++Idx)
14736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    ++Counts[getChunk(UImm, Idx)];
14836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Traverse the chunks to find one which occurs more than once.
15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (CountMap::const_iterator Chunk = Counts.begin(), End = Counts.end();
15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines       Chunk != End; ++Chunk) {
15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const uint64_t ChunkVal = Chunk->first;
15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const unsigned Count = Chunk->second;
15436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
15536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint64_t Encoding = 0;
15636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // We are looking for chunks which have two or three instances and can be
15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // materialized with an ORR instruction.
15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if ((Count != 2 && Count != 3) || !canUseOrr(ChunkVal, Encoding))
16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue;
16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const bool CountThree = Count == 3;
16336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Create the ORR-immediate instruction.
16436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB =
165dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXri))
16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(0))
167dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            .addReg(AArch64::XZR)
16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addImm(Encoding);
16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const unsigned DstReg = MI.getOperand(0).getReg();
17136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const bool DstIsDead = MI.getOperand(0).isDead();
17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned ShiftAmt = 0;
17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint64_t Imm16 = 0;
17536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Find the first chunk not materialized with the ORR instruction.
17636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (; ShiftAmt < 64; ShiftAmt += 16) {
17736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Imm16 = (UImm >> ShiftAmt) & 0xFFFF;
17836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (Imm16 != ChunkVal)
18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        break;
18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
18236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Create the first MOVK instruction.
18436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB1 =
185dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi))
18636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addReg(DstReg,
18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                    RegState::Define | getDeadRegState(DstIsDead && CountThree))
18836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addReg(DstReg)
18936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addImm(Imm16)
190dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt));
19136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
19236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // In case we have three instances the whole constant is now materialized
19336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // and we can exit.
19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (CountThree) {
19536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      transferImpOps(MI, MIB, MIB1);
19636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MI.eraseFromParent();
19736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
19836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
19936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
20036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Find the remaining chunk which needs to be materialized.
20136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (ShiftAmt += 16; ShiftAmt < 64; ShiftAmt += 16) {
20236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Imm16 = (UImm >> ShiftAmt) & 0xFFFF;
20336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (Imm16 != ChunkVal)
20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        break;
20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Create the second MOVK instruction.
20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB2 =
210dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi))
21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addReg(DstReg)
21336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addImm(Imm16)
214dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt));
21536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB, MIB2);
21736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
21836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
22036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return false;
22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
22336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
22436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Check whether this chunk matches the pattern '1...0...'. This pattern
22536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// starts a contiguous sequence of ones if we look at the bits from the LSB
22636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// towards the MSB.
22736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool isStartChunk(uint64_t Chunk) {
22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (Chunk == 0 || Chunk == UINT64_MAX)
22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return false;
23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return (CountLeadingOnes_64(Chunk) + countTrailingZeros(Chunk)) == 64;
23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
23336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Check whether this chunk matches the pattern '0...1...' This pattern
23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// ends a contiguous sequence of ones if we look at the bits from the LSB
23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// towards the MSB.
23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool isEndChunk(uint64_t Chunk) {
23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (Chunk == 0 || Chunk == UINT64_MAX)
23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return false;
24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return (countLeadingZeros(Chunk) + CountTrailingOnes_64(Chunk)) == 64;
24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
24436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Clear or set all bits in the chunk at the given index.
24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic uint64_t updateImm(uint64_t Imm, unsigned Idx, bool Clear) {
24636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const uint64_t Mask = 0xFFFF;
24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (Clear)
24936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Clear chunk in the immediate.
25036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Imm &= ~(Mask << (Idx * 16));
25136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  else
25236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Set all bits in the immediate for the particular chunk.
25336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Imm |= Mask << (Idx * 16);
25436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
25536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return Imm;
25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
25736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
25836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Check whether the constant contains a sequence of contiguous ones,
25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// which might be interrupted by one or two chunks. If so, materialize the
26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// sequence of contiguous ones with an ORR instruction.
26136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Materialize the chunks which are either interrupting the sequence or outside
26236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// of the sequence with a MOVK instruction.
26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Assuming S is a chunk which starts the sequence (1...0...), E is a chunk
26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// which ends the sequence (0...1...). Then we are looking for constants which
26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// contain at least one S and E chunk.
26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// E.g. |E|A|B|S|, |A|E|B|S| or |A|B|E|S|.
26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
26936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// We are also looking for constants like |S|A|B|E| where the contiguous
27036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// sequence of ones wraps around the MSB into the LSB.
27136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
27236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool trySequenceOfOnes(uint64_t UImm, MachineInstr &MI,
27336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                              MachineBasicBlock &MBB,
27436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                              MachineBasicBlock::iterator &MBBI,
275dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                              const AArch64InstrInfo *TII) {
27636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const int NotSet = -1;
27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const uint64_t Mask = 0xFFFF;
27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  int StartIdx = NotSet;
28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  int EndIdx = NotSet;
28136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Try to find the chunks which start/end a contiguous sequence of ones.
28236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (int Idx = 0; Idx < 4; ++Idx) {
28336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    int64_t Chunk = getChunk(UImm, Idx);
28436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Sign extend the 16-bit chunk to 64-bit.
28536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Chunk = (Chunk << 48) >> 48;
28636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
28736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (isStartChunk(Chunk))
28836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      StartIdx = Idx;
28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    else if (isEndChunk(Chunk))
29036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      EndIdx = Idx;
29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
29236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
29336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Early exit in case we can't find a start/end chunk.
29436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (StartIdx == NotSet || EndIdx == NotSet)
29536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return false;
29636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
29736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Outside of the contiguous sequence of ones everything needs to be zero.
29836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t Outside = 0;
29936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Chunks between the start and end chunk need to have all their bits set.
30036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t Inside = Mask;
30136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
30236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // If our contiguous sequence of ones wraps around from the MSB into the LSB,
30336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // just swap indices and pretend we are materializing a contiguous sequence
30436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // of zeros surrounded by a contiguous sequence of ones.
30536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (StartIdx > EndIdx) {
30636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::swap(StartIdx, EndIdx);
30736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::swap(Outside, Inside);
30836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
30936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
31036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t OrrImm = UImm;
31136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  int FirstMovkIdx = NotSet;
31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  int SecondMovkIdx = NotSet;
31336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
31436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Find out which chunks we need to patch up to obtain a contiguous sequence
31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // of ones.
31636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (int Idx = 0; Idx < 4; ++Idx) {
31736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const uint64_t Chunk = getChunk(UImm, Idx);
31836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
31936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Check whether we are looking at a chunk which is not part of the
32036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // contiguous sequence of ones.
32136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if ((Idx < StartIdx || EndIdx < Idx) && Chunk != Outside) {
32236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      OrrImm = updateImm(OrrImm, Idx, Outside == 0);
32336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Remember the index we need to patch.
32536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (FirstMovkIdx == NotSet)
32636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        FirstMovkIdx = Idx;
32736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      else
32836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        SecondMovkIdx = Idx;
32936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
33036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Check whether we are looking a chunk which is part of the contiguous
33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // sequence of ones.
33236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else if (Idx > StartIdx && Idx < EndIdx && Chunk != Inside) {
33336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      OrrImm = updateImm(OrrImm, Idx, Inside != Mask);
33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Remember the index we need to patch.
33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (FirstMovkIdx == NotSet)
33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        FirstMovkIdx = Idx;
33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      else
33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        SecondMovkIdx = Idx;
34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
34136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  assert(FirstMovkIdx != NotSet && "Constant materializable with single ORR!");
34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Create the ORR-immediate instruction.
34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t Encoding = 0;
346dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  AArch64_AM::processLogicalImmediate(OrrImm, 64, Encoding);
34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineInstrBuilder MIB =
348dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXri))
34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addOperand(MI.getOperand(0))
350dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          .addReg(AArch64::XZR)
35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addImm(Encoding);
35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const unsigned DstReg = MI.getOperand(0).getReg();
35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const bool DstIsDead = MI.getOperand(0).isDead();
35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const bool SingleMovk = SecondMovkIdx == NotSet;
35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Create the first MOVK instruction.
35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineInstrBuilder MIB1 =
359dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi))
36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addReg(DstReg,
36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                  RegState::Define | getDeadRegState(DstIsDead && SingleMovk))
36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addReg(DstReg)
36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addImm(getChunk(UImm, FirstMovkIdx))
364dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          .addImm(
365dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              AArch64_AM::getShifterImm(AArch64_AM::LSL, FirstMovkIdx * 16));
36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Early exit in case we only need to emit a single MOVK instruction.
36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (SingleMovk) {
36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB, MIB1);
37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
37136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
37436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Create the second MOVK instruction.
37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineInstrBuilder MIB2 =
376dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi))
37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addReg(DstReg)
37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addImm(getChunk(UImm, SecondMovkIdx))
380dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          .addImm(
381dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              AArch64_AM::getShifterImm(AArch64_AM::LSL, SecondMovkIdx * 16));
38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
38336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  transferImpOps(MI, MIB, MIB2);
38436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MI.eraseFromParent();
38536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return true;
38636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
38736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
38836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more
38936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// real move-immediate instructions to synthesize the immediate.
390dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool AArch64ExpandPseudo::expandMOVImm(MachineBasicBlock &MBB,
391dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                       MachineBasicBlock::iterator MBBI,
392dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                       unsigned BitSize) {
39336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineInstr &MI = *MBBI;
39436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t Imm = MI.getOperand(1).getImm();
39536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const unsigned Mask = 0xFFFF;
39636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
39736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Try a MOVI instruction (aka ORR-immediate with the zero register).
39836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t UImm = Imm << (64 - BitSize) >> (64 - BitSize);
39936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t Encoding;
400dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding)) {
401dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    unsigned Opc = (BitSize == 32 ? AArch64::ORRWri : AArch64::ORRXri);
40236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB =
40336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc))
40436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(0))
405dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            .addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
40636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addImm(Encoding);
40736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB, MIB);
40836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
40936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
41036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
41136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
41236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Scan the immediate and count the number of 16-bit chunks which are either
41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // all ones or all zeros.
41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned OneChunks = 0;
41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned ZeroChunks = 0;
41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (unsigned Shift = 0; Shift < BitSize; Shift += 16) {
41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const unsigned Chunk = (Imm >> Shift) & Mask;
41836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Chunk == Mask)
41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      OneChunks++;
42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    else if (Chunk == 0)
42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      ZeroChunks++;
42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
42336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
42436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Since we can't materialize the constant with a single ORR instruction,
42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // let's see whether we can materialize 3/4 of the constant with an ORR
42636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // instruction and use an additional MOVK instruction to materialize the
42736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // remaining 1/4.
42836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  //
42936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // We are looking for constants with a pattern like: |A|X|B|X| or |X|A|X|B|.
43036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  //
43136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // E.g. assuming |A|X|A|X| is a pattern which can be materialized with ORR,
43236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // we would create the following instruction sequence:
43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  //
43436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // ORR x0, xzr, |A|X|A|X|
43536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // MOVK x0, |B|, LSL #16
43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  //
43736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Only look at 64-bit constants which can't be materialized with a single
43836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // instruction e.g. which have less than either three all zero or all one
43936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // chunks.
44036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  //
44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Ignore 32-bit constants here, they always can be materialized with a
44236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // MOVZ/MOVN + MOVK pair. Since the 32-bit constant can't be materialized
44336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // with a single ORR, the best sequence we can achieve is a ORR + MOVK pair.
44436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Thus we fall back to the default code below which in the best case creates
44536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // a single MOVZ/MOVN instruction (in case one chunk is all zero or all one).
44636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  //
44736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (BitSize == 64 && OneChunks < 3 && ZeroChunks < 3) {
44836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // If we interpret the 64-bit constant as a v4i16, are elements 0 and 2
44936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // identical?
45036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (getChunk(UImm, 0) == getChunk(UImm, 2)) {
45136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // See if we can come up with a constant which can be materialized with
45236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // ORR-immediate by replicating element 3 into element 1.
45336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      uint64_t OrrImm = replicateChunk(UImm, 3, 1);
45436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (tryOrrMovk(UImm, OrrImm, MI, MBB, MBBI, TII, 1))
45536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return true;
45636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
45736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // See if we can come up with a constant which can be materialized with
45836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // ORR-immediate by replicating element 1 into element 3.
45936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      OrrImm = replicateChunk(UImm, 1, 3);
46036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (tryOrrMovk(UImm, OrrImm, MI, MBB, MBBI, TII, 3))
46136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return true;
46236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
46336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // If we interpret the 64-bit constant as a v4i16, are elements 1 and 3
46436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // identical?
46536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else if (getChunk(UImm, 1) == getChunk(UImm, 3)) {
46636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // See if we can come up with a constant which can be materialized with
46736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // ORR-immediate by replicating element 2 into element 0.
46836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      uint64_t OrrImm = replicateChunk(UImm, 2, 0);
46936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (tryOrrMovk(UImm, OrrImm, MI, MBB, MBBI, TII, 0))
47036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return true;
47136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
47236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // See if we can come up with a constant which can be materialized with
47336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // ORR-immediate by replicating element 1 into element 3.
47436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      OrrImm = replicateChunk(UImm, 0, 2);
47536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (tryOrrMovk(UImm, OrrImm, MI, MBB, MBBI, TII, 2))
47636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return true;
47736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
47836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
47936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
48036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Check for identical 16-bit chunks within the constant and if so materialize
48136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // them with a single ORR instruction. The remaining one or two 16-bit chunks
48236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // will be materialized with MOVK instructions.
48336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (BitSize == 64 && tryToreplicateChunks(UImm, MI, MBB, MBBI, TII))
48436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
48536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
48636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Check whether the constant contains a sequence of contiguous ones, which
48736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // might be interrupted by one or two chunks. If so, materialize the sequence
48836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // of contiguous ones with an ORR instruction. Materialize the chunks which
48936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // are either interrupting the sequence or outside of the sequence with a
49036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // MOVK instruction.
49136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (BitSize == 64 && trySequenceOfOnes(UImm, MI, MBB, MBBI, TII))
49236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
49336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
49436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Use a MOVZ or MOVN instruction to set the high bits, followed by one or
49536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // more MOVK instructions to insert additional 16-bit portions into the
49636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // lower bits.
49736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool isNeg = false;
49836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
49936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Use MOVN to materialize the high bits if we have more all one chunks
50036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // than all zero chunks.
50136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (OneChunks > ZeroChunks) {
50236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    isNeg = true;
50336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Imm = ~Imm;
50436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
50536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
50636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned FirstOpc;
50736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (BitSize == 32) {
50836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Imm &= (1LL << 32) - 1;
509dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    FirstOpc = (isNeg ? AArch64::MOVNWi : AArch64::MOVZWi);
51036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  } else {
511dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    FirstOpc = (isNeg ? AArch64::MOVNXi : AArch64::MOVZXi);
51236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned Shift = 0;     // LSL amount for high bits with MOVZ/MOVN
51436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned LastShift = 0; // LSL amount for last MOVK
51536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (Imm != 0) {
51636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned LZ = countLeadingZeros(Imm);
51736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned TZ = countTrailingZeros(Imm);
51836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Shift = ((63 - LZ) / 16) * 16;
51936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    LastShift = (TZ / 16) * 16;
52036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
52136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned Imm16 = (Imm >> Shift) & Mask;
52236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned DstReg = MI.getOperand(0).getReg();
52336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool DstIsDead = MI.getOperand(0).isDead();
52436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineInstrBuilder MIB1 =
52536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(FirstOpc))
52636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addReg(DstReg, RegState::Define |
52736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                              getDeadRegState(DstIsDead && Shift == LastShift))
52836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          .addImm(Imm16)
529dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, Shift));
53036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
53136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // If a MOVN was used for the high bits of a negative value, flip the rest
53236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // of the bits back for use with MOVK.
53336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (isNeg)
53436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Imm = ~Imm;
53536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
53636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (Shift == LastShift) {
53736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB1, MIB1);
53836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
53936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
54036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
54136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
54236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineInstrBuilder MIB2;
543dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  unsigned Opc = (BitSize == 32 ? AArch64::MOVKWi : AArch64::MOVKXi);
54436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  while (Shift != LastShift) {
54536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Shift -= 16;
54636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Imm16 = (Imm >> Shift) & Mask;
54736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Imm16 == (isNeg ? Mask : 0))
54836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      continue; // This 16-bit portion is already set correctly.
54936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc))
55036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines               .addReg(DstReg,
55136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                       RegState::Define |
55236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                           getDeadRegState(DstIsDead && Shift == LastShift))
55336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines               .addReg(DstReg)
55436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines               .addImm(Imm16)
555dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines               .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, Shift));
55636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
55736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
55836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  transferImpOps(MI, MIB1, MIB2);
55936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MI.eraseFromParent();
56036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return true;
56136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
56236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
56336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief If MBBI references a pseudo instruction that should be expanded here,
56436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// do the expansion and return true.  Otherwise return false.
565dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
56636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                 MachineBasicBlock::iterator MBBI) {
56736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineInstr &MI = *MBBI;
56836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned Opcode = MI.getOpcode();
56936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  switch (Opcode) {
57036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  default:
57136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    break;
57236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
573dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ADDWrr:
574dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::SUBWrr:
575dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ADDXrr:
576dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::SUBXrr:
577dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ADDSWrr:
578dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::SUBSWrr:
579dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ADDSXrr:
580dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::SUBSXrr:
581dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ANDWrr:
582dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ANDXrr:
583dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::BICWrr:
584dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::BICXrr:
585dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ANDSWrr:
586dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ANDSXrr:
587dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::BICSWrr:
588dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::BICSXrr:
589dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::EONWrr:
590dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::EONXrr:
591dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::EORWrr:
592dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::EORXrr:
593dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ORNWrr:
594dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ORNXrr:
595dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ORRWrr:
596dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::ORRXrr: {
59736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned Opcode;
59836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    switch (MI.getOpcode()) {
59936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    default:
60036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return false;
601dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ADDWrr:      Opcode = AArch64::ADDWrs; break;
602dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::SUBWrr:      Opcode = AArch64::SUBWrs; break;
603dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ADDXrr:      Opcode = AArch64::ADDXrs; break;
604dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::SUBXrr:      Opcode = AArch64::SUBXrs; break;
605dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ADDSWrr:     Opcode = AArch64::ADDSWrs; break;
606dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::SUBSWrr:     Opcode = AArch64::SUBSWrs; break;
607dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ADDSXrr:     Opcode = AArch64::ADDSXrs; break;
608dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::SUBSXrr:     Opcode = AArch64::SUBSXrs; break;
609dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ANDWrr:      Opcode = AArch64::ANDWrs; break;
610dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ANDXrr:      Opcode = AArch64::ANDXrs; break;
611dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::BICWrr:      Opcode = AArch64::BICWrs; break;
612dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::BICXrr:      Opcode = AArch64::BICXrs; break;
613dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ANDSWrr:     Opcode = AArch64::ANDSWrs; break;
614dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ANDSXrr:     Opcode = AArch64::ANDSXrs; break;
615dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::BICSWrr:     Opcode = AArch64::BICSWrs; break;
616dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::BICSXrr:     Opcode = AArch64::BICSXrs; break;
617dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::EONWrr:      Opcode = AArch64::EONWrs; break;
618dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::EONXrr:      Opcode = AArch64::EONXrs; break;
619dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::EORWrr:      Opcode = AArch64::EORWrs; break;
620dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::EORXrr:      Opcode = AArch64::EORXrs; break;
621dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ORNWrr:      Opcode = AArch64::ORNWrs; break;
622dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ORNXrr:      Opcode = AArch64::ORNXrs; break;
623dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ORRWrr:      Opcode = AArch64::ORRWrs; break;
624dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    case AArch64::ORRXrr:      Opcode = AArch64::ORRXrs; break;
62536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
62636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB1 =
62736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opcode),
62836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                MI.getOperand(0).getReg())
62936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(1))
63036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(2))
631dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
63236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB1, MIB1);
63336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
63436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
63536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
63636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
637dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::FCVTSHpseudo: {
63836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineOperand Src = MI.getOperand(1);
63936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Src.setImplicit();
640dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    unsigned SrcH =
641dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        TII->getRegisterInfo().getSubReg(Src.getReg(), AArch64::hsub);
642dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    auto MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::FCVTSHr))
64336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                   .addOperand(MI.getOperand(0))
64436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                   .addReg(SrcH, RegState::Undef)
64536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                   .addOperand(Src);
64636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB, MIB);
64736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
64836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
64936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
650dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::LOADgot: {
65136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Expand into ADRP + LDR.
65236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned DstReg = MI.getOperand(0).getReg();
65336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MachineOperand &MO1 = MI.getOperand(1);
65436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned Flags = MO1.getTargetFlags();
65536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB1 =
656dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg);
65736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB2 =
658dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRXui))
65936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(0))
66036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addReg(DstReg);
66136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
66236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (MO1.isGlobal()) {
663dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      MIB1.addGlobalAddress(MO1.getGlobal(), 0, Flags | AArch64II::MO_PAGE);
66436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MIB2.addGlobalAddress(MO1.getGlobal(), 0,
665dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            Flags | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
66636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else if (MO1.isSymbol()) {
667dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      MIB1.addExternalSymbol(MO1.getSymbolName(), Flags | AArch64II::MO_PAGE);
66836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MIB2.addExternalSymbol(MO1.getSymbolName(),
669dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                             Flags | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
67036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else {
67136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      assert(MO1.isCPI() &&
67236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines             "Only expect globals, externalsymbols, or constant pools");
67336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MIB1.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
674dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                Flags | AArch64II::MO_PAGE);
67536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MIB2.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
676dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                Flags | AArch64II::MO_PAGEOFF |
677dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                    AArch64II::MO_NC);
67836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
67936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
68036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB1, MIB2);
68136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
68236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
68336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
68436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
685dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::MOVaddr:
686dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::MOVaddrJT:
687dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::MOVaddrCP:
688dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::MOVaddrBA:
689dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::MOVaddrTLS:
690dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::MOVaddrEXT: {
69136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Expand into ADRP + ADD.
69236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned DstReg = MI.getOperand(0).getReg();
69336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB1 =
694dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
69536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(1));
69636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
69736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineInstrBuilder MIB2 =
698dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
69936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(0))
70036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addReg(DstReg)
70136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addOperand(MI.getOperand(2))
70236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            .addImm(0);
70336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
70436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    transferImpOps(MI, MIB1, MIB2);
70536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
70636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
70736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
70836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
709dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::MOVi32imm:
71036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return expandMOVImm(MBB, MBBI, 32);
711dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::MOVi64imm:
71236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return expandMOVImm(MBB, MBBI, 64);
713dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::RET_ReallyLR:
714dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::RET))
715dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        .addReg(AArch64::LR);
71636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MI.eraseFromParent();
71736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
71836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
71936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return false;
72036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
72136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
72236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Iterate over the instructions in basic block MBB and expand any
72336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// pseudo instructions.  Return true if anything was modified.
724dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool AArch64ExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
72536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool Modified = false;
72636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
72736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
72836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  while (MBBI != E) {
72936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachineBasicBlock::iterator NMBBI = std::next(MBBI);
73036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Modified |= expandMI(MBB, MBBI);
73136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MBBI = NMBBI;
73236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
73336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
73436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return Modified;
73536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
73636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
737dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool AArch64ExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
738dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  TII = static_cast<const AArch64InstrInfo *>(MF.getTarget().getInstrInfo());
73936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
74036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool Modified = false;
74136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (auto &MBB : MF)
74236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Modified |= expandMBB(MBB);
74336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return Modified;
74436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
74536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
74636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Returns an instance of the pseudo instruction expansion pass.
747dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesFunctionPass *llvm::createAArch64ExpandPseudoPass() {
748dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return new AArch64ExpandPseudo();
74936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
750