brintos

brintos / llvm-project-archived public Read only

0
0
Text · 30.2 KiB · efb92c9 Raw
867 lines · cpp
1//===- Thumb2InstrInfo.cpp - Thumb-2 Instruction Information --------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the Thumb-2 implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "Thumb2InstrInfo.h"14#include "ARMMachineFunctionInfo.h"15#include "ARMSubtarget.h"16#include "MCTargetDesc/ARMAddressingModes.h"17#include "llvm/CodeGen/MachineBasicBlock.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineFunction.h"20#include "llvm/CodeGen/MachineInstr.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/CodeGen/MachineMemOperand.h"23#include "llvm/CodeGen/MachineOperand.h"24#include "llvm/CodeGen/MachineRegisterInfo.h"25#include "llvm/CodeGen/TargetRegisterInfo.h"26#include "llvm/IR/DebugLoc.h"27#include "llvm/IR/Module.h"28#include "llvm/MC/MCInst.h"29#include "llvm/MC/MCInstBuilder.h"30#include "llvm/MC/MCInstrDesc.h"31#include "llvm/Support/CommandLine.h"32#include "llvm/Support/ErrorHandling.h"33#include "llvm/Target/TargetMachine.h"34#include <cassert>35 36using namespace llvm;37 38static cl::opt<bool>39OldT2IfCvt("old-thumb2-ifcvt", cl::Hidden,40           cl::desc("Use old-style Thumb2 if-conversion heuristics"),41           cl::init(false));42 43static cl::opt<bool>44PreferNoCSEL("prefer-no-csel", cl::Hidden,45             cl::desc("Prefer predicated Move to CSEL"),46             cl::init(false));47 48Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI)49    : ARMBaseInstrInfo(STI, RI), RI(STI) {}50 51/// Return the noop instruction to use for a noop.52MCInst Thumb2InstrInfo::getNop() const {53  return MCInstBuilder(ARM::tHINT).addImm(0).addImm(ARMCC::AL).addReg(0);54}55 56unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const {57  // FIXME58  return 0;59}60 61void62Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail,63                                         MachineBasicBlock *NewDest) const {64  MachineBasicBlock *MBB = Tail->getParent();65  ARMFunctionInfo *AFI = MBB->getParent()->getInfo<ARMFunctionInfo>();66  if (!AFI->hasITBlocks() || Tail->isBranch()) {67    TargetInstrInfo::ReplaceTailWithBranchTo(Tail, NewDest);68    return;69  }70 71  // If the first instruction of Tail is predicated, we may have to update72  // the IT instruction.73  Register PredReg;74  ARMCC::CondCodes CC = getInstrPredicate(*Tail, PredReg);75  MachineBasicBlock::iterator MBBI = Tail;76  if (CC != ARMCC::AL)77    // Expecting at least the t2IT instruction before it.78    --MBBI;79 80  // Actually replace the tail.81  TargetInstrInfo::ReplaceTailWithBranchTo(Tail, NewDest);82 83  // Fix up IT.84  if (CC != ARMCC::AL) {85    MachineBasicBlock::iterator E = MBB->begin();86    unsigned Count = 4; // At most 4 instructions in an IT block.87    while (Count && MBBI != E) {88      if (MBBI->isDebugInstr()) {89        --MBBI;90        continue;91      }92      if (MBBI->getOpcode() == ARM::t2IT) {93        unsigned Mask = MBBI->getOperand(1).getImm();94        if (Count == 4)95          MBBI->eraseFromParent();96        else {97          unsigned MaskOn = 1 << Count;98          unsigned MaskOff = ~(MaskOn - 1);99          MBBI->getOperand(1).setImm((Mask & MaskOff) | MaskOn);100        }101        return;102      }103      --MBBI;104      --Count;105    }106 107    // Ctrl flow can reach here if branch folding is run before IT block108    // formation pass.109  }110}111 112bool113Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,114                                     MachineBasicBlock::iterator MBBI) const {115  while (MBBI->isDebugInstr()) {116    ++MBBI;117    if (MBBI == MBB.end())118      return false;119  }120 121  Register PredReg;122  return getITInstrPredicate(*MBBI, PredReg) == ARMCC::AL;123}124 125MachineInstr *126Thumb2InstrInfo::optimizeSelect(MachineInstr &MI,127                                SmallPtrSetImpl<MachineInstr *> &SeenMIs,128                                bool PreferFalse) const {129  // Try to use the base optimizeSelect, which uses canFoldIntoMOVCC to fold the130  // MOVCC into another instruction. If that fails on 8.1-M fall back to using a131  // CSEL.132  MachineInstr *RV = ARMBaseInstrInfo::optimizeSelect(MI, SeenMIs, PreferFalse);133  if (!RV && getSubtarget().hasV8_1MMainlineOps() && !PreferNoCSEL) {134    Register DestReg = MI.getOperand(0).getReg();135 136    if (!DestReg.isVirtual())137      return nullptr;138 139    MachineInstrBuilder NewMI = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),140                                        get(ARM::t2CSEL), DestReg)141                                    .add(MI.getOperand(2))142                                    .add(MI.getOperand(1))143                                    .add(MI.getOperand(3));144    SeenMIs.insert(NewMI);145    return NewMI;146  }147  return RV;148}149 150void Thumb2InstrInfo::copyPhysReg(MachineBasicBlock &MBB,151                                  MachineBasicBlock::iterator I,152                                  const DebugLoc &DL, Register DestReg,153                                  Register SrcReg, bool KillSrc,154                                  bool RenamableDest, bool RenamableSrc) const {155  // Handle SPR, DPR, and QPR copies.156  if (!ARM::GPRRegClass.contains(DestReg, SrcReg))157    return ARMBaseInstrInfo::copyPhysReg(MBB, I, DL, DestReg, SrcReg, KillSrc);158 159  BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg)160      .addReg(SrcReg, getKillRegState(KillSrc))161      .add(predOps(ARMCC::AL));162}163 164void Thumb2InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,165                                          MachineBasicBlock::iterator I,166                                          Register SrcReg, bool isKill, int FI,167                                          const TargetRegisterClass *RC,168                                          Register VReg,169                                          MachineInstr::MIFlag Flags) const {170  DebugLoc DL;171  if (I != MBB.end()) DL = I->getDebugLoc();172 173  MachineFunction &MF = *MBB.getParent();174  MachineFrameInfo &MFI = MF.getFrameInfo();175  MachineMemOperand *MMO = MF.getMachineMemOperand(176      MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,177      MFI.getObjectSize(FI), MFI.getObjectAlign(FI));178 179  if (ARM::GPRRegClass.hasSubClassEq(RC)) {180    BuildMI(MBB, I, DL, get(ARM::t2STRi12))181        .addReg(SrcReg, getKillRegState(isKill))182        .addFrameIndex(FI)183        .addImm(0)184        .addMemOperand(MMO)185        .add(predOps(ARMCC::AL));186    return;187  }188 189  if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {190    // Thumb2 STRD expects its dest-registers to be in rGPR. Not a problem for191    // gsub_0, but needs an extra constraint for gsub_1 (which could be sp192    // otherwise).193    if (SrcReg.isVirtual()) {194      MachineRegisterInfo *MRI = &MF.getRegInfo();195      MRI->constrainRegClass(SrcReg, &ARM::GPRPairnospRegClass);196    }197 198    MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2STRDi8));199    AddDReg(MIB, SrcReg, ARM::gsub_0, getKillRegState(isKill));200    AddDReg(MIB, SrcReg, ARM::gsub_1, 0);201    MIB.addFrameIndex(FI).addImm(0).addMemOperand(MMO).add(predOps(ARMCC::AL));202    return;203  }204 205  ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC,206                                        Register());207}208 209void Thumb2InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,210                                           MachineBasicBlock::iterator I,211                                           Register DestReg, int FI,212                                           const TargetRegisterClass *RC,213                                           Register VReg,214                                           MachineInstr::MIFlag Flags) const {215  MachineFunction &MF = *MBB.getParent();216  MachineFrameInfo &MFI = MF.getFrameInfo();217  MachineMemOperand *MMO = MF.getMachineMemOperand(218      MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,219      MFI.getObjectSize(FI), MFI.getObjectAlign(FI));220  DebugLoc DL;221  if (I != MBB.end()) DL = I->getDebugLoc();222 223  if (ARM::GPRRegClass.hasSubClassEq(RC)) {224    BuildMI(MBB, I, DL, get(ARM::t2LDRi12), DestReg)225        .addFrameIndex(FI)226        .addImm(0)227        .addMemOperand(MMO)228        .add(predOps(ARMCC::AL));229    return;230  }231 232  if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {233    // Thumb2 LDRD expects its dest-registers to be in rGPR. Not a problem for234    // gsub_0, but needs an extra constraint for gsub_1 (which could be sp235    // otherwise).236    if (DestReg.isVirtual()) {237      MachineRegisterInfo *MRI = &MF.getRegInfo();238      MRI->constrainRegClass(DestReg, &ARM::GPRPairnospRegClass);239    }240 241    MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2LDRDi8));242    AddDReg(MIB, DestReg, ARM::gsub_0, RegState::DefineNoRead);243    AddDReg(MIB, DestReg, ARM::gsub_1, RegState::DefineNoRead);244    MIB.addFrameIndex(FI).addImm(0).addMemOperand(MMO).add(predOps(ARMCC::AL));245 246    if (DestReg.isPhysical())247      MIB.addReg(DestReg, RegState::ImplicitDefine);248    return;249  }250 251  ARMBaseInstrInfo::loadRegFromStackSlot(MBB, I, DestReg, FI, RC, Register());252}253 254void Thumb2InstrInfo::expandLoadStackGuard(255    MachineBasicBlock::iterator MI) const {256  MachineFunction &MF = *MI->getParent()->getParent();257  Module &M = *MF.getFunction().getParent();258 259  if (M.getStackProtectorGuard() == "tls") {260    expandLoadStackGuardBase(MI, ARM::t2MRC, ARM::t2LDRi12);261    return;262  }263 264  const auto *GV = cast<GlobalValue>((*MI->memoperands_begin())->getValue());265  const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>();266  bool IsPIC = MF.getTarget().isPositionIndependent();267  if (Subtarget.isTargetELF() && !GV->isDSOLocal())268    expandLoadStackGuardBase(MI, ARM::t2LDRLIT_ga_pcrel, ARM::t2LDRi12);269  else if (!Subtarget.useMovt())270    expandLoadStackGuardBase(271        MI, IsPIC ? ARM::t2LDRLIT_ga_pcrel : ARM::tLDRLIT_ga_abs,272        ARM::t2LDRi12);273  else if (IsPIC)274    expandLoadStackGuardBase(MI, ARM::t2MOV_ga_pcrel, ARM::t2LDRi12);275  else276    expandLoadStackGuardBase(MI, ARM::t2MOVi32imm, ARM::t2LDRi12);277}278 279MachineInstr *Thumb2InstrInfo::commuteInstructionImpl(MachineInstr &MI,280                                                      bool NewMI,281                                                      unsigned OpIdx1,282                                                      unsigned OpIdx2) const {283  switch (MI.getOpcode()) {284  case ARM::MVE_VMAXNMAf16:285  case ARM::MVE_VMAXNMAf32:286  case ARM::MVE_VMINNMAf16:287  case ARM::MVE_VMINNMAf32:288    // Don't allow predicated instructions to be commuted.289    if (getVPTInstrPredicate(MI) != ARMVCC::None)290      return nullptr;291  }292  return ARMBaseInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);293}294 295bool Thumb2InstrInfo::isSchedulingBoundary(const MachineInstr &MI,296                                           const MachineBasicBlock *MBB,297                                           const MachineFunction &MF) const {298  // BTI clearing instructions shall not take part in scheduling regions as299  // they must stay in their intended place. Although PAC isn't BTI clearing,300  // it can be transformed into PACBTI after the pre-RA Machine Scheduling301  // has taken place, so its movement must also be restricted.302  switch (MI.getOpcode()) {303  case ARM::t2BTI:304  case ARM::t2PAC:305  case ARM::t2PACBTI:306  case ARM::t2SG:307    return true;308  default:309    break;310  }311  return ARMBaseInstrInfo::isSchedulingBoundary(MI, MBB, MF);312}313 314void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,315                                  MachineBasicBlock::iterator &MBBI,316                                  const DebugLoc &dl, Register DestReg,317                                  Register BaseReg, int NumBytes,318                                  ARMCC::CondCodes Pred, Register PredReg,319                                  const ARMBaseInstrInfo &TII,320                                  unsigned MIFlags) {321  if (NumBytes == 0 && DestReg != BaseReg) {322    BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)323      .addReg(BaseReg, RegState::Kill)324      .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);325    return;326  }327 328  bool isSub = NumBytes < 0;329  if (isSub) NumBytes = -NumBytes;330 331  // If profitable, use a movw or movt to materialize the offset.332  // FIXME: Use the scavenger to grab a scratch register.333  if (DestReg != ARM::SP && DestReg != BaseReg &&334      NumBytes >= 4096 &&335      ARM_AM::getT2SOImmVal(NumBytes) == -1) {336    bool Fits = false;337    if (NumBytes < 65536) {338      // Use a movw to materialize the 16-bit constant.339      BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg)340        .addImm(NumBytes)341        .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);342      Fits = true;343    } else if ((NumBytes & 0xffff) == 0) {344      // Use a movt to materialize the 32-bit constant.345      BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg)346        .addReg(DestReg)347        .addImm(NumBytes >> 16)348        .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);349      Fits = true;350    }351 352    if (Fits) {353      if (isSub) {354        BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg)355            .addReg(BaseReg)356            .addReg(DestReg, RegState::Kill)357            .add(predOps(Pred, PredReg))358            .add(condCodeOp())359            .setMIFlags(MIFlags);360      } else {361        // Here we know that DestReg is not SP but we do not362        // know anything about BaseReg. t2ADDrr is an invalid363        // instruction is SP is used as the second argument, but364        // is fine if SP is the first argument. To be sure we365        // do not generate invalid encoding, put BaseReg first.366        BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg)367            .addReg(BaseReg)368            .addReg(DestReg, RegState::Kill)369            .add(predOps(Pred, PredReg))370            .add(condCodeOp())371            .setMIFlags(MIFlags);372      }373      return;374    }375  }376 377  while (NumBytes) {378    unsigned ThisVal = NumBytes;379    unsigned Opc = 0;380    if (DestReg == ARM::SP && BaseReg != ARM::SP) {381      // mov sp, rn. Note t2MOVr cannot be used.382      BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)383          .addReg(BaseReg)384          .setMIFlags(MIFlags)385          .add(predOps(ARMCC::AL));386      BaseReg = ARM::SP;387      continue;388    }389 390    assert((DestReg != ARM::SP || BaseReg == ARM::SP) &&391           "Writing to SP, from other register.");392 393    // Try to use T1, as it smaller394    if ((DestReg == ARM::SP) && (ThisVal < ((1 << 7) - 1) * 4)) {395      assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?");396      Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;397      BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)398          .addReg(BaseReg)399          .addImm(ThisVal / 4)400          .setMIFlags(MIFlags)401          .add(predOps(ARMCC::AL));402      break;403    }404    bool HasCCOut = true;405    int ImmIsT2SO = ARM_AM::getT2SOImmVal(ThisVal);406    bool ToSP = DestReg == ARM::SP;407    unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;408    unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;409    unsigned t2SUBi12 = ToSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12;410    unsigned t2ADDi12 = ToSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;411    Opc = isSub ? t2SUB : t2ADD;412    // Prefer T2: sub rd, rn, so_imm | sub sp, sp, so_imm413    if (ImmIsT2SO != -1) {414      NumBytes = 0;415    } else if (ThisVal < 4096) {416      // Prefer T3 if can make it in a single go: subw rd, rn, imm12 | subw sp,417      // sp, imm12418      Opc = isSub ? t2SUBi12 : t2ADDi12;419      HasCCOut = false;420      NumBytes = 0;421    } else {422      // Use one T2 instruction to reduce NumBytes423      // FIXME: Move this to ARMAddressingModes.h?424      unsigned RotAmt = llvm::countl_zero(ThisVal);425      ThisVal = ThisVal & llvm::rotr<uint32_t>(0xff000000U, RotAmt);426      NumBytes &= ~ThisVal;427      assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&428             "Bit extraction didn't work?");429    }430 431    // Build the new ADD / SUB.432    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)433                                  .addReg(BaseReg, RegState::Kill)434                                  .addImm(ThisVal)435                                  .add(predOps(ARMCC::AL))436                                  .setMIFlags(MIFlags);437    if (HasCCOut)438      MIB.add(condCodeOp());439 440    BaseReg = DestReg;441  }442}443 444static unsigned445negativeOffsetOpcode(unsigned opcode)446{447  switch (opcode) {448  case ARM::t2LDRi12:   return ARM::t2LDRi8;449  case ARM::t2LDRHi12:  return ARM::t2LDRHi8;450  case ARM::t2LDRBi12:  return ARM::t2LDRBi8;451  case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;452  case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;453  case ARM::t2STRi12:   return ARM::t2STRi8;454  case ARM::t2STRBi12:  return ARM::t2STRBi8;455  case ARM::t2STRHi12:  return ARM::t2STRHi8;456  case ARM::t2PLDi12:   return ARM::t2PLDi8;457  case ARM::t2PLDWi12:  return ARM::t2PLDWi8;458  case ARM::t2PLIi12:   return ARM::t2PLIi8;459 460  case ARM::t2LDRi8:461  case ARM::t2LDRHi8:462  case ARM::t2LDRBi8:463  case ARM::t2LDRSHi8:464  case ARM::t2LDRSBi8:465  case ARM::t2STRi8:466  case ARM::t2STRBi8:467  case ARM::t2STRHi8:468  case ARM::t2PLDi8:469  case ARM::t2PLDWi8:470  case ARM::t2PLIi8:471    return opcode;472 473  default:474    llvm_unreachable("unknown thumb2 opcode.");475  }476}477 478static unsigned479positiveOffsetOpcode(unsigned opcode)480{481  switch (opcode) {482  case ARM::t2LDRi8:   return ARM::t2LDRi12;483  case ARM::t2LDRHi8:  return ARM::t2LDRHi12;484  case ARM::t2LDRBi8:  return ARM::t2LDRBi12;485  case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;486  case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;487  case ARM::t2STRi8:   return ARM::t2STRi12;488  case ARM::t2STRBi8:  return ARM::t2STRBi12;489  case ARM::t2STRHi8:  return ARM::t2STRHi12;490  case ARM::t2PLDi8:   return ARM::t2PLDi12;491  case ARM::t2PLDWi8:  return ARM::t2PLDWi12;492  case ARM::t2PLIi8:   return ARM::t2PLIi12;493 494  case ARM::t2LDRi12:495  case ARM::t2LDRHi12:496  case ARM::t2LDRBi12:497  case ARM::t2LDRSHi12:498  case ARM::t2LDRSBi12:499  case ARM::t2STRi12:500  case ARM::t2STRBi12:501  case ARM::t2STRHi12:502  case ARM::t2PLDi12:503  case ARM::t2PLDWi12:504  case ARM::t2PLIi12:505    return opcode;506 507  default:508    llvm_unreachable("unknown thumb2 opcode.");509  }510}511 512static unsigned513immediateOffsetOpcode(unsigned opcode)514{515  switch (opcode) {516  case ARM::t2LDRs:   return ARM::t2LDRi12;517  case ARM::t2LDRHs:  return ARM::t2LDRHi12;518  case ARM::t2LDRBs:  return ARM::t2LDRBi12;519  case ARM::t2LDRSHs: return ARM::t2LDRSHi12;520  case ARM::t2LDRSBs: return ARM::t2LDRSBi12;521  case ARM::t2STRs:   return ARM::t2STRi12;522  case ARM::t2STRBs:  return ARM::t2STRBi12;523  case ARM::t2STRHs:  return ARM::t2STRHi12;524  case ARM::t2PLDs:   return ARM::t2PLDi12;525  case ARM::t2PLDWs:  return ARM::t2PLDWi12;526  case ARM::t2PLIs:   return ARM::t2PLIi12;527 528  case ARM::t2LDRi12:529  case ARM::t2LDRHi12:530  case ARM::t2LDRBi12:531  case ARM::t2LDRSHi12:532  case ARM::t2LDRSBi12:533  case ARM::t2STRi12:534  case ARM::t2STRBi12:535  case ARM::t2STRHi12:536  case ARM::t2PLDi12:537  case ARM::t2PLDWi12:538  case ARM::t2PLIi12:539  case ARM::t2LDRi8:540  case ARM::t2LDRHi8:541  case ARM::t2LDRBi8:542  case ARM::t2LDRSHi8:543  case ARM::t2LDRSBi8:544  case ARM::t2STRi8:545  case ARM::t2STRBi8:546  case ARM::t2STRHi8:547  case ARM::t2PLDi8:548  case ARM::t2PLDWi8:549  case ARM::t2PLIi8:550    return opcode;551 552  default:553    llvm_unreachable("unknown thumb2 opcode.");554  }555}556 557bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,558                               Register FrameReg, int &Offset,559                               const ARMBaseInstrInfo &TII,560                               const TargetRegisterInfo *TRI) {561  unsigned Opcode = MI.getOpcode();562  const MCInstrDesc &Desc = MI.getDesc();563  unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);564  bool isSub = false;565 566  MachineFunction &MF = *MI.getParent()->getParent();567  const TargetRegisterClass *RegClass = TII.getRegClass(Desc, FrameRegIdx);568 569  // Memory operands in inline assembly always use AddrModeT2_i12.570  if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)571    AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?572 573  const bool IsSP = Opcode == ARM::t2ADDspImm12 || Opcode == ARM::t2ADDspImm;574  if (IsSP || Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {575    Offset += MI.getOperand(FrameRegIdx+1).getImm();576 577    Register PredReg;578    if (Offset == 0 && getInstrPredicate(MI, PredReg) == ARMCC::AL &&579        !MI.definesRegister(ARM::CPSR, /*TRI=*/nullptr)) {580      // Turn it into a move.581      MI.setDesc(TII.get(ARM::tMOVr));582      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);583      // Remove offset and remaining explicit predicate operands.584      do MI.removeOperand(FrameRegIdx+1);585      while (MI.getNumOperands() > FrameRegIdx+1);586      MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);587      MIB.add(predOps(ARMCC::AL));588      return true;589    }590 591    bool HasCCOut = (Opcode != ARM::t2ADDspImm12 && Opcode != ARM::t2ADDri12);592 593    if (Offset < 0) {594      Offset = -Offset;595      isSub = true;596      MI.setDesc(IsSP ? TII.get(ARM::t2SUBspImm) : TII.get(ARM::t2SUBri));597    } else {598      MI.setDesc(IsSP ? TII.get(ARM::t2ADDspImm) : TII.get(ARM::t2ADDri));599    }600 601    // Common case: small offset, fits into instruction.602    if (ARM_AM::getT2SOImmVal(Offset) != -1) {603      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);604      MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);605      // Add cc_out operand if the original instruction did not have one.606      if (!HasCCOut)607        MI.addOperand(MachineOperand::CreateReg(0, false));608      Offset = 0;609      return true;610    }611    // Another common case: imm12.612    if (Offset < 4096 &&613        (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {614      unsigned NewOpc = isSub ? IsSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12615                              : IsSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;616      MI.setDesc(TII.get(NewOpc));617      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);618      MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);619      // Remove the cc_out operand.620      if (HasCCOut)621        MI.removeOperand(MI.getNumOperands()-1);622      Offset = 0;623      return true;624    }625 626    // Otherwise, extract 8 adjacent bits from the immediate into this627    // t2ADDri/t2SUBri.628    unsigned RotAmt = llvm::countl_zero<unsigned>(Offset);629    unsigned ThisImmVal = Offset & llvm::rotr<uint32_t>(0xff000000U, RotAmt);630 631    // We will handle these bits from offset, clear them.632    Offset &= ~ThisImmVal;633 634    assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&635           "Bit extraction didn't work?");636    MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);637    // Add cc_out operand if the original instruction did not have one.638    if (!HasCCOut)639      MI.addOperand(MachineOperand::CreateReg(0, false));640  } else {641    // AddrMode4 and AddrMode6 cannot handle any offset.642    if (AddrMode == ARMII::AddrMode4 || AddrMode == ARMII::AddrMode6)643      return false;644 645    // AddrModeT2_so cannot handle any offset. If there is no offset646    // register then we change to an immediate version.647    unsigned NewOpc = Opcode;648    if (AddrMode == ARMII::AddrModeT2_so) {649      Register OffsetReg = MI.getOperand(FrameRegIdx + 1).getReg();650      if (OffsetReg != 0) {651        MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);652        return Offset == 0;653      }654 655      MI.removeOperand(FrameRegIdx+1);656      MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);657      NewOpc = immediateOffsetOpcode(Opcode);658      AddrMode = ARMII::AddrModeT2_i12;659    }660 661    unsigned NumBits = 0;662    unsigned Scale = 1;663    if (AddrMode == ARMII::AddrModeT2_i8neg ||664        AddrMode == ARMII::AddrModeT2_i12) {665      // i8 supports only negative, and i12 supports only positive, so666      // based on Offset sign convert Opcode to the appropriate667      // instruction668      Offset += MI.getOperand(FrameRegIdx+1).getImm();669      if (Offset < 0) {670        NewOpc = negativeOffsetOpcode(Opcode);671        NumBits = 8;672        isSub = true;673        Offset = -Offset;674      } else {675        NewOpc = positiveOffsetOpcode(Opcode);676        NumBits = 12;677      }678    } else if (AddrMode == ARMII::AddrMode5) {679      // VFP address mode.680      const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);681      int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());682      if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)683        InstrOffs *= -1;684      NumBits = 8;685      Scale = 4;686      Offset += InstrOffs * 4;687      assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");688      if (Offset < 0) {689        Offset = -Offset;690        isSub = true;691      }692    } else if (AddrMode == ARMII::AddrMode5FP16) {693      // VFP address mode.694      const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);695      int InstrOffs = ARM_AM::getAM5FP16Offset(OffOp.getImm());696      if (ARM_AM::getAM5FP16Op(OffOp.getImm()) == ARM_AM::sub)697        InstrOffs *= -1;698      NumBits = 8;699      Scale = 2;700      Offset += InstrOffs * 2;701      assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");702      if (Offset < 0) {703        Offset = -Offset;704        isSub = true;705      }706    } else if (AddrMode == ARMII::AddrModeT2_i7s4 ||707               AddrMode == ARMII::AddrModeT2_i7s2 ||708               AddrMode == ARMII::AddrModeT2_i7) {709      Offset += MI.getOperand(FrameRegIdx + 1).getImm();710      unsigned OffsetMask;711      switch (AddrMode) {712      case ARMII::AddrModeT2_i7s4: NumBits = 9; OffsetMask = 0x3; break;713      case ARMII::AddrModeT2_i7s2: NumBits = 8; OffsetMask = 0x1; break;714      default:                     NumBits = 7; OffsetMask = 0x0; break;715      }716      // MCInst operand expects already scaled value.717      Scale = 1;718      assert((Offset & OffsetMask) == 0 && "Can't encode this offset!");719      (void)OffsetMask; // squash unused-variable warning at -NDEBUG720    } else if (AddrMode == ARMII::AddrModeT2_i8s4) {721      Offset += MI.getOperand(FrameRegIdx + 1).getImm();722      NumBits = 8 + 2;723      // MCInst operand expects already scaled value.724      Scale = 1;725      assert((Offset & 3) == 0 && "Can't encode this offset!");726    } else if (AddrMode == ARMII::AddrModeT2_ldrex) {727      Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4;728      NumBits = 8; // 8 bits scaled by 4729      Scale = 4;730      assert((Offset & 3) == 0 && "Can't encode this offset!");731    } else {732      llvm_unreachable("Unsupported addressing mode!");733    }734 735    if (NewOpc != Opcode)736      MI.setDesc(TII.get(NewOpc));737 738    MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);739 740    // Attempt to fold address computation741    // Common case: small offset, fits into instruction. We need to make sure742    // the register class is correct too, for instructions like the MVE743    // VLDRH.32, which only accepts low tGPR registers.744    int ImmedOffset = Offset / Scale;745    unsigned Mask = (1 << NumBits) - 1;746    if ((unsigned)Offset <= Mask * Scale &&747        (FrameReg.isVirtual() || RegClass->contains(FrameReg))) {748      if (FrameReg.isVirtual()) {749        // Make sure the register class for the virtual register is correct750        MachineRegisterInfo *MRI = &MF.getRegInfo();751        if (!MRI->constrainRegClass(FrameReg, RegClass))752          llvm_unreachable("Unable to constrain virtual register class.");753      }754 755      // Replace the FrameIndex with fp/sp756      MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);757      if (isSub) {758        if (AddrMode == ARMII::AddrMode5 || AddrMode == ARMII::AddrMode5FP16)759          // FIXME: Not consistent.760          ImmedOffset |= 1 << NumBits;761        else762          ImmedOffset = -ImmedOffset;763      }764      ImmOp.ChangeToImmediate(ImmedOffset);765      Offset = 0;766      return true;767    }768 769    // Otherwise, offset doesn't fit. Pull in what we can to simplify770    ImmedOffset = ImmedOffset & Mask;771    if (isSub) {772      if (AddrMode == ARMII::AddrMode5 || AddrMode == ARMII::AddrMode5FP16)773        // FIXME: Not consistent.774        ImmedOffset |= 1 << NumBits;775      else {776        ImmedOffset = -ImmedOffset;777        if (ImmedOffset == 0)778          // Change the opcode back if the encoded offset is zero.779          MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc)));780      }781    }782    ImmOp.ChangeToImmediate(ImmedOffset);783    Offset &= ~(Mask*Scale);784  }785 786  Offset = (isSub) ? -Offset : Offset;787  return Offset == 0 && (FrameReg.isVirtual() || RegClass->contains(FrameReg));788}789 790ARMCC::CondCodes llvm::getITInstrPredicate(const MachineInstr &MI,791                                           Register &PredReg) {792  unsigned Opc = MI.getOpcode();793  if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)794    return ARMCC::AL;795  return getInstrPredicate(MI, PredReg);796}797 798int llvm::findFirstVPTPredOperandIdx(const MachineInstr &MI) {799  const MCInstrDesc &MCID = MI.getDesc();800 801  for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i)802    if (ARM::isVpred(MCID.operands()[i].OperandType))803      return i;804 805  return -1;806}807 808int llvm::findVPTInactiveOperandIdx(const MachineInstr &MI) {809  const MCInstrDesc &MCID = MI.getDesc();810 811  for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i)812    if (MCID.operands()[i].OperandType == ARM::OPERAND_VPRED_R)813      return i + ARM::SUBOP_vpred_r_inactive;814 815  return -1;816}817 818ARMVCC::VPTCodes llvm::getVPTInstrPredicate(const MachineInstr &MI,819                                            Register &PredReg) {820  int PIdx = findFirstVPTPredOperandIdx(MI);821  if (PIdx == -1) {822    PredReg = 0;823    return ARMVCC::None;824  }825 826  PredReg = MI.getOperand(PIdx+1).getReg();827  return (ARMVCC::VPTCodes)MI.getOperand(PIdx).getImm();828}829 830void llvm::recomputeVPTBlockMask(MachineInstr &Instr) {831  assert(isVPTOpcode(Instr.getOpcode()) && "Not a VPST or VPT Instruction!");832 833  MachineOperand &MaskOp = Instr.getOperand(0);834  assert(MaskOp.isImm() && "Operand 0 is not the block mask of the VPT/VPST?!");835 836  MachineBasicBlock::iterator Iter = ++Instr.getIterator(),837                              End = Instr.getParent()->end();838 839  while (Iter != End && Iter->isDebugInstr())840    ++Iter;841 842  // Verify that the instruction after the VPT/VPST is predicated (it should843  // be), and skip it.844  assert(Iter != End && "Expected some instructions in any VPT block");845  assert(846      getVPTInstrPredicate(*Iter) == ARMVCC::Then &&847      "VPT/VPST should be followed by an instruction with a 'then' predicate!");848  ++Iter;849 850  // Iterate over the predicated instructions, updating the BlockMask as we go.851  ARM::PredBlockMask BlockMask = ARM::PredBlockMask::T;852  while (Iter != End) {853    if (Iter->isDebugInstr()) {854      ++Iter;855      continue;856    }857    ARMVCC::VPTCodes Pred = getVPTInstrPredicate(*Iter);858    if (Pred == ARMVCC::None)859      break;860    BlockMask = expandPredBlockMask(BlockMask, Pred);861    ++Iter;862  }863 864  // Rewrite the BlockMask.865  MaskOp.setImm((int64_t)(BlockMask));866}867