Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
35266 views
//===-- ARMExpandPseudoInsts.cpp - Expand pseudo instructions -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a pass that expands pseudo instructions into target9// instructions to allow proper scheduling, if-conversion, and other late10// optimizations. This pass should be run after register allocation but before11// the post-regalloc scheduling pass.12//13//===----------------------------------------------------------------------===//1415#include "ARM.h"16#include "ARMBaseInstrInfo.h"17#include "ARMBaseRegisterInfo.h"18#include "ARMConstantPoolValue.h"19#include "ARMMachineFunctionInfo.h"20#include "ARMSubtarget.h"21#include "MCTargetDesc/ARMAddressingModes.h"22#include "llvm/CodeGen/LivePhysRegs.h"23#include "llvm/CodeGen/MachineFrameInfo.h"24#include "llvm/CodeGen/MachineFunctionPass.h"25#include "llvm/CodeGen/MachineJumpTableInfo.h"26#include "llvm/MC/MCAsmInfo.h"27#include "llvm/Support/Debug.h"2829using namespace llvm;3031#define DEBUG_TYPE "arm-pseudo"3233static cl::opt<bool>34VerifyARMPseudo("verify-arm-pseudo-expand", cl::Hidden,35cl::desc("Verify machine code after expanding ARM pseudos"));3637#define ARM_EXPAND_PSEUDO_NAME "ARM pseudo instruction expansion pass"3839namespace {40class ARMExpandPseudo : public MachineFunctionPass {41public:42static char ID;43ARMExpandPseudo() : MachineFunctionPass(ID) {}4445const ARMBaseInstrInfo *TII;46const TargetRegisterInfo *TRI;47const ARMSubtarget *STI;48ARMFunctionInfo *AFI;4950bool runOnMachineFunction(MachineFunction &Fn) override;5152MachineFunctionProperties getRequiredProperties() const override {53return MachineFunctionProperties().set(54MachineFunctionProperties::Property::NoVRegs);55}5657StringRef getPassName() const override {58return ARM_EXPAND_PSEUDO_NAME;59}6061private:62bool ExpandMI(MachineBasicBlock &MBB,63MachineBasicBlock::iterator MBBI,64MachineBasicBlock::iterator &NextMBBI);65bool ExpandMBB(MachineBasicBlock &MBB);66void ExpandVLD(MachineBasicBlock::iterator &MBBI);67void ExpandVST(MachineBasicBlock::iterator &MBBI);68void ExpandLaneOp(MachineBasicBlock::iterator &MBBI);69void ExpandVTBL(MachineBasicBlock::iterator &MBBI,70unsigned Opc, bool IsExt);71void ExpandMQQPRLoadStore(MachineBasicBlock::iterator &MBBI);72void ExpandTMOV32BitImm(MachineBasicBlock &MBB,73MachineBasicBlock::iterator &MBBI);74void ExpandMOV32BitImm(MachineBasicBlock &MBB,75MachineBasicBlock::iterator &MBBI);76void CMSEClearGPRegs(MachineBasicBlock &MBB,77MachineBasicBlock::iterator MBBI, const DebugLoc &DL,78const SmallVectorImpl<unsigned> &ClearRegs,79unsigned ClobberReg);80MachineBasicBlock &CMSEClearFPRegs(MachineBasicBlock &MBB,81MachineBasicBlock::iterator MBBI);82MachineBasicBlock &CMSEClearFPRegsV8(MachineBasicBlock &MBB,83MachineBasicBlock::iterator MBBI,84const BitVector &ClearRegs);85MachineBasicBlock &CMSEClearFPRegsV81(MachineBasicBlock &MBB,86MachineBasicBlock::iterator MBBI,87const BitVector &ClearRegs);88void CMSESaveClearFPRegs(MachineBasicBlock &MBB,89MachineBasicBlock::iterator MBBI, DebugLoc &DL,90const LivePhysRegs &LiveRegs,91SmallVectorImpl<unsigned> &AvailableRegs);92void CMSESaveClearFPRegsV8(MachineBasicBlock &MBB,93MachineBasicBlock::iterator MBBI, DebugLoc &DL,94const LivePhysRegs &LiveRegs,95SmallVectorImpl<unsigned> &ScratchRegs);96void CMSESaveClearFPRegsV81(MachineBasicBlock &MBB,97MachineBasicBlock::iterator MBBI, DebugLoc &DL,98const LivePhysRegs &LiveRegs);99void CMSERestoreFPRegs(MachineBasicBlock &MBB,100MachineBasicBlock::iterator MBBI, DebugLoc &DL,101SmallVectorImpl<unsigned> &AvailableRegs);102void CMSERestoreFPRegsV8(MachineBasicBlock &MBB,103MachineBasicBlock::iterator MBBI, DebugLoc &DL,104SmallVectorImpl<unsigned> &AvailableRegs);105void CMSERestoreFPRegsV81(MachineBasicBlock &MBB,106MachineBasicBlock::iterator MBBI, DebugLoc &DL,107SmallVectorImpl<unsigned> &AvailableRegs);108bool ExpandCMP_SWAP(MachineBasicBlock &MBB,109MachineBasicBlock::iterator MBBI, unsigned LdrexOp,110unsigned StrexOp, unsigned UxtOp,111MachineBasicBlock::iterator &NextMBBI);112113bool ExpandCMP_SWAP_64(MachineBasicBlock &MBB,114MachineBasicBlock::iterator MBBI,115MachineBasicBlock::iterator &NextMBBI);116};117char ARMExpandPseudo::ID = 0;118}119120INITIALIZE_PASS(ARMExpandPseudo, DEBUG_TYPE, ARM_EXPAND_PSEUDO_NAME, false,121false)122123namespace {124// Constants for register spacing in NEON load/store instructions.125// For quad-register load-lane and store-lane pseudo instructors, the126// spacing is initially assumed to be EvenDblSpc, and that is changed to127// OddDblSpc depending on the lane number operand.128enum NEONRegSpacing {129SingleSpc,130SingleLowSpc , // Single spacing, low registers, three and four vectors.131SingleHighQSpc, // Single spacing, high registers, four vectors.132SingleHighTSpc, // Single spacing, high registers, three vectors.133EvenDblSpc,134OddDblSpc135};136137// Entries for NEON load/store information table. The table is sorted by138// PseudoOpc for fast binary-search lookups.139struct NEONLdStTableEntry {140uint16_t PseudoOpc;141uint16_t RealOpc;142bool IsLoad;143bool isUpdating;144bool hasWritebackOperand;145uint8_t RegSpacing; // One of type NEONRegSpacing146uint8_t NumRegs; // D registers loaded or stored147uint8_t RegElts; // elements per D register; used for lane ops148// FIXME: Temporary flag to denote whether the real instruction takes149// a single register (like the encoding) or all of the registers in150// the list (like the asm syntax and the isel DAG). When all definitions151// are converted to take only the single encoded register, this will152// go away.153bool copyAllListRegs;154155// Comparison methods for binary search of the table.156bool operator<(const NEONLdStTableEntry &TE) const {157return PseudoOpc < TE.PseudoOpc;158}159friend bool operator<(const NEONLdStTableEntry &TE, unsigned PseudoOpc) {160return TE.PseudoOpc < PseudoOpc;161}162friend bool LLVM_ATTRIBUTE_UNUSED operator<(unsigned PseudoOpc,163const NEONLdStTableEntry &TE) {164return PseudoOpc < TE.PseudoOpc;165}166};167}168169static const NEONLdStTableEntry NEONLdStTable[] = {170{ ARM::VLD1LNq16Pseudo, ARM::VLD1LNd16, true, false, false, EvenDblSpc, 1, 4 ,true},171{ ARM::VLD1LNq16Pseudo_UPD, ARM::VLD1LNd16_UPD, true, true, true, EvenDblSpc, 1, 4 ,true},172{ ARM::VLD1LNq32Pseudo, ARM::VLD1LNd32, true, false, false, EvenDblSpc, 1, 2 ,true},173{ ARM::VLD1LNq32Pseudo_UPD, ARM::VLD1LNd32_UPD, true, true, true, EvenDblSpc, 1, 2 ,true},174{ ARM::VLD1LNq8Pseudo, ARM::VLD1LNd8, true, false, false, EvenDblSpc, 1, 8 ,true},175{ ARM::VLD1LNq8Pseudo_UPD, ARM::VLD1LNd8_UPD, true, true, true, EvenDblSpc, 1, 8 ,true},176177{ ARM::VLD1d16QPseudo, ARM::VLD1d16Q, true, false, false, SingleSpc, 4, 4 ,false},178{ ARM::VLD1d16QPseudoWB_fixed, ARM::VLD1d16Qwb_fixed, true, true, false, SingleSpc, 4, 4 ,false},179{ ARM::VLD1d16QPseudoWB_register, ARM::VLD1d16Qwb_register, true, true, true, SingleSpc, 4, 4 ,false},180{ ARM::VLD1d16TPseudo, ARM::VLD1d16T, true, false, false, SingleSpc, 3, 4 ,false},181{ ARM::VLD1d16TPseudoWB_fixed, ARM::VLD1d16Twb_fixed, true, true, false, SingleSpc, 3, 4 ,false},182{ ARM::VLD1d16TPseudoWB_register, ARM::VLD1d16Twb_register, true, true, true, SingleSpc, 3, 4 ,false},183184{ ARM::VLD1d32QPseudo, ARM::VLD1d32Q, true, false, false, SingleSpc, 4, 2 ,false},185{ ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d32Qwb_fixed, true, true, false, SingleSpc, 4, 2 ,false},186{ ARM::VLD1d32QPseudoWB_register, ARM::VLD1d32Qwb_register, true, true, true, SingleSpc, 4, 2 ,false},187{ ARM::VLD1d32TPseudo, ARM::VLD1d32T, true, false, false, SingleSpc, 3, 2 ,false},188{ ARM::VLD1d32TPseudoWB_fixed, ARM::VLD1d32Twb_fixed, true, true, false, SingleSpc, 3, 2 ,false},189{ ARM::VLD1d32TPseudoWB_register, ARM::VLD1d32Twb_register, true, true, true, SingleSpc, 3, 2 ,false},190191{ ARM::VLD1d64QPseudo, ARM::VLD1d64Q, true, false, false, SingleSpc, 4, 1 ,false},192{ ARM::VLD1d64QPseudoWB_fixed, ARM::VLD1d64Qwb_fixed, true, true, false, SingleSpc, 4, 1 ,false},193{ ARM::VLD1d64QPseudoWB_register, ARM::VLD1d64Qwb_register, true, true, true, SingleSpc, 4, 1 ,false},194{ ARM::VLD1d64TPseudo, ARM::VLD1d64T, true, false, false, SingleSpc, 3, 1 ,false},195{ ARM::VLD1d64TPseudoWB_fixed, ARM::VLD1d64Twb_fixed, true, true, false, SingleSpc, 3, 1 ,false},196{ ARM::VLD1d64TPseudoWB_register, ARM::VLD1d64Twb_register, true, true, true, SingleSpc, 3, 1 ,false},197198{ ARM::VLD1d8QPseudo, ARM::VLD1d8Q, true, false, false, SingleSpc, 4, 8 ,false},199{ ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d8Qwb_fixed, true, true, false, SingleSpc, 4, 8 ,false},200{ ARM::VLD1d8QPseudoWB_register, ARM::VLD1d8Qwb_register, true, true, true, SingleSpc, 4, 8 ,false},201{ ARM::VLD1d8TPseudo, ARM::VLD1d8T, true, false, false, SingleSpc, 3, 8 ,false},202{ ARM::VLD1d8TPseudoWB_fixed, ARM::VLD1d8Twb_fixed, true, true, false, SingleSpc, 3, 8 ,false},203{ ARM::VLD1d8TPseudoWB_register, ARM::VLD1d8Twb_register, true, true, true, SingleSpc, 3, 8 ,false},204205{ ARM::VLD1q16HighQPseudo, ARM::VLD1d16Q, true, false, false, SingleHighQSpc, 4, 4 ,false},206{ ARM::VLD1q16HighQPseudo_UPD, ARM::VLD1d16Qwb_fixed, true, true, true, SingleHighQSpc, 4, 4 ,false},207{ ARM::VLD1q16HighTPseudo, ARM::VLD1d16T, true, false, false, SingleHighTSpc, 3, 4 ,false},208{ ARM::VLD1q16HighTPseudo_UPD, ARM::VLD1d16Twb_fixed, true, true, true, SingleHighTSpc, 3, 4 ,false},209{ ARM::VLD1q16LowQPseudo_UPD, ARM::VLD1d16Qwb_fixed, true, true, true, SingleLowSpc, 4, 4 ,false},210{ ARM::VLD1q16LowTPseudo_UPD, ARM::VLD1d16Twb_fixed, true, true, true, SingleLowSpc, 3, 4 ,false},211212{ ARM::VLD1q32HighQPseudo, ARM::VLD1d32Q, true, false, false, SingleHighQSpc, 4, 2 ,false},213{ ARM::VLD1q32HighQPseudo_UPD, ARM::VLD1d32Qwb_fixed, true, true, true, SingleHighQSpc, 4, 2 ,false},214{ ARM::VLD1q32HighTPseudo, ARM::VLD1d32T, true, false, false, SingleHighTSpc, 3, 2 ,false},215{ ARM::VLD1q32HighTPseudo_UPD, ARM::VLD1d32Twb_fixed, true, true, true, SingleHighTSpc, 3, 2 ,false},216{ ARM::VLD1q32LowQPseudo_UPD, ARM::VLD1d32Qwb_fixed, true, true, true, SingleLowSpc, 4, 2 ,false},217{ ARM::VLD1q32LowTPseudo_UPD, ARM::VLD1d32Twb_fixed, true, true, true, SingleLowSpc, 3, 2 ,false},218219{ ARM::VLD1q64HighQPseudo, ARM::VLD1d64Q, true, false, false, SingleHighQSpc, 4, 1 ,false},220{ ARM::VLD1q64HighQPseudo_UPD, ARM::VLD1d64Qwb_fixed, true, true, true, SingleHighQSpc, 4, 1 ,false},221{ ARM::VLD1q64HighTPseudo, ARM::VLD1d64T, true, false, false, SingleHighTSpc, 3, 1 ,false},222{ ARM::VLD1q64HighTPseudo_UPD, ARM::VLD1d64Twb_fixed, true, true, true, SingleHighTSpc, 3, 1 ,false},223{ ARM::VLD1q64LowQPseudo_UPD, ARM::VLD1d64Qwb_fixed, true, true, true, SingleLowSpc, 4, 1 ,false},224{ ARM::VLD1q64LowTPseudo_UPD, ARM::VLD1d64Twb_fixed, true, true, true, SingleLowSpc, 3, 1 ,false},225226{ ARM::VLD1q8HighQPseudo, ARM::VLD1d8Q, true, false, false, SingleHighQSpc, 4, 8 ,false},227{ ARM::VLD1q8HighQPseudo_UPD, ARM::VLD1d8Qwb_fixed, true, true, true, SingleHighQSpc, 4, 8 ,false},228{ ARM::VLD1q8HighTPseudo, ARM::VLD1d8T, true, false, false, SingleHighTSpc, 3, 8 ,false},229{ ARM::VLD1q8HighTPseudo_UPD, ARM::VLD1d8Twb_fixed, true, true, true, SingleHighTSpc, 3, 8 ,false},230{ ARM::VLD1q8LowQPseudo_UPD, ARM::VLD1d8Qwb_fixed, true, true, true, SingleLowSpc, 4, 8 ,false},231{ ARM::VLD1q8LowTPseudo_UPD, ARM::VLD1d8Twb_fixed, true, true, true, SingleLowSpc, 3, 8 ,false},232233{ ARM::VLD2DUPq16EvenPseudo, ARM::VLD2DUPd16x2, true, false, false, EvenDblSpc, 2, 4 ,false},234{ ARM::VLD2DUPq16OddPseudo, ARM::VLD2DUPd16x2, true, false, false, OddDblSpc, 2, 4 ,false},235{ ARM::VLD2DUPq16OddPseudoWB_fixed, ARM::VLD2DUPd16x2wb_fixed, true, true, false, OddDblSpc, 2, 4 ,false},236{ ARM::VLD2DUPq16OddPseudoWB_register, ARM::VLD2DUPd16x2wb_register, true, true, true, OddDblSpc, 2, 4 ,false},237{ ARM::VLD2DUPq32EvenPseudo, ARM::VLD2DUPd32x2, true, false, false, EvenDblSpc, 2, 2 ,false},238{ ARM::VLD2DUPq32OddPseudo, ARM::VLD2DUPd32x2, true, false, false, OddDblSpc, 2, 2 ,false},239{ ARM::VLD2DUPq32OddPseudoWB_fixed, ARM::VLD2DUPd32x2wb_fixed, true, true, false, OddDblSpc, 2, 2 ,false},240{ ARM::VLD2DUPq32OddPseudoWB_register, ARM::VLD2DUPd32x2wb_register, true, true, true, OddDblSpc, 2, 2 ,false},241{ ARM::VLD2DUPq8EvenPseudo, ARM::VLD2DUPd8x2, true, false, false, EvenDblSpc, 2, 8 ,false},242{ ARM::VLD2DUPq8OddPseudo, ARM::VLD2DUPd8x2, true, false, false, OddDblSpc, 2, 8 ,false},243{ ARM::VLD2DUPq8OddPseudoWB_fixed, ARM::VLD2DUPd8x2wb_fixed, true, true, false, OddDblSpc, 2, 8 ,false},244{ ARM::VLD2DUPq8OddPseudoWB_register, ARM::VLD2DUPd8x2wb_register, true, true, true, OddDblSpc, 2, 8 ,false},245246{ ARM::VLD2LNd16Pseudo, ARM::VLD2LNd16, true, false, false, SingleSpc, 2, 4 ,true},247{ ARM::VLD2LNd16Pseudo_UPD, ARM::VLD2LNd16_UPD, true, true, true, SingleSpc, 2, 4 ,true},248{ ARM::VLD2LNd32Pseudo, ARM::VLD2LNd32, true, false, false, SingleSpc, 2, 2 ,true},249{ ARM::VLD2LNd32Pseudo_UPD, ARM::VLD2LNd32_UPD, true, true, true, SingleSpc, 2, 2 ,true},250{ ARM::VLD2LNd8Pseudo, ARM::VLD2LNd8, true, false, false, SingleSpc, 2, 8 ,true},251{ ARM::VLD2LNd8Pseudo_UPD, ARM::VLD2LNd8_UPD, true, true, true, SingleSpc, 2, 8 ,true},252{ ARM::VLD2LNq16Pseudo, ARM::VLD2LNq16, true, false, false, EvenDblSpc, 2, 4 ,true},253{ ARM::VLD2LNq16Pseudo_UPD, ARM::VLD2LNq16_UPD, true, true, true, EvenDblSpc, 2, 4 ,true},254{ ARM::VLD2LNq32Pseudo, ARM::VLD2LNq32, true, false, false, EvenDblSpc, 2, 2 ,true},255{ ARM::VLD2LNq32Pseudo_UPD, ARM::VLD2LNq32_UPD, true, true, true, EvenDblSpc, 2, 2 ,true},256257{ ARM::VLD2q16Pseudo, ARM::VLD2q16, true, false, false, SingleSpc, 4, 4 ,false},258{ ARM::VLD2q16PseudoWB_fixed, ARM::VLD2q16wb_fixed, true, true, false, SingleSpc, 4, 4 ,false},259{ ARM::VLD2q16PseudoWB_register, ARM::VLD2q16wb_register, true, true, true, SingleSpc, 4, 4 ,false},260{ ARM::VLD2q32Pseudo, ARM::VLD2q32, true, false, false, SingleSpc, 4, 2 ,false},261{ ARM::VLD2q32PseudoWB_fixed, ARM::VLD2q32wb_fixed, true, true, false, SingleSpc, 4, 2 ,false},262{ ARM::VLD2q32PseudoWB_register, ARM::VLD2q32wb_register, true, true, true, SingleSpc, 4, 2 ,false},263{ ARM::VLD2q8Pseudo, ARM::VLD2q8, true, false, false, SingleSpc, 4, 8 ,false},264{ ARM::VLD2q8PseudoWB_fixed, ARM::VLD2q8wb_fixed, true, true, false, SingleSpc, 4, 8 ,false},265{ ARM::VLD2q8PseudoWB_register, ARM::VLD2q8wb_register, true, true, true, SingleSpc, 4, 8 ,false},266267{ ARM::VLD3DUPd16Pseudo, ARM::VLD3DUPd16, true, false, false, SingleSpc, 3, 4,true},268{ ARM::VLD3DUPd16Pseudo_UPD, ARM::VLD3DUPd16_UPD, true, true, true, SingleSpc, 3, 4,true},269{ ARM::VLD3DUPd32Pseudo, ARM::VLD3DUPd32, true, false, false, SingleSpc, 3, 2,true},270{ ARM::VLD3DUPd32Pseudo_UPD, ARM::VLD3DUPd32_UPD, true, true, true, SingleSpc, 3, 2,true},271{ ARM::VLD3DUPd8Pseudo, ARM::VLD3DUPd8, true, false, false, SingleSpc, 3, 8,true},272{ ARM::VLD3DUPd8Pseudo_UPD, ARM::VLD3DUPd8_UPD, true, true, true, SingleSpc, 3, 8,true},273{ ARM::VLD3DUPq16EvenPseudo, ARM::VLD3DUPq16, true, false, false, EvenDblSpc, 3, 4 ,true},274{ ARM::VLD3DUPq16OddPseudo, ARM::VLD3DUPq16, true, false, false, OddDblSpc, 3, 4 ,true},275{ ARM::VLD3DUPq16OddPseudo_UPD, ARM::VLD3DUPq16_UPD, true, true, true, OddDblSpc, 3, 4 ,true},276{ ARM::VLD3DUPq32EvenPseudo, ARM::VLD3DUPq32, true, false, false, EvenDblSpc, 3, 2 ,true},277{ ARM::VLD3DUPq32OddPseudo, ARM::VLD3DUPq32, true, false, false, OddDblSpc, 3, 2 ,true},278{ ARM::VLD3DUPq32OddPseudo_UPD, ARM::VLD3DUPq32_UPD, true, true, true, OddDblSpc, 3, 2 ,true},279{ ARM::VLD3DUPq8EvenPseudo, ARM::VLD3DUPq8, true, false, false, EvenDblSpc, 3, 8 ,true},280{ ARM::VLD3DUPq8OddPseudo, ARM::VLD3DUPq8, true, false, false, OddDblSpc, 3, 8 ,true},281{ ARM::VLD3DUPq8OddPseudo_UPD, ARM::VLD3DUPq8_UPD, true, true, true, OddDblSpc, 3, 8 ,true},282283{ ARM::VLD3LNd16Pseudo, ARM::VLD3LNd16, true, false, false, SingleSpc, 3, 4 ,true},284{ ARM::VLD3LNd16Pseudo_UPD, ARM::VLD3LNd16_UPD, true, true, true, SingleSpc, 3, 4 ,true},285{ ARM::VLD3LNd32Pseudo, ARM::VLD3LNd32, true, false, false, SingleSpc, 3, 2 ,true},286{ ARM::VLD3LNd32Pseudo_UPD, ARM::VLD3LNd32_UPD, true, true, true, SingleSpc, 3, 2 ,true},287{ ARM::VLD3LNd8Pseudo, ARM::VLD3LNd8, true, false, false, SingleSpc, 3, 8 ,true},288{ ARM::VLD3LNd8Pseudo_UPD, ARM::VLD3LNd8_UPD, true, true, true, SingleSpc, 3, 8 ,true},289{ ARM::VLD3LNq16Pseudo, ARM::VLD3LNq16, true, false, false, EvenDblSpc, 3, 4 ,true},290{ ARM::VLD3LNq16Pseudo_UPD, ARM::VLD3LNq16_UPD, true, true, true, EvenDblSpc, 3, 4 ,true},291{ ARM::VLD3LNq32Pseudo, ARM::VLD3LNq32, true, false, false, EvenDblSpc, 3, 2 ,true},292{ ARM::VLD3LNq32Pseudo_UPD, ARM::VLD3LNq32_UPD, true, true, true, EvenDblSpc, 3, 2 ,true},293294{ ARM::VLD3d16Pseudo, ARM::VLD3d16, true, false, false, SingleSpc, 3, 4 ,true},295{ ARM::VLD3d16Pseudo_UPD, ARM::VLD3d16_UPD, true, true, true, SingleSpc, 3, 4 ,true},296{ ARM::VLD3d32Pseudo, ARM::VLD3d32, true, false, false, SingleSpc, 3, 2 ,true},297{ ARM::VLD3d32Pseudo_UPD, ARM::VLD3d32_UPD, true, true, true, SingleSpc, 3, 2 ,true},298{ ARM::VLD3d8Pseudo, ARM::VLD3d8, true, false, false, SingleSpc, 3, 8 ,true},299{ ARM::VLD3d8Pseudo_UPD, ARM::VLD3d8_UPD, true, true, true, SingleSpc, 3, 8 ,true},300301{ ARM::VLD3q16Pseudo_UPD, ARM::VLD3q16_UPD, true, true, true, EvenDblSpc, 3, 4 ,true},302{ ARM::VLD3q16oddPseudo, ARM::VLD3q16, true, false, false, OddDblSpc, 3, 4 ,true},303{ ARM::VLD3q16oddPseudo_UPD, ARM::VLD3q16_UPD, true, true, true, OddDblSpc, 3, 4 ,true},304{ ARM::VLD3q32Pseudo_UPD, ARM::VLD3q32_UPD, true, true, true, EvenDblSpc, 3, 2 ,true},305{ ARM::VLD3q32oddPseudo, ARM::VLD3q32, true, false, false, OddDblSpc, 3, 2 ,true},306{ ARM::VLD3q32oddPseudo_UPD, ARM::VLD3q32_UPD, true, true, true, OddDblSpc, 3, 2 ,true},307{ ARM::VLD3q8Pseudo_UPD, ARM::VLD3q8_UPD, true, true, true, EvenDblSpc, 3, 8 ,true},308{ ARM::VLD3q8oddPseudo, ARM::VLD3q8, true, false, false, OddDblSpc, 3, 8 ,true},309{ ARM::VLD3q8oddPseudo_UPD, ARM::VLD3q8_UPD, true, true, true, OddDblSpc, 3, 8 ,true},310311{ ARM::VLD4DUPd16Pseudo, ARM::VLD4DUPd16, true, false, false, SingleSpc, 4, 4,true},312{ ARM::VLD4DUPd16Pseudo_UPD, ARM::VLD4DUPd16_UPD, true, true, true, SingleSpc, 4, 4,true},313{ ARM::VLD4DUPd32Pseudo, ARM::VLD4DUPd32, true, false, false, SingleSpc, 4, 2,true},314{ ARM::VLD4DUPd32Pseudo_UPD, ARM::VLD4DUPd32_UPD, true, true, true, SingleSpc, 4, 2,true},315{ ARM::VLD4DUPd8Pseudo, ARM::VLD4DUPd8, true, false, false, SingleSpc, 4, 8,true},316{ ARM::VLD4DUPd8Pseudo_UPD, ARM::VLD4DUPd8_UPD, true, true, true, SingleSpc, 4, 8,true},317{ ARM::VLD4DUPq16EvenPseudo, ARM::VLD4DUPq16, true, false, false, EvenDblSpc, 4, 4 ,true},318{ ARM::VLD4DUPq16OddPseudo, ARM::VLD4DUPq16, true, false, false, OddDblSpc, 4, 4 ,true},319{ ARM::VLD4DUPq16OddPseudo_UPD, ARM::VLD4DUPq16_UPD, true, true, true, OddDblSpc, 4, 4 ,true},320{ ARM::VLD4DUPq32EvenPseudo, ARM::VLD4DUPq32, true, false, false, EvenDblSpc, 4, 2 ,true},321{ ARM::VLD4DUPq32OddPseudo, ARM::VLD4DUPq32, true, false, false, OddDblSpc, 4, 2 ,true},322{ ARM::VLD4DUPq32OddPseudo_UPD, ARM::VLD4DUPq32_UPD, true, true, true, OddDblSpc, 4, 2 ,true},323{ ARM::VLD4DUPq8EvenPseudo, ARM::VLD4DUPq8, true, false, false, EvenDblSpc, 4, 8 ,true},324{ ARM::VLD4DUPq8OddPseudo, ARM::VLD4DUPq8, true, false, false, OddDblSpc, 4, 8 ,true},325{ ARM::VLD4DUPq8OddPseudo_UPD, ARM::VLD4DUPq8_UPD, true, true, true, OddDblSpc, 4, 8 ,true},326327{ ARM::VLD4LNd16Pseudo, ARM::VLD4LNd16, true, false, false, SingleSpc, 4, 4 ,true},328{ ARM::VLD4LNd16Pseudo_UPD, ARM::VLD4LNd16_UPD, true, true, true, SingleSpc, 4, 4 ,true},329{ ARM::VLD4LNd32Pseudo, ARM::VLD4LNd32, true, false, false, SingleSpc, 4, 2 ,true},330{ ARM::VLD4LNd32Pseudo_UPD, ARM::VLD4LNd32_UPD, true, true, true, SingleSpc, 4, 2 ,true},331{ ARM::VLD4LNd8Pseudo, ARM::VLD4LNd8, true, false, false, SingleSpc, 4, 8 ,true},332{ ARM::VLD4LNd8Pseudo_UPD, ARM::VLD4LNd8_UPD, true, true, true, SingleSpc, 4, 8 ,true},333{ ARM::VLD4LNq16Pseudo, ARM::VLD4LNq16, true, false, false, EvenDblSpc, 4, 4 ,true},334{ ARM::VLD4LNq16Pseudo_UPD, ARM::VLD4LNq16_UPD, true, true, true, EvenDblSpc, 4, 4 ,true},335{ ARM::VLD4LNq32Pseudo, ARM::VLD4LNq32, true, false, false, EvenDblSpc, 4, 2 ,true},336{ ARM::VLD4LNq32Pseudo_UPD, ARM::VLD4LNq32_UPD, true, true, true, EvenDblSpc, 4, 2 ,true},337338{ ARM::VLD4d16Pseudo, ARM::VLD4d16, true, false, false, SingleSpc, 4, 4 ,true},339{ ARM::VLD4d16Pseudo_UPD, ARM::VLD4d16_UPD, true, true, true, SingleSpc, 4, 4 ,true},340{ ARM::VLD4d32Pseudo, ARM::VLD4d32, true, false, false, SingleSpc, 4, 2 ,true},341{ ARM::VLD4d32Pseudo_UPD, ARM::VLD4d32_UPD, true, true, true, SingleSpc, 4, 2 ,true},342{ ARM::VLD4d8Pseudo, ARM::VLD4d8, true, false, false, SingleSpc, 4, 8 ,true},343{ ARM::VLD4d8Pseudo_UPD, ARM::VLD4d8_UPD, true, true, true, SingleSpc, 4, 8 ,true},344345{ ARM::VLD4q16Pseudo_UPD, ARM::VLD4q16_UPD, true, true, true, EvenDblSpc, 4, 4 ,true},346{ ARM::VLD4q16oddPseudo, ARM::VLD4q16, true, false, false, OddDblSpc, 4, 4 ,true},347{ ARM::VLD4q16oddPseudo_UPD, ARM::VLD4q16_UPD, true, true, true, OddDblSpc, 4, 4 ,true},348{ ARM::VLD4q32Pseudo_UPD, ARM::VLD4q32_UPD, true, true, true, EvenDblSpc, 4, 2 ,true},349{ ARM::VLD4q32oddPseudo, ARM::VLD4q32, true, false, false, OddDblSpc, 4, 2 ,true},350{ ARM::VLD4q32oddPseudo_UPD, ARM::VLD4q32_UPD, true, true, true, OddDblSpc, 4, 2 ,true},351{ ARM::VLD4q8Pseudo_UPD, ARM::VLD4q8_UPD, true, true, true, EvenDblSpc, 4, 8 ,true},352{ ARM::VLD4q8oddPseudo, ARM::VLD4q8, true, false, false, OddDblSpc, 4, 8 ,true},353{ ARM::VLD4q8oddPseudo_UPD, ARM::VLD4q8_UPD, true, true, true, OddDblSpc, 4, 8 ,true},354355{ ARM::VST1LNq16Pseudo, ARM::VST1LNd16, false, false, false, EvenDblSpc, 1, 4 ,true},356{ ARM::VST1LNq16Pseudo_UPD, ARM::VST1LNd16_UPD, false, true, true, EvenDblSpc, 1, 4 ,true},357{ ARM::VST1LNq32Pseudo, ARM::VST1LNd32, false, false, false, EvenDblSpc, 1, 2 ,true},358{ ARM::VST1LNq32Pseudo_UPD, ARM::VST1LNd32_UPD, false, true, true, EvenDblSpc, 1, 2 ,true},359{ ARM::VST1LNq8Pseudo, ARM::VST1LNd8, false, false, false, EvenDblSpc, 1, 8 ,true},360{ ARM::VST1LNq8Pseudo_UPD, ARM::VST1LNd8_UPD, false, true, true, EvenDblSpc, 1, 8 ,true},361362{ ARM::VST1d16QPseudo, ARM::VST1d16Q, false, false, false, SingleSpc, 4, 4 ,false},363{ ARM::VST1d16QPseudoWB_fixed, ARM::VST1d16Qwb_fixed, false, true, false, SingleSpc, 4, 4 ,false},364{ ARM::VST1d16QPseudoWB_register, ARM::VST1d16Qwb_register, false, true, true, SingleSpc, 4, 4 ,false},365{ ARM::VST1d16TPseudo, ARM::VST1d16T, false, false, false, SingleSpc, 3, 4 ,false},366{ ARM::VST1d16TPseudoWB_fixed, ARM::VST1d16Twb_fixed, false, true, false, SingleSpc, 3, 4 ,false},367{ ARM::VST1d16TPseudoWB_register, ARM::VST1d16Twb_register, false, true, true, SingleSpc, 3, 4 ,false},368369{ ARM::VST1d32QPseudo, ARM::VST1d32Q, false, false, false, SingleSpc, 4, 2 ,false},370{ ARM::VST1d32QPseudoWB_fixed, ARM::VST1d32Qwb_fixed, false, true, false, SingleSpc, 4, 2 ,false},371{ ARM::VST1d32QPseudoWB_register, ARM::VST1d32Qwb_register, false, true, true, SingleSpc, 4, 2 ,false},372{ ARM::VST1d32TPseudo, ARM::VST1d32T, false, false, false, SingleSpc, 3, 2 ,false},373{ ARM::VST1d32TPseudoWB_fixed, ARM::VST1d32Twb_fixed, false, true, false, SingleSpc, 3, 2 ,false},374{ ARM::VST1d32TPseudoWB_register, ARM::VST1d32Twb_register, false, true, true, SingleSpc, 3, 2 ,false},375376{ ARM::VST1d64QPseudo, ARM::VST1d64Q, false, false, false, SingleSpc, 4, 1 ,false},377{ ARM::VST1d64QPseudoWB_fixed, ARM::VST1d64Qwb_fixed, false, true, false, SingleSpc, 4, 1 ,false},378{ ARM::VST1d64QPseudoWB_register, ARM::VST1d64Qwb_register, false, true, true, SingleSpc, 4, 1 ,false},379{ ARM::VST1d64TPseudo, ARM::VST1d64T, false, false, false, SingleSpc, 3, 1 ,false},380{ ARM::VST1d64TPseudoWB_fixed, ARM::VST1d64Twb_fixed, false, true, false, SingleSpc, 3, 1 ,false},381{ ARM::VST1d64TPseudoWB_register, ARM::VST1d64Twb_register, false, true, true, SingleSpc, 3, 1 ,false},382383{ ARM::VST1d8QPseudo, ARM::VST1d8Q, false, false, false, SingleSpc, 4, 8 ,false},384{ ARM::VST1d8QPseudoWB_fixed, ARM::VST1d8Qwb_fixed, false, true, false, SingleSpc, 4, 8 ,false},385{ ARM::VST1d8QPseudoWB_register, ARM::VST1d8Qwb_register, false, true, true, SingleSpc, 4, 8 ,false},386{ ARM::VST1d8TPseudo, ARM::VST1d8T, false, false, false, SingleSpc, 3, 8 ,false},387{ ARM::VST1d8TPseudoWB_fixed, ARM::VST1d8Twb_fixed, false, true, false, SingleSpc, 3, 8 ,false},388{ ARM::VST1d8TPseudoWB_register, ARM::VST1d8Twb_register, false, true, true, SingleSpc, 3, 8 ,false},389390{ ARM::VST1q16HighQPseudo, ARM::VST1d16Q, false, false, false, SingleHighQSpc, 4, 4 ,false},391{ ARM::VST1q16HighQPseudo_UPD, ARM::VST1d16Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},392{ ARM::VST1q16HighTPseudo, ARM::VST1d16T, false, false, false, SingleHighTSpc, 3, 4 ,false},393{ ARM::VST1q16HighTPseudo_UPD, ARM::VST1d16Twb_fixed, false, true, true, SingleHighTSpc, 3, 4 ,false},394{ ARM::VST1q16LowQPseudo_UPD, ARM::VST1d16Qwb_fixed, false, true, true, SingleLowSpc, 4, 4 ,false},395{ ARM::VST1q16LowTPseudo_UPD, ARM::VST1d16Twb_fixed, false, true, true, SingleLowSpc, 3, 4 ,false},396397{ ARM::VST1q32HighQPseudo, ARM::VST1d32Q, false, false, false, SingleHighQSpc, 4, 2 ,false},398{ ARM::VST1q32HighQPseudo_UPD, ARM::VST1d32Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},399{ ARM::VST1q32HighTPseudo, ARM::VST1d32T, false, false, false, SingleHighTSpc, 3, 2 ,false},400{ ARM::VST1q32HighTPseudo_UPD, ARM::VST1d32Twb_fixed, false, true, true, SingleHighTSpc, 3, 2 ,false},401{ ARM::VST1q32LowQPseudo_UPD, ARM::VST1d32Qwb_fixed, false, true, true, SingleLowSpc, 4, 2 ,false},402{ ARM::VST1q32LowTPseudo_UPD, ARM::VST1d32Twb_fixed, false, true, true, SingleLowSpc, 3, 2 ,false},403404{ ARM::VST1q64HighQPseudo, ARM::VST1d64Q, false, false, false, SingleHighQSpc, 4, 1 ,false},405{ ARM::VST1q64HighQPseudo_UPD, ARM::VST1d64Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},406{ ARM::VST1q64HighTPseudo, ARM::VST1d64T, false, false, false, SingleHighTSpc, 3, 1 ,false},407{ ARM::VST1q64HighTPseudo_UPD, ARM::VST1d64Twb_fixed, false, true, true, SingleHighTSpc, 3, 1 ,false},408{ ARM::VST1q64LowQPseudo_UPD, ARM::VST1d64Qwb_fixed, false, true, true, SingleLowSpc, 4, 1 ,false},409{ ARM::VST1q64LowTPseudo_UPD, ARM::VST1d64Twb_fixed, false, true, true, SingleLowSpc, 3, 1 ,false},410411{ ARM::VST1q8HighQPseudo, ARM::VST1d8Q, false, false, false, SingleHighQSpc, 4, 8 ,false},412{ ARM::VST1q8HighQPseudo_UPD, ARM::VST1d8Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},413{ ARM::VST1q8HighTPseudo, ARM::VST1d8T, false, false, false, SingleHighTSpc, 3, 8 ,false},414{ ARM::VST1q8HighTPseudo_UPD, ARM::VST1d8Twb_fixed, false, true, true, SingleHighTSpc, 3, 8 ,false},415{ ARM::VST1q8LowQPseudo_UPD, ARM::VST1d8Qwb_fixed, false, true, true, SingleLowSpc, 4, 8 ,false},416{ ARM::VST1q8LowTPseudo_UPD, ARM::VST1d8Twb_fixed, false, true, true, SingleLowSpc, 3, 8 ,false},417418{ ARM::VST2LNd16Pseudo, ARM::VST2LNd16, false, false, false, SingleSpc, 2, 4 ,true},419{ ARM::VST2LNd16Pseudo_UPD, ARM::VST2LNd16_UPD, false, true, true, SingleSpc, 2, 4 ,true},420{ ARM::VST2LNd32Pseudo, ARM::VST2LNd32, false, false, false, SingleSpc, 2, 2 ,true},421{ ARM::VST2LNd32Pseudo_UPD, ARM::VST2LNd32_UPD, false, true, true, SingleSpc, 2, 2 ,true},422{ ARM::VST2LNd8Pseudo, ARM::VST2LNd8, false, false, false, SingleSpc, 2, 8 ,true},423{ ARM::VST2LNd8Pseudo_UPD, ARM::VST2LNd8_UPD, false, true, true, SingleSpc, 2, 8 ,true},424{ ARM::VST2LNq16Pseudo, ARM::VST2LNq16, false, false, false, EvenDblSpc, 2, 4,true},425{ ARM::VST2LNq16Pseudo_UPD, ARM::VST2LNq16_UPD, false, true, true, EvenDblSpc, 2, 4,true},426{ ARM::VST2LNq32Pseudo, ARM::VST2LNq32, false, false, false, EvenDblSpc, 2, 2,true},427{ ARM::VST2LNq32Pseudo_UPD, ARM::VST2LNq32_UPD, false, true, true, EvenDblSpc, 2, 2,true},428429{ ARM::VST2q16Pseudo, ARM::VST2q16, false, false, false, SingleSpc, 4, 4 ,false},430{ ARM::VST2q16PseudoWB_fixed, ARM::VST2q16wb_fixed, false, true, false, SingleSpc, 4, 4 ,false},431{ ARM::VST2q16PseudoWB_register, ARM::VST2q16wb_register, false, true, true, SingleSpc, 4, 4 ,false},432{ ARM::VST2q32Pseudo, ARM::VST2q32, false, false, false, SingleSpc, 4, 2 ,false},433{ ARM::VST2q32PseudoWB_fixed, ARM::VST2q32wb_fixed, false, true, false, SingleSpc, 4, 2 ,false},434{ ARM::VST2q32PseudoWB_register, ARM::VST2q32wb_register, false, true, true, SingleSpc, 4, 2 ,false},435{ ARM::VST2q8Pseudo, ARM::VST2q8, false, false, false, SingleSpc, 4, 8 ,false},436{ ARM::VST2q8PseudoWB_fixed, ARM::VST2q8wb_fixed, false, true, false, SingleSpc, 4, 8 ,false},437{ ARM::VST2q8PseudoWB_register, ARM::VST2q8wb_register, false, true, true, SingleSpc, 4, 8 ,false},438439{ ARM::VST3LNd16Pseudo, ARM::VST3LNd16, false, false, false, SingleSpc, 3, 4 ,true},440{ ARM::VST3LNd16Pseudo_UPD, ARM::VST3LNd16_UPD, false, true, true, SingleSpc, 3, 4 ,true},441{ ARM::VST3LNd32Pseudo, ARM::VST3LNd32, false, false, false, SingleSpc, 3, 2 ,true},442{ ARM::VST3LNd32Pseudo_UPD, ARM::VST3LNd32_UPD, false, true, true, SingleSpc, 3, 2 ,true},443{ ARM::VST3LNd8Pseudo, ARM::VST3LNd8, false, false, false, SingleSpc, 3, 8 ,true},444{ ARM::VST3LNd8Pseudo_UPD, ARM::VST3LNd8_UPD, false, true, true, SingleSpc, 3, 8 ,true},445{ ARM::VST3LNq16Pseudo, ARM::VST3LNq16, false, false, false, EvenDblSpc, 3, 4,true},446{ ARM::VST3LNq16Pseudo_UPD, ARM::VST3LNq16_UPD, false, true, true, EvenDblSpc, 3, 4,true},447{ ARM::VST3LNq32Pseudo, ARM::VST3LNq32, false, false, false, EvenDblSpc, 3, 2,true},448{ ARM::VST3LNq32Pseudo_UPD, ARM::VST3LNq32_UPD, false, true, true, EvenDblSpc, 3, 2,true},449450{ ARM::VST3d16Pseudo, ARM::VST3d16, false, false, false, SingleSpc, 3, 4 ,true},451{ ARM::VST3d16Pseudo_UPD, ARM::VST3d16_UPD, false, true, true, SingleSpc, 3, 4 ,true},452{ ARM::VST3d32Pseudo, ARM::VST3d32, false, false, false, SingleSpc, 3, 2 ,true},453{ ARM::VST3d32Pseudo_UPD, ARM::VST3d32_UPD, false, true, true, SingleSpc, 3, 2 ,true},454{ ARM::VST3d8Pseudo, ARM::VST3d8, false, false, false, SingleSpc, 3, 8 ,true},455{ ARM::VST3d8Pseudo_UPD, ARM::VST3d8_UPD, false, true, true, SingleSpc, 3, 8 ,true},456457{ ARM::VST3q16Pseudo_UPD, ARM::VST3q16_UPD, false, true, true, EvenDblSpc, 3, 4 ,true},458{ ARM::VST3q16oddPseudo, ARM::VST3q16, false, false, false, OddDblSpc, 3, 4 ,true},459{ ARM::VST3q16oddPseudo_UPD, ARM::VST3q16_UPD, false, true, true, OddDblSpc, 3, 4 ,true},460{ ARM::VST3q32Pseudo_UPD, ARM::VST3q32_UPD, false, true, true, EvenDblSpc, 3, 2 ,true},461{ ARM::VST3q32oddPseudo, ARM::VST3q32, false, false, false, OddDblSpc, 3, 2 ,true},462{ ARM::VST3q32oddPseudo_UPD, ARM::VST3q32_UPD, false, true, true, OddDblSpc, 3, 2 ,true},463{ ARM::VST3q8Pseudo_UPD, ARM::VST3q8_UPD, false, true, true, EvenDblSpc, 3, 8 ,true},464{ ARM::VST3q8oddPseudo, ARM::VST3q8, false, false, false, OddDblSpc, 3, 8 ,true},465{ ARM::VST3q8oddPseudo_UPD, ARM::VST3q8_UPD, false, true, true, OddDblSpc, 3, 8 ,true},466467{ ARM::VST4LNd16Pseudo, ARM::VST4LNd16, false, false, false, SingleSpc, 4, 4 ,true},468{ ARM::VST4LNd16Pseudo_UPD, ARM::VST4LNd16_UPD, false, true, true, SingleSpc, 4, 4 ,true},469{ ARM::VST4LNd32Pseudo, ARM::VST4LNd32, false, false, false, SingleSpc, 4, 2 ,true},470{ ARM::VST4LNd32Pseudo_UPD, ARM::VST4LNd32_UPD, false, true, true, SingleSpc, 4, 2 ,true},471{ ARM::VST4LNd8Pseudo, ARM::VST4LNd8, false, false, false, SingleSpc, 4, 8 ,true},472{ ARM::VST4LNd8Pseudo_UPD, ARM::VST4LNd8_UPD, false, true, true, SingleSpc, 4, 8 ,true},473{ ARM::VST4LNq16Pseudo, ARM::VST4LNq16, false, false, false, EvenDblSpc, 4, 4,true},474{ ARM::VST4LNq16Pseudo_UPD, ARM::VST4LNq16_UPD, false, true, true, EvenDblSpc, 4, 4,true},475{ ARM::VST4LNq32Pseudo, ARM::VST4LNq32, false, false, false, EvenDblSpc, 4, 2,true},476{ ARM::VST4LNq32Pseudo_UPD, ARM::VST4LNq32_UPD, false, true, true, EvenDblSpc, 4, 2,true},477478{ ARM::VST4d16Pseudo, ARM::VST4d16, false, false, false, SingleSpc, 4, 4 ,true},479{ ARM::VST4d16Pseudo_UPD, ARM::VST4d16_UPD, false, true, true, SingleSpc, 4, 4 ,true},480{ ARM::VST4d32Pseudo, ARM::VST4d32, false, false, false, SingleSpc, 4, 2 ,true},481{ ARM::VST4d32Pseudo_UPD, ARM::VST4d32_UPD, false, true, true, SingleSpc, 4, 2 ,true},482{ ARM::VST4d8Pseudo, ARM::VST4d8, false, false, false, SingleSpc, 4, 8 ,true},483{ ARM::VST4d8Pseudo_UPD, ARM::VST4d8_UPD, false, true, true, SingleSpc, 4, 8 ,true},484485{ ARM::VST4q16Pseudo_UPD, ARM::VST4q16_UPD, false, true, true, EvenDblSpc, 4, 4 ,true},486{ ARM::VST4q16oddPseudo, ARM::VST4q16, false, false, false, OddDblSpc, 4, 4 ,true},487{ ARM::VST4q16oddPseudo_UPD, ARM::VST4q16_UPD, false, true, true, OddDblSpc, 4, 4 ,true},488{ ARM::VST4q32Pseudo_UPD, ARM::VST4q32_UPD, false, true, true, EvenDblSpc, 4, 2 ,true},489{ ARM::VST4q32oddPseudo, ARM::VST4q32, false, false, false, OddDblSpc, 4, 2 ,true},490{ ARM::VST4q32oddPseudo_UPD, ARM::VST4q32_UPD, false, true, true, OddDblSpc, 4, 2 ,true},491{ ARM::VST4q8Pseudo_UPD, ARM::VST4q8_UPD, false, true, true, EvenDblSpc, 4, 8 ,true},492{ ARM::VST4q8oddPseudo, ARM::VST4q8, false, false, false, OddDblSpc, 4, 8 ,true},493{ ARM::VST4q8oddPseudo_UPD, ARM::VST4q8_UPD, false, true, true, OddDblSpc, 4, 8 ,true}494};495496/// LookupNEONLdSt - Search the NEONLdStTable for information about a NEON497/// load or store pseudo instruction.498static const NEONLdStTableEntry *LookupNEONLdSt(unsigned Opcode) {499#ifndef NDEBUG500// Make sure the table is sorted.501static std::atomic<bool> TableChecked(false);502if (!TableChecked.load(std::memory_order_relaxed)) {503assert(llvm::is_sorted(NEONLdStTable) && "NEONLdStTable is not sorted!");504TableChecked.store(true, std::memory_order_relaxed);505}506#endif507508auto I = llvm::lower_bound(NEONLdStTable, Opcode);509if (I != std::end(NEONLdStTable) && I->PseudoOpc == Opcode)510return I;511return nullptr;512}513514/// GetDSubRegs - Get 4 D subregisters of a Q, QQ, or QQQQ register,515/// corresponding to the specified register spacing. Not all of the results516/// are necessarily valid, e.g., a Q register only has 2 D subregisters.517static void GetDSubRegs(unsigned Reg, NEONRegSpacing RegSpc,518const TargetRegisterInfo *TRI, unsigned &D0,519unsigned &D1, unsigned &D2, unsigned &D3) {520if (RegSpc == SingleSpc || RegSpc == SingleLowSpc) {521D0 = TRI->getSubReg(Reg, ARM::dsub_0);522D1 = TRI->getSubReg(Reg, ARM::dsub_1);523D2 = TRI->getSubReg(Reg, ARM::dsub_2);524D3 = TRI->getSubReg(Reg, ARM::dsub_3);525} else if (RegSpc == SingleHighQSpc) {526D0 = TRI->getSubReg(Reg, ARM::dsub_4);527D1 = TRI->getSubReg(Reg, ARM::dsub_5);528D2 = TRI->getSubReg(Reg, ARM::dsub_6);529D3 = TRI->getSubReg(Reg, ARM::dsub_7);530} else if (RegSpc == SingleHighTSpc) {531D0 = TRI->getSubReg(Reg, ARM::dsub_3);532D1 = TRI->getSubReg(Reg, ARM::dsub_4);533D2 = TRI->getSubReg(Reg, ARM::dsub_5);534D3 = TRI->getSubReg(Reg, ARM::dsub_6);535} else if (RegSpc == EvenDblSpc) {536D0 = TRI->getSubReg(Reg, ARM::dsub_0);537D1 = TRI->getSubReg(Reg, ARM::dsub_2);538D2 = TRI->getSubReg(Reg, ARM::dsub_4);539D3 = TRI->getSubReg(Reg, ARM::dsub_6);540} else {541assert(RegSpc == OddDblSpc && "unknown register spacing");542D0 = TRI->getSubReg(Reg, ARM::dsub_1);543D1 = TRI->getSubReg(Reg, ARM::dsub_3);544D2 = TRI->getSubReg(Reg, ARM::dsub_5);545D3 = TRI->getSubReg(Reg, ARM::dsub_7);546}547}548549/// ExpandVLD - Translate VLD pseudo instructions with Q, QQ or QQQQ register550/// operands to real VLD instructions with D register operands.551void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) {552MachineInstr &MI = *MBBI;553MachineBasicBlock &MBB = *MI.getParent();554LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());555556const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());557assert(TableEntry && TableEntry->IsLoad && "NEONLdStTable lookup failed");558NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;559unsigned NumRegs = TableEntry->NumRegs;560561MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),562TII->get(TableEntry->RealOpc));563unsigned OpIdx = 0;564565bool DstIsDead = MI.getOperand(OpIdx).isDead();566Register DstReg = MI.getOperand(OpIdx++).getReg();567568bool IsVLD2DUP = TableEntry->RealOpc == ARM::VLD2DUPd8x2 ||569TableEntry->RealOpc == ARM::VLD2DUPd16x2 ||570TableEntry->RealOpc == ARM::VLD2DUPd32x2 ||571TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_fixed ||572TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_fixed ||573TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_fixed ||574TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_register ||575TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_register ||576TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_register;577578if (IsVLD2DUP) {579unsigned SubRegIndex;580if (RegSpc == EvenDblSpc) {581SubRegIndex = ARM::dsub_0;582} else {583assert(RegSpc == OddDblSpc && "Unexpected spacing!");584SubRegIndex = ARM::dsub_1;585}586Register SubReg = TRI->getSubReg(DstReg, SubRegIndex);587unsigned DstRegPair = TRI->getMatchingSuperReg(SubReg, ARM::dsub_0,588&ARM::DPairSpcRegClass);589MIB.addReg(DstRegPair, RegState::Define | getDeadRegState(DstIsDead));590} else {591unsigned D0, D1, D2, D3;592GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);593MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead));594if (NumRegs > 1 && TableEntry->copyAllListRegs)595MIB.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));596if (NumRegs > 2 && TableEntry->copyAllListRegs)597MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));598if (NumRegs > 3 && TableEntry->copyAllListRegs)599MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));600}601602if (TableEntry->isUpdating)603MIB.add(MI.getOperand(OpIdx++));604605// Copy the addrmode6 operands.606MIB.add(MI.getOperand(OpIdx++));607MIB.add(MI.getOperand(OpIdx++));608609// Copy the am6offset operand.610if (TableEntry->hasWritebackOperand) {611// TODO: The writing-back pseudo instructions we translate here are all612// defined to take am6offset nodes that are capable to represent both fixed613// and register forms. Some real instructions, however, do not rely on614// am6offset and have separate definitions for such forms. When this is the615// case, fixed forms do not take any offset nodes, so here we skip them for616// such instructions. Once all real and pseudo writing-back instructions are617// rewritten without use of am6offset nodes, this code will go away.618const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);619if (TableEntry->RealOpc == ARM::VLD1d8Qwb_fixed ||620TableEntry->RealOpc == ARM::VLD1d16Qwb_fixed ||621TableEntry->RealOpc == ARM::VLD1d32Qwb_fixed ||622TableEntry->RealOpc == ARM::VLD1d64Qwb_fixed ||623TableEntry->RealOpc == ARM::VLD1d8Twb_fixed ||624TableEntry->RealOpc == ARM::VLD1d16Twb_fixed ||625TableEntry->RealOpc == ARM::VLD1d32Twb_fixed ||626TableEntry->RealOpc == ARM::VLD1d64Twb_fixed ||627TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_fixed ||628TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_fixed ||629TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_fixed) {630assert(AM6Offset.getReg() == 0 &&631"A fixed writing-back pseudo instruction provides an offset "632"register!");633} else {634MIB.add(AM6Offset);635}636}637638// For an instruction writing double-spaced subregs, the pseudo instruction639// has an extra operand that is a use of the super-register. Record the640// operand index and skip over it.641unsigned SrcOpIdx = 0;642if (RegSpc == EvenDblSpc || RegSpc == OddDblSpc || RegSpc == SingleLowSpc ||643RegSpc == SingleHighQSpc || RegSpc == SingleHighTSpc)644SrcOpIdx = OpIdx++;645646// Copy the predicate operands.647MIB.add(MI.getOperand(OpIdx++));648MIB.add(MI.getOperand(OpIdx++));649650// Copy the super-register source operand used for double-spaced subregs over651// to the new instruction as an implicit operand.652if (SrcOpIdx != 0) {653MachineOperand MO = MI.getOperand(SrcOpIdx);654MO.setImplicit(true);655MIB.add(MO);656}657// Add an implicit def for the super-register.658MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));659MIB.copyImplicitOps(MI);660661// Transfer memoperands.662MIB.cloneMemRefs(MI);663MI.eraseFromParent();664LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););665}666667/// ExpandVST - Translate VST pseudo instructions with Q, QQ or QQQQ register668/// operands to real VST instructions with D register operands.669void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) {670MachineInstr &MI = *MBBI;671MachineBasicBlock &MBB = *MI.getParent();672LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());673674const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());675assert(TableEntry && !TableEntry->IsLoad && "NEONLdStTable lookup failed");676NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;677unsigned NumRegs = TableEntry->NumRegs;678679MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),680TII->get(TableEntry->RealOpc));681unsigned OpIdx = 0;682if (TableEntry->isUpdating)683MIB.add(MI.getOperand(OpIdx++));684685// Copy the addrmode6 operands.686MIB.add(MI.getOperand(OpIdx++));687MIB.add(MI.getOperand(OpIdx++));688689if (TableEntry->hasWritebackOperand) {690// TODO: The writing-back pseudo instructions we translate here are all691// defined to take am6offset nodes that are capable to represent both fixed692// and register forms. Some real instructions, however, do not rely on693// am6offset and have separate definitions for such forms. When this is the694// case, fixed forms do not take any offset nodes, so here we skip them for695// such instructions. Once all real and pseudo writing-back instructions are696// rewritten without use of am6offset nodes, this code will go away.697const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);698if (TableEntry->RealOpc == ARM::VST1d8Qwb_fixed ||699TableEntry->RealOpc == ARM::VST1d16Qwb_fixed ||700TableEntry->RealOpc == ARM::VST1d32Qwb_fixed ||701TableEntry->RealOpc == ARM::VST1d64Qwb_fixed ||702TableEntry->RealOpc == ARM::VST1d8Twb_fixed ||703TableEntry->RealOpc == ARM::VST1d16Twb_fixed ||704TableEntry->RealOpc == ARM::VST1d32Twb_fixed ||705TableEntry->RealOpc == ARM::VST1d64Twb_fixed) {706assert(AM6Offset.getReg() == 0 &&707"A fixed writing-back pseudo instruction provides an offset "708"register!");709} else {710MIB.add(AM6Offset);711}712}713714bool SrcIsKill = MI.getOperand(OpIdx).isKill();715bool SrcIsUndef = MI.getOperand(OpIdx).isUndef();716Register SrcReg = MI.getOperand(OpIdx++).getReg();717unsigned D0, D1, D2, D3;718GetDSubRegs(SrcReg, RegSpc, TRI, D0, D1, D2, D3);719MIB.addReg(D0, getUndefRegState(SrcIsUndef));720if (NumRegs > 1 && TableEntry->copyAllListRegs)721MIB.addReg(D1, getUndefRegState(SrcIsUndef));722if (NumRegs > 2 && TableEntry->copyAllListRegs)723MIB.addReg(D2, getUndefRegState(SrcIsUndef));724if (NumRegs > 3 && TableEntry->copyAllListRegs)725MIB.addReg(D3, getUndefRegState(SrcIsUndef));726727// Copy the predicate operands.728MIB.add(MI.getOperand(OpIdx++));729MIB.add(MI.getOperand(OpIdx++));730731if (SrcIsKill && !SrcIsUndef) // Add an implicit kill for the super-reg.732MIB->addRegisterKilled(SrcReg, TRI, true);733else if (!SrcIsUndef)734MIB.addReg(SrcReg, RegState::Implicit); // Add implicit uses for src reg.735MIB.copyImplicitOps(MI);736737// Transfer memoperands.738MIB.cloneMemRefs(MI);739MI.eraseFromParent();740LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););741}742743/// ExpandLaneOp - Translate VLD*LN and VST*LN instructions with Q, QQ or QQQQ744/// register operands to real instructions with D register operands.745void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) {746MachineInstr &MI = *MBBI;747MachineBasicBlock &MBB = *MI.getParent();748LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());749750const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());751assert(TableEntry && "NEONLdStTable lookup failed");752NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;753unsigned NumRegs = TableEntry->NumRegs;754unsigned RegElts = TableEntry->RegElts;755756MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),757TII->get(TableEntry->RealOpc));758unsigned OpIdx = 0;759// The lane operand is always the 3rd from last operand, before the 2760// predicate operands.761unsigned Lane = MI.getOperand(MI.getDesc().getNumOperands() - 3).getImm();762763// Adjust the lane and spacing as needed for Q registers.764assert(RegSpc != OddDblSpc && "unexpected register spacing for VLD/VST-lane");765if (RegSpc == EvenDblSpc && Lane >= RegElts) {766RegSpc = OddDblSpc;767Lane -= RegElts;768}769assert(Lane < RegElts && "out of range lane for VLD/VST-lane");770771unsigned D0 = 0, D1 = 0, D2 = 0, D3 = 0;772unsigned DstReg = 0;773bool DstIsDead = false;774if (TableEntry->IsLoad) {775DstIsDead = MI.getOperand(OpIdx).isDead();776DstReg = MI.getOperand(OpIdx++).getReg();777GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);778MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead));779if (NumRegs > 1)780MIB.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));781if (NumRegs > 2)782MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));783if (NumRegs > 3)784MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));785}786787if (TableEntry->isUpdating)788MIB.add(MI.getOperand(OpIdx++));789790// Copy the addrmode6 operands.791MIB.add(MI.getOperand(OpIdx++));792MIB.add(MI.getOperand(OpIdx++));793// Copy the am6offset operand.794if (TableEntry->hasWritebackOperand)795MIB.add(MI.getOperand(OpIdx++));796797// Grab the super-register source.798MachineOperand MO = MI.getOperand(OpIdx++);799if (!TableEntry->IsLoad)800GetDSubRegs(MO.getReg(), RegSpc, TRI, D0, D1, D2, D3);801802// Add the subregs as sources of the new instruction.803unsigned SrcFlags = (getUndefRegState(MO.isUndef()) |804getKillRegState(MO.isKill()));805MIB.addReg(D0, SrcFlags);806if (NumRegs > 1)807MIB.addReg(D1, SrcFlags);808if (NumRegs > 2)809MIB.addReg(D2, SrcFlags);810if (NumRegs > 3)811MIB.addReg(D3, SrcFlags);812813// Add the lane number operand.814MIB.addImm(Lane);815OpIdx += 1;816817// Copy the predicate operands.818MIB.add(MI.getOperand(OpIdx++));819MIB.add(MI.getOperand(OpIdx++));820821// Copy the super-register source to be an implicit source.822MO.setImplicit(true);823MIB.add(MO);824if (TableEntry->IsLoad)825// Add an implicit def for the super-register.826MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));827MIB.copyImplicitOps(MI);828// Transfer memoperands.829MIB.cloneMemRefs(MI);830MI.eraseFromParent();831}832833/// ExpandVTBL - Translate VTBL and VTBX pseudo instructions with Q or QQ834/// register operands to real instructions with D register operands.835void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI,836unsigned Opc, bool IsExt) {837MachineInstr &MI = *MBBI;838MachineBasicBlock &MBB = *MI.getParent();839LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());840841MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc));842unsigned OpIdx = 0;843844// Transfer the destination register operand.845MIB.add(MI.getOperand(OpIdx++));846if (IsExt) {847MachineOperand VdSrc(MI.getOperand(OpIdx++));848MIB.add(VdSrc);849}850851bool SrcIsKill = MI.getOperand(OpIdx).isKill();852Register SrcReg = MI.getOperand(OpIdx++).getReg();853unsigned D0, D1, D2, D3;854GetDSubRegs(SrcReg, SingleSpc, TRI, D0, D1, D2, D3);855MIB.addReg(D0);856857// Copy the other source register operand.858MachineOperand VmSrc(MI.getOperand(OpIdx++));859MIB.add(VmSrc);860861// Copy the predicate operands.862MIB.add(MI.getOperand(OpIdx++));863MIB.add(MI.getOperand(OpIdx++));864865// Add an implicit kill and use for the super-reg.866MIB.addReg(SrcReg, RegState::Implicit | getKillRegState(SrcIsKill));867MIB.copyImplicitOps(MI);868MI.eraseFromParent();869LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););870}871872void ARMExpandPseudo::ExpandMQQPRLoadStore(MachineBasicBlock::iterator &MBBI) {873MachineInstr &MI = *MBBI;874MachineBasicBlock &MBB = *MI.getParent();875unsigned NewOpc =876MI.getOpcode() == ARM::MQQPRStore || MI.getOpcode() == ARM::MQQQQPRStore877? ARM::VSTMDIA878: ARM::VLDMDIA;879MachineInstrBuilder MIB =880BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));881882unsigned Flags = getKillRegState(MI.getOperand(0).isKill()) |883getDefRegState(MI.getOperand(0).isDef());884Register SrcReg = MI.getOperand(0).getReg();885886// Copy the destination register.887MIB.add(MI.getOperand(1));888MIB.add(predOps(ARMCC::AL));889MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_0), Flags);890MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_1), Flags);891MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_2), Flags);892MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_3), Flags);893if (MI.getOpcode() == ARM::MQQQQPRStore ||894MI.getOpcode() == ARM::MQQQQPRLoad) {895MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_4), Flags);896MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_5), Flags);897MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_6), Flags);898MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_7), Flags);899}900901if (NewOpc == ARM::VSTMDIA)902MIB.addReg(SrcReg, RegState::Implicit);903904MIB.copyImplicitOps(MI);905MIB.cloneMemRefs(MI);906MI.eraseFromParent();907}908909static bool IsAnAddressOperand(const MachineOperand &MO) {910// This check is overly conservative. Unless we are certain that the machine911// operand is not a symbol reference, we return that it is a symbol reference.912// This is important as the load pair may not be split up Windows.913switch (MO.getType()) {914case MachineOperand::MO_Register:915case MachineOperand::MO_Immediate:916case MachineOperand::MO_CImmediate:917case MachineOperand::MO_FPImmediate:918case MachineOperand::MO_ShuffleMask:919return false;920case MachineOperand::MO_MachineBasicBlock:921return true;922case MachineOperand::MO_FrameIndex:923return false;924case MachineOperand::MO_ConstantPoolIndex:925case MachineOperand::MO_TargetIndex:926case MachineOperand::MO_JumpTableIndex:927case MachineOperand::MO_ExternalSymbol:928case MachineOperand::MO_GlobalAddress:929case MachineOperand::MO_BlockAddress:930return true;931case MachineOperand::MO_RegisterMask:932case MachineOperand::MO_RegisterLiveOut:933return false;934case MachineOperand::MO_Metadata:935case MachineOperand::MO_MCSymbol:936return true;937case MachineOperand::MO_DbgInstrRef:938case MachineOperand::MO_CFIIndex:939return false;940case MachineOperand::MO_IntrinsicID:941case MachineOperand::MO_Predicate:942llvm_unreachable("should not exist post-isel");943}944llvm_unreachable("unhandled machine operand type");945}946947static MachineOperand makeImplicit(const MachineOperand &MO) {948MachineOperand NewMO = MO;949NewMO.setImplicit();950return NewMO;951}952953static MachineOperand getMovOperand(const MachineOperand &MO,954unsigned TargetFlag) {955unsigned TF = MO.getTargetFlags() | TargetFlag;956switch (MO.getType()) {957case MachineOperand::MO_Immediate: {958unsigned Imm = MO.getImm();959switch (TargetFlag) {960case ARMII::MO_HI_8_15:961Imm = (Imm >> 24) & 0xff;962break;963case ARMII::MO_HI_0_7:964Imm = (Imm >> 16) & 0xff;965break;966case ARMII::MO_LO_8_15:967Imm = (Imm >> 8) & 0xff;968break;969case ARMII::MO_LO_0_7:970Imm = Imm & 0xff;971break;972case ARMII::MO_HI16:973Imm = (Imm >> 16) & 0xffff;974break;975case ARMII::MO_LO16:976Imm = Imm & 0xffff;977break;978default:979llvm_unreachable("Only HI/LO target flags are expected");980}981return MachineOperand::CreateImm(Imm);982}983case MachineOperand::MO_ExternalSymbol:984return MachineOperand::CreateES(MO.getSymbolName(), TF);985case MachineOperand::MO_JumpTableIndex:986return MachineOperand::CreateJTI(MO.getIndex(), TF);987default:988return MachineOperand::CreateGA(MO.getGlobal(), MO.getOffset(), TF);989}990}991992void ARMExpandPseudo::ExpandTMOV32BitImm(MachineBasicBlock &MBB,993MachineBasicBlock::iterator &MBBI) {994MachineInstr &MI = *MBBI;995Register DstReg = MI.getOperand(0).getReg();996bool DstIsDead = MI.getOperand(0).isDead();997const MachineOperand &MO = MI.getOperand(1);998unsigned MIFlags = MI.getFlags();9991000LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());10011002// Expand the mov into a sequence of mov/add+lsl of the individual bytes. We1003// want to avoid emitting any zero bytes, as they won't change the result, and1004// also don't want any pointless shifts, so instead of immediately emitting1005// the shift for a byte we keep track of how much we will need to shift and do1006// it before the next nonzero byte.1007unsigned PendingShift = 0;1008for (unsigned Byte = 0; Byte < 4; ++Byte) {1009unsigned Flag = Byte == 0 ? ARMII::MO_HI_8_151010: Byte == 1 ? ARMII::MO_HI_0_71011: Byte == 2 ? ARMII::MO_LO_8_151012: ARMII::MO_LO_0_7;1013MachineOperand Operand = getMovOperand(MO, Flag);1014bool ZeroImm = Operand.isImm() && Operand.getImm() == 0;1015unsigned Op = PendingShift ? ARM::tADDi8 : ARM::tMOVi8;10161017// Emit the pending shift if we're going to emit this byte or if we've1018// reached the end.1019if (PendingShift && (!ZeroImm || Byte == 3)) {1020MachineInstr *Lsl =1021BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tLSLri), DstReg)1022.add(t1CondCodeOp(true))1023.addReg(DstReg)1024.addImm(PendingShift)1025.add(predOps(ARMCC::AL))1026.setMIFlags(MIFlags);1027(void)Lsl;1028LLVM_DEBUG(dbgs() << "And: "; Lsl->dump(););1029PendingShift = 0;1030}10311032// Emit this byte if it's nonzero.1033if (!ZeroImm) {1034MachineInstrBuilder MIB =1035BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Op), DstReg)1036.add(t1CondCodeOp(true));1037if (Op == ARM::tADDi8)1038MIB.addReg(DstReg);1039MIB.add(Operand);1040MIB.add(predOps(ARMCC::AL));1041MIB.setMIFlags(MIFlags);1042LLVM_DEBUG(dbgs() << (Op == ARM::tMOVi8 ? "To: " : "And:") << " ";1043MIB.getInstr()->dump(););1044}10451046// Don't accumulate the shift value if we've not yet seen a nonzero byte.1047if (PendingShift || !ZeroImm)1048PendingShift += 8;1049}10501051// The dest is dead on the last instruction we emitted if it was dead on the1052// original instruction.1053(--MBBI)->getOperand(0).setIsDead(DstIsDead);10541055MI.eraseFromParent();1056}10571058void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB,1059MachineBasicBlock::iterator &MBBI) {1060MachineInstr &MI = *MBBI;1061unsigned Opcode = MI.getOpcode();1062Register PredReg;1063ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);1064Register DstReg = MI.getOperand(0).getReg();1065bool DstIsDead = MI.getOperand(0).isDead();1066bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm;1067const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1);1068bool RequiresBundling = STI->isTargetWindows() && IsAnAddressOperand(MO);1069MachineInstrBuilder LO16, HI16;1070LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());10711072if (!STI->hasV6T2Ops() &&1073(Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) {1074// FIXME Windows CE supports older ARM CPUs1075assert(!STI->isTargetWindows() && "Windows on ARM requires ARMv7+");10761077assert (MO.isImm() && "MOVi32imm w/ non-immediate source operand!");1078unsigned ImmVal = (unsigned)MO.getImm();1079unsigned SOImmValV1 = 0, SOImmValV2 = 0;10801081if (ARM_AM::isSOImmTwoPartVal(ImmVal)) { // Expand into a movi + orr.1082LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg);1083HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri))1084.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))1085.addReg(DstReg);1086SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal);1087SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal);1088} else { // Expand into a mvn + sub.1089LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MVNi), DstReg);1090HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri))1091.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))1092.addReg(DstReg);1093SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(-ImmVal);1094SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(-ImmVal);1095SOImmValV1 = ~(-SOImmValV1);1096}10971098unsigned MIFlags = MI.getFlags();1099LO16 = LO16.addImm(SOImmValV1);1100HI16 = HI16.addImm(SOImmValV2);1101LO16.cloneMemRefs(MI);1102HI16.cloneMemRefs(MI);1103LO16.setMIFlags(MIFlags);1104HI16.setMIFlags(MIFlags);1105LO16.addImm(Pred).addReg(PredReg).add(condCodeOp());1106HI16.addImm(Pred).addReg(PredReg).add(condCodeOp());1107if (isCC)1108LO16.add(makeImplicit(MI.getOperand(1)));1109LO16.copyImplicitOps(MI);1110HI16.copyImplicitOps(MI);1111MI.eraseFromParent();1112return;1113}11141115unsigned LO16Opc = 0;1116unsigned HI16Opc = 0;1117unsigned MIFlags = MI.getFlags();1118if (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm) {1119LO16Opc = ARM::t2MOVi16;1120HI16Opc = ARM::t2MOVTi16;1121} else {1122LO16Opc = ARM::MOVi16;1123HI16Opc = ARM::MOVTi16;1124}11251126LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg);1127LO16.setMIFlags(MIFlags);1128LO16.add(getMovOperand(MO, ARMII::MO_LO16));1129LO16.cloneMemRefs(MI);1130LO16.addImm(Pred).addReg(PredReg);1131if (isCC)1132LO16.add(makeImplicit(MI.getOperand(1)));1133LO16.copyImplicitOps(MI);1134LLVM_DEBUG(dbgs() << "To: "; LO16.getInstr()->dump(););11351136MachineOperand HIOperand = getMovOperand(MO, ARMII::MO_HI16);1137if (!(HIOperand.isImm() && HIOperand.getImm() == 0)) {1138HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc))1139.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))1140.addReg(DstReg);1141HI16.setMIFlags(MIFlags);1142HI16.add(HIOperand);1143HI16.cloneMemRefs(MI);1144HI16.addImm(Pred).addReg(PredReg);1145HI16.copyImplicitOps(MI);1146LLVM_DEBUG(dbgs() << "And: "; HI16.getInstr()->dump(););1147} else {1148LO16->getOperand(0).setIsDead(DstIsDead);1149}11501151if (RequiresBundling)1152finalizeBundle(MBB, LO16->getIterator(), MBBI->getIterator());11531154MI.eraseFromParent();1155}11561157// The size of the area, accessed by that VLSTM/VLLDM1158// S0-S31 + FPSCR + 8 more bytes (VPR + pad, or just pad)1159static const int CMSE_FP_SAVE_SIZE = 136;11601161static void determineGPRegsToClear(const MachineInstr &MI,1162const std::initializer_list<unsigned> &Regs,1163SmallVectorImpl<unsigned> &ClearRegs) {1164SmallVector<unsigned, 4> OpRegs;1165for (const MachineOperand &Op : MI.operands()) {1166if (!Op.isReg() || !Op.isUse())1167continue;1168OpRegs.push_back(Op.getReg());1169}1170llvm::sort(OpRegs);11711172std::set_difference(Regs.begin(), Regs.end(), OpRegs.begin(), OpRegs.end(),1173std::back_inserter(ClearRegs));1174}11751176void ARMExpandPseudo::CMSEClearGPRegs(1177MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,1178const DebugLoc &DL, const SmallVectorImpl<unsigned> &ClearRegs,1179unsigned ClobberReg) {11801181if (STI->hasV8_1MMainlineOps()) {1182// Clear the registers using the CLRM instruction.1183MachineInstrBuilder CLRM =1184BuildMI(MBB, MBBI, DL, TII->get(ARM::t2CLRM)).add(predOps(ARMCC::AL));1185for (unsigned R : ClearRegs)1186CLRM.addReg(R, RegState::Define);1187CLRM.addReg(ARM::APSR, RegState::Define);1188CLRM.addReg(ARM::CPSR, RegState::Define | RegState::Implicit);1189} else {1190// Clear the registers and flags by copying ClobberReg into them.1191// (Baseline can't do a high register clear in one instruction).1192for (unsigned Reg : ClearRegs) {1193if (Reg == ClobberReg)1194continue;1195BuildMI(MBB, MBBI, DL, TII->get(ARM::tMOVr), Reg)1196.addReg(ClobberReg)1197.add(predOps(ARMCC::AL));1198}11991200BuildMI(MBB, MBBI, DL, TII->get(ARM::t2MSR_M))1201.addImm(STI->hasDSP() ? 0xc00 : 0x800)1202.addReg(ClobberReg)1203.add(predOps(ARMCC::AL));1204}1205}12061207// Find which FP registers need to be cleared. The parameter `ClearRegs` is1208// initialised with all elements set to true, and this function resets all the1209// bits, which correspond to register uses. Returns true if any floating point1210// register is defined, false otherwise.1211static bool determineFPRegsToClear(const MachineInstr &MI,1212BitVector &ClearRegs) {1213bool DefFP = false;1214for (const MachineOperand &Op : MI.operands()) {1215if (!Op.isReg())1216continue;12171218Register Reg = Op.getReg();1219if (Op.isDef()) {1220if ((Reg >= ARM::Q0 && Reg <= ARM::Q7) ||1221(Reg >= ARM::D0 && Reg <= ARM::D15) ||1222(Reg >= ARM::S0 && Reg <= ARM::S31))1223DefFP = true;1224continue;1225}12261227if (Reg >= ARM::Q0 && Reg <= ARM::Q7) {1228int R = Reg - ARM::Q0;1229ClearRegs.reset(R * 4, (R + 1) * 4);1230} else if (Reg >= ARM::D0 && Reg <= ARM::D15) {1231int R = Reg - ARM::D0;1232ClearRegs.reset(R * 2, (R + 1) * 2);1233} else if (Reg >= ARM::S0 && Reg <= ARM::S31) {1234ClearRegs[Reg - ARM::S0] = false;1235}1236}1237return DefFP;1238}12391240MachineBasicBlock &1241ARMExpandPseudo::CMSEClearFPRegs(MachineBasicBlock &MBB,1242MachineBasicBlock::iterator MBBI) {1243BitVector ClearRegs(16, true);1244(void)determineFPRegsToClear(*MBBI, ClearRegs);12451246if (STI->hasV8_1MMainlineOps())1247return CMSEClearFPRegsV81(MBB, MBBI, ClearRegs);1248else1249return CMSEClearFPRegsV8(MBB, MBBI, ClearRegs);1250}12511252// Clear the FP registers for v8.0-M, by copying over the content1253// of LR. Uses R12 as a scratch register.1254MachineBasicBlock &1255ARMExpandPseudo::CMSEClearFPRegsV8(MachineBasicBlock &MBB,1256MachineBasicBlock::iterator MBBI,1257const BitVector &ClearRegs) {1258if (!STI->hasFPRegs())1259return MBB;12601261auto &RetI = *MBBI;1262const DebugLoc &DL = RetI.getDebugLoc();12631264// If optimising for minimum size, clear FP registers unconditionally.1265// Otherwise, check the CONTROL.SFPA (Secure Floating-Point Active) bit and1266// don't clear them if they belong to the non-secure state.1267MachineBasicBlock *ClearBB, *DoneBB;1268if (STI->hasMinSize()) {1269ClearBB = DoneBB = &MBB;1270} else {1271MachineFunction *MF = MBB.getParent();1272ClearBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());1273DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());12741275MF->insert(++MBB.getIterator(), ClearBB);1276MF->insert(++ClearBB->getIterator(), DoneBB);12771278DoneBB->splice(DoneBB->end(), &MBB, MBBI, MBB.end());1279DoneBB->transferSuccessors(&MBB);1280MBB.addSuccessor(ClearBB);1281MBB.addSuccessor(DoneBB);1282ClearBB->addSuccessor(DoneBB);12831284// At the new basic blocks we need to have live-in the registers, used1285// for the return value as well as LR, used to clear registers.1286for (const MachineOperand &Op : RetI.operands()) {1287if (!Op.isReg())1288continue;1289Register Reg = Op.getReg();1290if (Reg == ARM::NoRegister || Reg == ARM::LR)1291continue;1292assert(Reg.isPhysical() && "Unallocated register");1293ClearBB->addLiveIn(Reg);1294DoneBB->addLiveIn(Reg);1295}1296ClearBB->addLiveIn(ARM::LR);1297DoneBB->addLiveIn(ARM::LR);12981299// Read the CONTROL register.1300BuildMI(MBB, MBB.end(), DL, TII->get(ARM::t2MRS_M), ARM::R12)1301.addImm(20)1302.add(predOps(ARMCC::AL));1303// Check bit 3 (SFPA).1304BuildMI(MBB, MBB.end(), DL, TII->get(ARM::t2TSTri))1305.addReg(ARM::R12)1306.addImm(8)1307.add(predOps(ARMCC::AL));1308// If SFPA is clear, jump over ClearBB to DoneBB.1309BuildMI(MBB, MBB.end(), DL, TII->get(ARM::tBcc))1310.addMBB(DoneBB)1311.addImm(ARMCC::EQ)1312.addReg(ARM::CPSR, RegState::Kill);1313}13141315// Emit the clearing sequence1316for (unsigned D = 0; D < 8; D++) {1317// Attempt to clear as double1318if (ClearRegs[D * 2 + 0] && ClearRegs[D * 2 + 1]) {1319unsigned Reg = ARM::D0 + D;1320BuildMI(ClearBB, DL, TII->get(ARM::VMOVDRR), Reg)1321.addReg(ARM::LR)1322.addReg(ARM::LR)1323.add(predOps(ARMCC::AL));1324} else {1325// Clear first part as single1326if (ClearRegs[D * 2 + 0]) {1327unsigned Reg = ARM::S0 + D * 2;1328BuildMI(ClearBB, DL, TII->get(ARM::VMOVSR), Reg)1329.addReg(ARM::LR)1330.add(predOps(ARMCC::AL));1331}1332// Clear second part as single1333if (ClearRegs[D * 2 + 1]) {1334unsigned Reg = ARM::S0 + D * 2 + 1;1335BuildMI(ClearBB, DL, TII->get(ARM::VMOVSR), Reg)1336.addReg(ARM::LR)1337.add(predOps(ARMCC::AL));1338}1339}1340}13411342// Clear FPSCR bits 0-4, 7, 28-311343// The other bits are program global according to the AAPCS1344BuildMI(ClearBB, DL, TII->get(ARM::VMRS), ARM::R12)1345.add(predOps(ARMCC::AL));1346BuildMI(ClearBB, DL, TII->get(ARM::t2BICri), ARM::R12)1347.addReg(ARM::R12)1348.addImm(0x0000009F)1349.add(predOps(ARMCC::AL))1350.add(condCodeOp());1351BuildMI(ClearBB, DL, TII->get(ARM::t2BICri), ARM::R12)1352.addReg(ARM::R12)1353.addImm(0xF0000000)1354.add(predOps(ARMCC::AL))1355.add(condCodeOp());1356BuildMI(ClearBB, DL, TII->get(ARM::VMSR))1357.addReg(ARM::R12)1358.add(predOps(ARMCC::AL));13591360return *DoneBB;1361}13621363MachineBasicBlock &1364ARMExpandPseudo::CMSEClearFPRegsV81(MachineBasicBlock &MBB,1365MachineBasicBlock::iterator MBBI,1366const BitVector &ClearRegs) {1367auto &RetI = *MBBI;13681369// Emit a sequence of VSCCLRM <sreglist> instructions, one instruction for1370// each contiguous sequence of S-registers.1371int Start = -1, End = -1;1372for (int S = 0, E = ClearRegs.size(); S != E; ++S) {1373if (ClearRegs[S] && S == End + 1) {1374End = S; // extend range1375continue;1376}1377// Emit current range.1378if (Start < End) {1379MachineInstrBuilder VSCCLRM =1380BuildMI(MBB, MBBI, RetI.getDebugLoc(), TII->get(ARM::VSCCLRMS))1381.add(predOps(ARMCC::AL));1382while (++Start <= End)1383VSCCLRM.addReg(ARM::S0 + Start, RegState::Define);1384VSCCLRM.addReg(ARM::VPR, RegState::Define);1385}1386Start = End = S;1387}1388// Emit last range.1389if (Start < End) {1390MachineInstrBuilder VSCCLRM =1391BuildMI(MBB, MBBI, RetI.getDebugLoc(), TII->get(ARM::VSCCLRMS))1392.add(predOps(ARMCC::AL));1393while (++Start <= End)1394VSCCLRM.addReg(ARM::S0 + Start, RegState::Define);1395VSCCLRM.addReg(ARM::VPR, RegState::Define);1396}13971398return MBB;1399}14001401void ARMExpandPseudo::CMSESaveClearFPRegs(1402MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,1403const LivePhysRegs &LiveRegs, SmallVectorImpl<unsigned> &ScratchRegs) {1404if (STI->hasV8_1MMainlineOps())1405CMSESaveClearFPRegsV81(MBB, MBBI, DL, LiveRegs);1406else if (STI->hasV8MMainlineOps())1407CMSESaveClearFPRegsV8(MBB, MBBI, DL, LiveRegs, ScratchRegs);1408}14091410// Save and clear FP registers if present1411void ARMExpandPseudo::CMSESaveClearFPRegsV8(1412MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,1413const LivePhysRegs &LiveRegs, SmallVectorImpl<unsigned> &ScratchRegs) {14141415// Store an available register for FPSCR clearing1416assert(!ScratchRegs.empty());1417unsigned SpareReg = ScratchRegs.front();14181419// save space on stack for VLSTM1420BuildMI(MBB, MBBI, DL, TII->get(ARM::tSUBspi), ARM::SP)1421.addReg(ARM::SP)1422.addImm(CMSE_FP_SAVE_SIZE >> 2)1423.add(predOps(ARMCC::AL));14241425// Use ScratchRegs to store the fp regs1426std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;1427std::vector<unsigned> NonclearedFPRegs;1428for (const MachineOperand &Op : MBBI->operands()) {1429if (Op.isReg() && Op.isUse()) {1430Register Reg = Op.getReg();1431assert(!ARM::DPRRegClass.contains(Reg) ||1432ARM::DPR_VFP2RegClass.contains(Reg));1433assert(!ARM::QPRRegClass.contains(Reg));1434if (ARM::DPR_VFP2RegClass.contains(Reg)) {1435if (ScratchRegs.size() >= 2) {1436unsigned SaveReg2 = ScratchRegs.pop_back_val();1437unsigned SaveReg1 = ScratchRegs.pop_back_val();1438ClearedFPRegs.emplace_back(Reg, SaveReg1, SaveReg2);14391440// Save the fp register to the normal registers1441BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRRD))1442.addReg(SaveReg1, RegState::Define)1443.addReg(SaveReg2, RegState::Define)1444.addReg(Reg)1445.add(predOps(ARMCC::AL));1446} else {1447NonclearedFPRegs.push_back(Reg);1448}1449} else if (ARM::SPRRegClass.contains(Reg)) {1450if (ScratchRegs.size() >= 1) {1451unsigned SaveReg = ScratchRegs.pop_back_val();1452ClearedFPRegs.emplace_back(Reg, SaveReg, 0);14531454// Save the fp register to the normal registers1455BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRS), SaveReg)1456.addReg(Reg)1457.add(predOps(ARMCC::AL));1458} else {1459NonclearedFPRegs.push_back(Reg);1460}1461}1462}1463}14641465bool passesFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());14661467if (passesFPReg)1468assert(STI->hasFPRegs() && "Subtarget needs fpregs");14691470// Lazy store all fp registers to the stack.1471// This executes as NOP in the absence of floating-point support.1472MachineInstrBuilder VLSTM =1473BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM))1474.addReg(ARM::SP)1475.add(predOps(ARMCC::AL))1476.addImm(0); // Represents a pseoudo register list, has no effect on1477// the encoding.1478// Mark non-live registers as undef1479for (MachineOperand &MO : VLSTM->implicit_operands()) {1480if (MO.isReg() && !MO.isDef()) {1481Register Reg = MO.getReg();1482MO.setIsUndef(!LiveRegs.contains(Reg));1483}1484}14851486// Restore all arguments1487for (const auto &Regs : ClearedFPRegs) {1488unsigned Reg, SaveReg1, SaveReg2;1489std::tie(Reg, SaveReg1, SaveReg2) = Regs;1490if (ARM::DPR_VFP2RegClass.contains(Reg))1491BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVDRR), Reg)1492.addReg(SaveReg1)1493.addReg(SaveReg2)1494.add(predOps(ARMCC::AL));1495else if (ARM::SPRRegClass.contains(Reg))1496BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVSR), Reg)1497.addReg(SaveReg1)1498.add(predOps(ARMCC::AL));1499}15001501for (unsigned Reg : NonclearedFPRegs) {1502if (ARM::DPR_VFP2RegClass.contains(Reg)) {1503if (STI->isLittle()) {1504BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRD), Reg)1505.addReg(ARM::SP)1506.addImm((Reg - ARM::D0) * 2)1507.add(predOps(ARMCC::AL));1508} else {1509// For big-endian targets we need to load the two subregisters of Reg1510// manually because VLDRD would load them in wrong order1511unsigned SReg0 = TRI->getSubReg(Reg, ARM::ssub_0);1512BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), SReg0)1513.addReg(ARM::SP)1514.addImm((Reg - ARM::D0) * 2)1515.add(predOps(ARMCC::AL));1516BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), SReg0 + 1)1517.addReg(ARM::SP)1518.addImm((Reg - ARM::D0) * 2 + 1)1519.add(predOps(ARMCC::AL));1520}1521} else if (ARM::SPRRegClass.contains(Reg)) {1522BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), Reg)1523.addReg(ARM::SP)1524.addImm(Reg - ARM::S0)1525.add(predOps(ARMCC::AL));1526}1527}1528// restore FPSCR from stack and clear bits 0-4, 7, 28-311529// The other bits are program global according to the AAPCS1530if (passesFPReg) {1531BuildMI(MBB, MBBI, DL, TII->get(ARM::tLDRspi), SpareReg)1532.addReg(ARM::SP)1533.addImm(0x10)1534.add(predOps(ARMCC::AL));1535BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), SpareReg)1536.addReg(SpareReg)1537.addImm(0x0000009F)1538.add(predOps(ARMCC::AL))1539.add(condCodeOp());1540BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), SpareReg)1541.addReg(SpareReg)1542.addImm(0xF0000000)1543.add(predOps(ARMCC::AL))1544.add(condCodeOp());1545BuildMI(MBB, MBBI, DL, TII->get(ARM::VMSR))1546.addReg(SpareReg)1547.add(predOps(ARMCC::AL));1548// The ldr must happen after a floating point instruction. To prevent the1549// post-ra scheduler to mess with the order, we create a bundle.1550finalizeBundle(MBB, VLSTM->getIterator(), MBBI->getIterator());1551}1552}15531554void ARMExpandPseudo::CMSESaveClearFPRegsV81(MachineBasicBlock &MBB,1555MachineBasicBlock::iterator MBBI,1556DebugLoc &DL,1557const LivePhysRegs &LiveRegs) {1558BitVector ClearRegs(32, true);1559bool DefFP = determineFPRegsToClear(*MBBI, ClearRegs);15601561// If the instruction does not write to a FP register and no elements were1562// removed from the set, then no FP registers were used to pass1563// arguments/returns.1564if (!DefFP && ClearRegs.count() == ClearRegs.size()) {1565// save space on stack for VLSTM1566BuildMI(MBB, MBBI, DL, TII->get(ARM::tSUBspi), ARM::SP)1567.addReg(ARM::SP)1568.addImm(CMSE_FP_SAVE_SIZE >> 2)1569.add(predOps(ARMCC::AL));15701571// Lazy store all FP registers to the stack1572MachineInstrBuilder VLSTM =1573BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM))1574.addReg(ARM::SP)1575.add(predOps(ARMCC::AL))1576.addImm(0); // Represents a pseoudo register list, has no effect on1577// the encoding.1578// Mark non-live registers as undef1579for (MachineOperand &MO : VLSTM->implicit_operands()) {1580if (MO.isReg() && MO.isImplicit() && !MO.isDef()) {1581Register Reg = MO.getReg();1582MO.setIsUndef(!LiveRegs.contains(Reg));1583}1584}1585} else {1586// Push all the callee-saved registers (s16-s31).1587MachineInstrBuilder VPUSH =1588BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTMSDB_UPD), ARM::SP)1589.addReg(ARM::SP)1590.add(predOps(ARMCC::AL));1591for (int Reg = ARM::S16; Reg <= ARM::S31; ++Reg)1592VPUSH.addReg(Reg);15931594// Clear FP registers with a VSCCLRM.1595(void)CMSEClearFPRegsV81(MBB, MBBI, ClearRegs);15961597// Save floating-point context.1598BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTR_FPCXTS_pre), ARM::SP)1599.addReg(ARM::SP)1600.addImm(-8)1601.add(predOps(ARMCC::AL));1602}1603}16041605// Restore FP registers if present1606void ARMExpandPseudo::CMSERestoreFPRegs(1607MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,1608SmallVectorImpl<unsigned> &AvailableRegs) {1609if (STI->hasV8_1MMainlineOps())1610CMSERestoreFPRegsV81(MBB, MBBI, DL, AvailableRegs);1611else if (STI->hasV8MMainlineOps())1612CMSERestoreFPRegsV8(MBB, MBBI, DL, AvailableRegs);1613}16141615void ARMExpandPseudo::CMSERestoreFPRegsV8(1616MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,1617SmallVectorImpl<unsigned> &AvailableRegs) {16181619// Keep a scratch register for the mitigation sequence.1620unsigned ScratchReg = ARM::NoRegister;1621if (STI->fixCMSE_CVE_2021_35465())1622ScratchReg = AvailableRegs.pop_back_val();16231624// Use AvailableRegs to store the fp regs1625std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;1626std::vector<unsigned> NonclearedFPRegs;1627for (const MachineOperand &Op : MBBI->operands()) {1628if (Op.isReg() && Op.isDef()) {1629Register Reg = Op.getReg();1630assert(!ARM::DPRRegClass.contains(Reg) ||1631ARM::DPR_VFP2RegClass.contains(Reg));1632assert(!ARM::QPRRegClass.contains(Reg));1633if (ARM::DPR_VFP2RegClass.contains(Reg)) {1634if (AvailableRegs.size() >= 2) {1635unsigned SaveReg2 = AvailableRegs.pop_back_val();1636unsigned SaveReg1 = AvailableRegs.pop_back_val();1637ClearedFPRegs.emplace_back(Reg, SaveReg1, SaveReg2);16381639// Save the fp register to the normal registers1640BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRRD))1641.addReg(SaveReg1, RegState::Define)1642.addReg(SaveReg2, RegState::Define)1643.addReg(Reg)1644.add(predOps(ARMCC::AL));1645} else {1646NonclearedFPRegs.push_back(Reg);1647}1648} else if (ARM::SPRRegClass.contains(Reg)) {1649if (AvailableRegs.size() >= 1) {1650unsigned SaveReg = AvailableRegs.pop_back_val();1651ClearedFPRegs.emplace_back(Reg, SaveReg, 0);16521653// Save the fp register to the normal registers1654BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRS), SaveReg)1655.addReg(Reg)1656.add(predOps(ARMCC::AL));1657} else {1658NonclearedFPRegs.push_back(Reg);1659}1660}1661}1662}16631664bool returnsFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());16651666if (returnsFPReg)1667assert(STI->hasFPRegs() && "Subtarget needs fpregs");16681669// Push FP regs that cannot be restored via normal registers on the stack1670for (unsigned Reg : NonclearedFPRegs) {1671if (ARM::DPR_VFP2RegClass.contains(Reg))1672BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTRD))1673.addReg(Reg)1674.addReg(ARM::SP)1675.addImm((Reg - ARM::D0) * 2)1676.add(predOps(ARMCC::AL));1677else if (ARM::SPRRegClass.contains(Reg))1678BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTRS))1679.addReg(Reg)1680.addReg(ARM::SP)1681.addImm(Reg - ARM::S0)1682.add(predOps(ARMCC::AL));1683}16841685// Lazy load fp regs from stack.1686// This executes as NOP in the absence of floating-point support.1687MachineInstrBuilder VLLDM =1688BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM))1689.addReg(ARM::SP)1690.add(predOps(ARMCC::AL))1691.addImm(0); // Represents a pseoudo register list, has no effect on1692// the encoding.16931694if (STI->fixCMSE_CVE_2021_35465()) {1695auto Bundler = MIBundleBuilder(MBB, VLLDM);1696// Read the CONTROL register.1697Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2MRS_M))1698.addReg(ScratchReg, RegState::Define)1699.addImm(20)1700.add(predOps(ARMCC::AL)));1701// Check bit 3 (SFPA).1702Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2TSTri))1703.addReg(ScratchReg)1704.addImm(8)1705.add(predOps(ARMCC::AL)));1706// Emit the IT block.1707Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2IT))1708.addImm(ARMCC::NE)1709.addImm(8));1710// If SFPA is clear jump over to VLLDM, otherwise execute an instruction1711// which has no functional effect apart from causing context creation:1712// vmovne s0, s0. In the absence of FPU we emit .inst.w 0xeeb00a40,1713// which is defined as NOP if not executed.1714if (STI->hasFPRegs())1715Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::VMOVS))1716.addReg(ARM::S0, RegState::Define)1717.addReg(ARM::S0, RegState::Undef)1718.add(predOps(ARMCC::NE)));1719else1720Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::INLINEASM))1721.addExternalSymbol(".inst.w 0xeeb00a40")1722.addImm(InlineAsm::Extra_HasSideEffects));1723finalizeBundle(MBB, Bundler.begin(), Bundler.end());1724}17251726// Restore all FP registers via normal registers1727for (const auto &Regs : ClearedFPRegs) {1728unsigned Reg, SaveReg1, SaveReg2;1729std::tie(Reg, SaveReg1, SaveReg2) = Regs;1730if (ARM::DPR_VFP2RegClass.contains(Reg))1731BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVDRR), Reg)1732.addReg(SaveReg1)1733.addReg(SaveReg2)1734.add(predOps(ARMCC::AL));1735else if (ARM::SPRRegClass.contains(Reg))1736BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVSR), Reg)1737.addReg(SaveReg1)1738.add(predOps(ARMCC::AL));1739}17401741// Pop the stack space1742BuildMI(MBB, MBBI, DL, TII->get(ARM::tADDspi), ARM::SP)1743.addReg(ARM::SP)1744.addImm(CMSE_FP_SAVE_SIZE >> 2)1745.add(predOps(ARMCC::AL));1746}17471748static bool definesOrUsesFPReg(const MachineInstr &MI) {1749for (const MachineOperand &Op : MI.operands()) {1750if (!Op.isReg())1751continue;1752Register Reg = Op.getReg();1753if ((Reg >= ARM::Q0 && Reg <= ARM::Q7) ||1754(Reg >= ARM::D0 && Reg <= ARM::D15) ||1755(Reg >= ARM::S0 && Reg <= ARM::S31))1756return true;1757}1758return false;1759}17601761void ARMExpandPseudo::CMSERestoreFPRegsV81(1762MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,1763SmallVectorImpl<unsigned> &AvailableRegs) {1764if (!definesOrUsesFPReg(*MBBI)) {1765if (STI->fixCMSE_CVE_2021_35465()) {1766BuildMI(MBB, MBBI, DL, TII->get(ARM::VSCCLRMS))1767.add(predOps(ARMCC::AL))1768.addReg(ARM::VPR, RegState::Define);1769}17701771// Load FP registers from stack.1772BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM))1773.addReg(ARM::SP)1774.add(predOps(ARMCC::AL))1775.addImm(0); // Represents a pseoudo register list, has no effect on the1776// encoding.17771778// Pop the stack space1779BuildMI(MBB, MBBI, DL, TII->get(ARM::tADDspi), ARM::SP)1780.addReg(ARM::SP)1781.addImm(CMSE_FP_SAVE_SIZE >> 2)1782.add(predOps(ARMCC::AL));1783} else {1784// Restore the floating point context.1785BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(ARM::VLDR_FPCXTS_post),1786ARM::SP)1787.addReg(ARM::SP)1788.addImm(8)1789.add(predOps(ARMCC::AL));17901791// Pop all the callee-saved registers (s16-s31).1792MachineInstrBuilder VPOP =1793BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDMSIA_UPD), ARM::SP)1794.addReg(ARM::SP)1795.add(predOps(ARMCC::AL));1796for (int Reg = ARM::S16; Reg <= ARM::S31; ++Reg)1797VPOP.addReg(Reg, RegState::Define);1798}1799}18001801/// Expand a CMP_SWAP pseudo-inst to an ldrex/strex loop as simply as1802/// possible. This only gets used at -O0 so we don't care about efficiency of1803/// the generated code.1804bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,1805MachineBasicBlock::iterator MBBI,1806unsigned LdrexOp, unsigned StrexOp,1807unsigned UxtOp,1808MachineBasicBlock::iterator &NextMBBI) {1809bool IsThumb = STI->isThumb();1810bool IsThumb1Only = STI->isThumb1Only();1811MachineInstr &MI = *MBBI;1812DebugLoc DL = MI.getDebugLoc();1813const MachineOperand &Dest = MI.getOperand(0);1814Register TempReg = MI.getOperand(1).getReg();1815// Duplicating undef operands into 2 instructions does not guarantee the same1816// value on both; However undef should be replaced by xzr anyway.1817assert(!MI.getOperand(2).isUndef() && "cannot handle undef");1818Register AddrReg = MI.getOperand(2).getReg();1819Register DesiredReg = MI.getOperand(3).getReg();1820Register NewReg = MI.getOperand(4).getReg();18211822if (IsThumb) {1823assert(STI->hasV8MBaselineOps() &&1824"CMP_SWAP not expected to be custom expanded for Thumb1");1825assert((UxtOp == 0 || UxtOp == ARM::tUXTB || UxtOp == ARM::tUXTH) &&1826"ARMv8-M.baseline does not have t2UXTB/t2UXTH");1827assert((UxtOp == 0 || ARM::tGPRRegClass.contains(DesiredReg)) &&1828"DesiredReg used for UXT op must be tGPR");1829}18301831MachineFunction *MF = MBB.getParent();1832auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());1833auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());1834auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());18351836MF->insert(++MBB.getIterator(), LoadCmpBB);1837MF->insert(++LoadCmpBB->getIterator(), StoreBB);1838MF->insert(++StoreBB->getIterator(), DoneBB);18391840if (UxtOp) {1841MachineInstrBuilder MIB =1842BuildMI(MBB, MBBI, DL, TII->get(UxtOp), DesiredReg)1843.addReg(DesiredReg, RegState::Kill);1844if (!IsThumb)1845MIB.addImm(0);1846MIB.add(predOps(ARMCC::AL));1847}18481849// .Lloadcmp:1850// ldrex rDest, [rAddr]1851// cmp rDest, rDesired1852// bne .Ldone18531854MachineInstrBuilder MIB;1855MIB = BuildMI(LoadCmpBB, DL, TII->get(LdrexOp), Dest.getReg());1856MIB.addReg(AddrReg);1857if (LdrexOp == ARM::t2LDREX)1858MIB.addImm(0); // a 32-bit Thumb ldrex (only) allows an offset.1859MIB.add(predOps(ARMCC::AL));18601861unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;1862BuildMI(LoadCmpBB, DL, TII->get(CMPrr))1863.addReg(Dest.getReg(), getKillRegState(Dest.isDead()))1864.addReg(DesiredReg)1865.add(predOps(ARMCC::AL));1866unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;1867BuildMI(LoadCmpBB, DL, TII->get(Bcc))1868.addMBB(DoneBB)1869.addImm(ARMCC::NE)1870.addReg(ARM::CPSR, RegState::Kill);1871LoadCmpBB->addSuccessor(DoneBB);1872LoadCmpBB->addSuccessor(StoreBB);18731874// .Lstore:1875// strex rTempReg, rNew, [rAddr]1876// cmp rTempReg, #01877// bne .Lloadcmp1878MIB = BuildMI(StoreBB, DL, TII->get(StrexOp), TempReg)1879.addReg(NewReg)1880.addReg(AddrReg);1881if (StrexOp == ARM::t2STREX)1882MIB.addImm(0); // a 32-bit Thumb strex (only) allows an offset.1883MIB.add(predOps(ARMCC::AL));18841885unsigned CMPri =1886IsThumb ? (IsThumb1Only ? ARM::tCMPi8 : ARM::t2CMPri) : ARM::CMPri;1887BuildMI(StoreBB, DL, TII->get(CMPri))1888.addReg(TempReg, RegState::Kill)1889.addImm(0)1890.add(predOps(ARMCC::AL));1891BuildMI(StoreBB, DL, TII->get(Bcc))1892.addMBB(LoadCmpBB)1893.addImm(ARMCC::NE)1894.addReg(ARM::CPSR, RegState::Kill);1895StoreBB->addSuccessor(LoadCmpBB);1896StoreBB->addSuccessor(DoneBB);18971898DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());1899DoneBB->transferSuccessors(&MBB);19001901MBB.addSuccessor(LoadCmpBB);19021903NextMBBI = MBB.end();1904MI.eraseFromParent();19051906// Recompute livein lists.1907LivePhysRegs LiveRegs;1908computeAndAddLiveIns(LiveRegs, *DoneBB);1909computeAndAddLiveIns(LiveRegs, *StoreBB);1910computeAndAddLiveIns(LiveRegs, *LoadCmpBB);1911// Do an extra pass around the loop to get loop carried registers right.1912StoreBB->clearLiveIns();1913computeAndAddLiveIns(LiveRegs, *StoreBB);1914LoadCmpBB->clearLiveIns();1915computeAndAddLiveIns(LiveRegs, *LoadCmpBB);19161917return true;1918}19191920/// ARM's ldrexd/strexd take a consecutive register pair (represented as a1921/// single GPRPair register), Thumb's take two separate registers so we need to1922/// extract the subregs from the pair.1923static void addExclusiveRegPair(MachineInstrBuilder &MIB, MachineOperand &Reg,1924unsigned Flags, bool IsThumb,1925const TargetRegisterInfo *TRI) {1926if (IsThumb) {1927Register RegLo = TRI->getSubReg(Reg.getReg(), ARM::gsub_0);1928Register RegHi = TRI->getSubReg(Reg.getReg(), ARM::gsub_1);1929MIB.addReg(RegLo, Flags);1930MIB.addReg(RegHi, Flags);1931} else1932MIB.addReg(Reg.getReg(), Flags);1933}19341935/// Expand a 64-bit CMP_SWAP to an ldrexd/strexd loop.1936bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,1937MachineBasicBlock::iterator MBBI,1938MachineBasicBlock::iterator &NextMBBI) {1939bool IsThumb = STI->isThumb();1940assert(!STI->isThumb1Only() && "CMP_SWAP_64 unsupported under Thumb1!");1941MachineInstr &MI = *MBBI;1942DebugLoc DL = MI.getDebugLoc();1943MachineOperand &Dest = MI.getOperand(0);1944Register TempReg = MI.getOperand(1).getReg();1945// Duplicating undef operands into 2 instructions does not guarantee the same1946// value on both; However undef should be replaced by xzr anyway.1947assert(!MI.getOperand(2).isUndef() && "cannot handle undef");1948Register AddrReg = MI.getOperand(2).getReg();1949Register DesiredReg = MI.getOperand(3).getReg();1950MachineOperand New = MI.getOperand(4);1951New.setIsKill(false);19521953Register DestLo = TRI->getSubReg(Dest.getReg(), ARM::gsub_0);1954Register DestHi = TRI->getSubReg(Dest.getReg(), ARM::gsub_1);1955Register DesiredLo = TRI->getSubReg(DesiredReg, ARM::gsub_0);1956Register DesiredHi = TRI->getSubReg(DesiredReg, ARM::gsub_1);19571958MachineFunction *MF = MBB.getParent();1959auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());1960auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());1961auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());19621963MF->insert(++MBB.getIterator(), LoadCmpBB);1964MF->insert(++LoadCmpBB->getIterator(), StoreBB);1965MF->insert(++StoreBB->getIterator(), DoneBB);19661967// .Lloadcmp:1968// ldrexd rDestLo, rDestHi, [rAddr]1969// cmp rDestLo, rDesiredLo1970// sbcs dead rTempReg, rDestHi, rDesiredHi1971// bne .Ldone1972unsigned LDREXD = IsThumb ? ARM::t2LDREXD : ARM::LDREXD;1973MachineInstrBuilder MIB;1974MIB = BuildMI(LoadCmpBB, DL, TII->get(LDREXD));1975addExclusiveRegPair(MIB, Dest, RegState::Define, IsThumb, TRI);1976MIB.addReg(AddrReg).add(predOps(ARMCC::AL));19771978unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;1979BuildMI(LoadCmpBB, DL, TII->get(CMPrr))1980.addReg(DestLo, getKillRegState(Dest.isDead()))1981.addReg(DesiredLo)1982.add(predOps(ARMCC::AL));19831984BuildMI(LoadCmpBB, DL, TII->get(CMPrr))1985.addReg(DestHi, getKillRegState(Dest.isDead()))1986.addReg(DesiredHi)1987.addImm(ARMCC::EQ).addReg(ARM::CPSR, RegState::Kill);19881989unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;1990BuildMI(LoadCmpBB, DL, TII->get(Bcc))1991.addMBB(DoneBB)1992.addImm(ARMCC::NE)1993.addReg(ARM::CPSR, RegState::Kill);1994LoadCmpBB->addSuccessor(DoneBB);1995LoadCmpBB->addSuccessor(StoreBB);19961997// .Lstore:1998// strexd rTempReg, rNewLo, rNewHi, [rAddr]1999// cmp rTempReg, #02000// bne .Lloadcmp2001unsigned STREXD = IsThumb ? ARM::t2STREXD : ARM::STREXD;2002MIB = BuildMI(StoreBB, DL, TII->get(STREXD), TempReg);2003unsigned Flags = getKillRegState(New.isDead());2004addExclusiveRegPair(MIB, New, Flags, IsThumb, TRI);2005MIB.addReg(AddrReg).add(predOps(ARMCC::AL));20062007unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;2008BuildMI(StoreBB, DL, TII->get(CMPri))2009.addReg(TempReg, RegState::Kill)2010.addImm(0)2011.add(predOps(ARMCC::AL));2012BuildMI(StoreBB, DL, TII->get(Bcc))2013.addMBB(LoadCmpBB)2014.addImm(ARMCC::NE)2015.addReg(ARM::CPSR, RegState::Kill);2016StoreBB->addSuccessor(LoadCmpBB);2017StoreBB->addSuccessor(DoneBB);20182019DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());2020DoneBB->transferSuccessors(&MBB);20212022MBB.addSuccessor(LoadCmpBB);20232024NextMBBI = MBB.end();2025MI.eraseFromParent();20262027// Recompute livein lists.2028LivePhysRegs LiveRegs;2029computeAndAddLiveIns(LiveRegs, *DoneBB);2030computeAndAddLiveIns(LiveRegs, *StoreBB);2031computeAndAddLiveIns(LiveRegs, *LoadCmpBB);2032// Do an extra pass around the loop to get loop carried registers right.2033StoreBB->clearLiveIns();2034computeAndAddLiveIns(LiveRegs, *StoreBB);2035LoadCmpBB->clearLiveIns();2036computeAndAddLiveIns(LiveRegs, *LoadCmpBB);20372038return true;2039}20402041static void CMSEPushCalleeSaves(const TargetInstrInfo &TII,2042MachineBasicBlock &MBB,2043MachineBasicBlock::iterator MBBI, int JumpReg,2044const LivePhysRegs &LiveRegs, bool Thumb1Only) {2045const DebugLoc &DL = MBBI->getDebugLoc();2046if (Thumb1Only) { // push Lo and Hi regs separately2047MachineInstrBuilder PushMIB =2048BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));2049for (int Reg = ARM::R4; Reg < ARM::R8; ++Reg) {2050PushMIB.addReg(2051Reg, Reg == JumpReg || LiveRegs.contains(Reg) ? 0 : RegState::Undef);2052}20532054// Thumb1 can only tPUSH low regs, so we copy the high regs to the low2055// regs that we just saved and push the low regs again, taking care to2056// not clobber JumpReg. If JumpReg is one of the low registers, push first2057// the values of r9-r11, and then r8. That would leave them ordered in2058// memory, and allow us to later pop them with a single instructions.2059// FIXME: Could also use any of r0-r3 that are free (including in the2060// first PUSH above).2061for (int LoReg = ARM::R7, HiReg = ARM::R11; LoReg >= ARM::R4; --LoReg) {2062if (JumpReg == LoReg)2063continue;2064BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), LoReg)2065.addReg(HiReg, LiveRegs.contains(HiReg) ? 0 : RegState::Undef)2066.add(predOps(ARMCC::AL));2067--HiReg;2068}2069MachineInstrBuilder PushMIB2 =2070BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));2071for (int Reg = ARM::R4; Reg < ARM::R8; ++Reg) {2072if (Reg == JumpReg)2073continue;2074PushMIB2.addReg(Reg, RegState::Kill);2075}20762077// If we couldn't use a low register for temporary storage (because it was2078// the JumpReg), use r4 or r5, whichever is not JumpReg. It has already been2079// saved.2080if (JumpReg >= ARM::R4 && JumpReg <= ARM::R7) {2081int LoReg = JumpReg == ARM::R4 ? ARM::R5 : ARM::R4;2082BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), LoReg)2083.addReg(ARM::R8, LiveRegs.contains(ARM::R8) ? 0 : RegState::Undef)2084.add(predOps(ARMCC::AL));2085BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH))2086.add(predOps(ARMCC::AL))2087.addReg(LoReg, RegState::Kill);2088}2089} else { // push Lo and Hi registers with a single instruction2090MachineInstrBuilder PushMIB =2091BuildMI(MBB, MBBI, DL, TII.get(ARM::t2STMDB_UPD), ARM::SP)2092.addReg(ARM::SP)2093.add(predOps(ARMCC::AL));2094for (int Reg = ARM::R4; Reg < ARM::R12; ++Reg) {2095PushMIB.addReg(2096Reg, Reg == JumpReg || LiveRegs.contains(Reg) ? 0 : RegState::Undef);2097}2098}2099}21002101static void CMSEPopCalleeSaves(const TargetInstrInfo &TII,2102MachineBasicBlock &MBB,2103MachineBasicBlock::iterator MBBI, int JumpReg,2104bool Thumb1Only) {2105const DebugLoc &DL = MBBI->getDebugLoc();2106if (Thumb1Only) {2107MachineInstrBuilder PopMIB =2108BuildMI(MBB, MBBI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL));2109for (int R = 0; R < 4; ++R) {2110PopMIB.addReg(ARM::R4 + R, RegState::Define);2111BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), ARM::R8 + R)2112.addReg(ARM::R4 + R, RegState::Kill)2113.add(predOps(ARMCC::AL));2114}2115MachineInstrBuilder PopMIB2 =2116BuildMI(MBB, MBBI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL));2117for (int R = 0; R < 4; ++R)2118PopMIB2.addReg(ARM::R4 + R, RegState::Define);2119} else { // pop Lo and Hi registers with a single instruction2120MachineInstrBuilder PopMIB =2121BuildMI(MBB, MBBI, DL, TII.get(ARM::t2LDMIA_UPD), ARM::SP)2122.addReg(ARM::SP)2123.add(predOps(ARMCC::AL));2124for (int Reg = ARM::R4; Reg < ARM::R12; ++Reg)2125PopMIB.addReg(Reg, RegState::Define);2126}2127}21282129bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,2130MachineBasicBlock::iterator MBBI,2131MachineBasicBlock::iterator &NextMBBI) {2132MachineInstr &MI = *MBBI;2133unsigned Opcode = MI.getOpcode();2134switch (Opcode) {2135default:2136return false;21372138case ARM::VBSPd:2139case ARM::VBSPq: {2140Register DstReg = MI.getOperand(0).getReg();2141if (DstReg == MI.getOperand(3).getReg()) {2142// Expand to VBIT2143unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBITd : ARM::VBITq;2144BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))2145.add(MI.getOperand(0))2146.add(MI.getOperand(3))2147.add(MI.getOperand(2))2148.add(MI.getOperand(1))2149.addImm(MI.getOperand(4).getImm())2150.add(MI.getOperand(5));2151} else if (DstReg == MI.getOperand(2).getReg()) {2152// Expand to VBIF2153unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBIFd : ARM::VBIFq;2154BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))2155.add(MI.getOperand(0))2156.add(MI.getOperand(2))2157.add(MI.getOperand(3))2158.add(MI.getOperand(1))2159.addImm(MI.getOperand(4).getImm())2160.add(MI.getOperand(5));2161} else {2162// Expand to VBSL2163unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBSLd : ARM::VBSLq;2164if (DstReg == MI.getOperand(1).getReg()) {2165BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))2166.add(MI.getOperand(0))2167.add(MI.getOperand(1))2168.add(MI.getOperand(2))2169.add(MI.getOperand(3))2170.addImm(MI.getOperand(4).getImm())2171.add(MI.getOperand(5));2172} else {2173// Use move to satisfy constraints2174unsigned MoveOpc = Opcode == ARM::VBSPd ? ARM::VORRd : ARM::VORRq;2175BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MoveOpc))2176.addReg(DstReg,2177RegState::Define |2178getRenamableRegState(MI.getOperand(0).isRenamable()))2179.add(MI.getOperand(1))2180.add(MI.getOperand(1))2181.addImm(MI.getOperand(4).getImm())2182.add(MI.getOperand(5));2183BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))2184.add(MI.getOperand(0))2185.addReg(DstReg,2186RegState::Kill |2187getRenamableRegState(MI.getOperand(0).isRenamable()))2188.add(MI.getOperand(2))2189.add(MI.getOperand(3))2190.addImm(MI.getOperand(4).getImm())2191.add(MI.getOperand(5));2192}2193}2194MI.eraseFromParent();2195return true;2196}21972198case ARM::TCRETURNdi:2199case ARM::TCRETURNri:2200case ARM::TCRETURNrinotr12: {2201MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();2202if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)2203MBBI--;2204if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)2205MBBI--;2206assert(MBBI->isReturn() &&2207"Can only insert epilog into returning blocks");2208unsigned RetOpcode = MBBI->getOpcode();2209DebugLoc dl = MBBI->getDebugLoc();2210const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>(2211MBB.getParent()->getSubtarget().getInstrInfo());22122213// Tail call return: adjust the stack pointer and jump to callee.2214MBBI = MBB.getLastNonDebugInstr();2215if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)2216MBBI--;2217if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)2218MBBI--;2219MachineOperand &JumpTarget = MBBI->getOperand(0);22202221// Jump to label or value in register.2222if (RetOpcode == ARM::TCRETURNdi) {2223MachineFunction *MF = MBB.getParent();2224bool NeedsWinCFI = MF->getTarget().getMCAsmInfo()->usesWindowsCFI() &&2225MF->getFunction().needsUnwindTableEntry();2226unsigned TCOpcode =2227STI->isThumb()2228? ((STI->isTargetMachO() || NeedsWinCFI) ? ARM::tTAILJMPd2229: ARM::tTAILJMPdND)2230: ARM::TAILJMPd;2231MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));2232if (JumpTarget.isGlobal())2233MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),2234JumpTarget.getTargetFlags());2235else {2236assert(JumpTarget.isSymbol());2237MIB.addExternalSymbol(JumpTarget.getSymbolName(),2238JumpTarget.getTargetFlags());2239}22402241// Add the default predicate in Thumb mode.2242if (STI->isThumb())2243MIB.add(predOps(ARMCC::AL));2244} else if (RetOpcode == ARM::TCRETURNri ||2245RetOpcode == ARM::TCRETURNrinotr12) {2246unsigned Opcode =2247STI->isThumb() ? ARM::tTAILJMPr2248: (STI->hasV4TOps() ? ARM::TAILJMPr : ARM::TAILJMPr4);2249BuildMI(MBB, MBBI, dl,2250TII.get(Opcode))2251.addReg(JumpTarget.getReg(), RegState::Kill);2252}22532254auto NewMI = std::prev(MBBI);2255for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i)2256NewMI->addOperand(MBBI->getOperand(i));225722582259// Update call site info and delete the pseudo instruction TCRETURN.2260if (MI.isCandidateForCallSiteEntry())2261MI.getMF()->moveCallSiteInfo(&MI, &*NewMI);2262// Copy nomerge flag over to new instruction.2263if (MI.getFlag(MachineInstr::NoMerge))2264NewMI->setFlag(MachineInstr::NoMerge);2265MBB.erase(MBBI);22662267MBBI = NewMI;2268return true;2269}2270case ARM::tBXNS_RET: {2271// For v8.0-M.Main we need to authenticate LR before clearing FPRs, which2272// uses R12 as a scratch register.2273if (!STI->hasV8_1MMainlineOps() && AFI->shouldSignReturnAddress())2274BuildMI(MBB, MBBI, DebugLoc(), TII->get(ARM::t2AUT));22752276MachineBasicBlock &AfterBB = CMSEClearFPRegs(MBB, MBBI);22772278if (STI->hasV8_1MMainlineOps()) {2279// Restore the non-secure floating point context.2280BuildMI(MBB, MBBI, MBBI->getDebugLoc(),2281TII->get(ARM::VLDR_FPCXTNS_post), ARM::SP)2282.addReg(ARM::SP)2283.addImm(4)2284.add(predOps(ARMCC::AL));22852286if (AFI->shouldSignReturnAddress())2287BuildMI(AfterBB, AfterBB.end(), DebugLoc(), TII->get(ARM::t2AUT));2288}22892290// Clear all GPR that are not a use of the return instruction.2291assert(llvm::all_of(MBBI->operands(), [](const MachineOperand &Op) {2292return !Op.isReg() || Op.getReg() != ARM::R12;2293}));2294SmallVector<unsigned, 5> ClearRegs;2295determineGPRegsToClear(2296*MBBI, {ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R12}, ClearRegs);2297CMSEClearGPRegs(AfterBB, AfterBB.end(), MBBI->getDebugLoc(), ClearRegs,2298ARM::LR);22992300MachineInstrBuilder NewMI =2301BuildMI(AfterBB, AfterBB.end(), MBBI->getDebugLoc(),2302TII->get(ARM::tBXNS))2303.addReg(ARM::LR)2304.add(predOps(ARMCC::AL));2305for (const MachineOperand &Op : MI.operands())2306NewMI->addOperand(Op);2307MI.eraseFromParent();2308return true;2309}2310case ARM::tBLXNS_CALL: {2311DebugLoc DL = MBBI->getDebugLoc();2312Register JumpReg = MBBI->getOperand(0).getReg();23132314// Figure out which registers are live at the point immediately before the2315// call. When we indiscriminately push a set of registers, the live2316// registers are added as ordinary use operands, whereas dead registers2317// are "undef".2318LivePhysRegs LiveRegs(*TRI);2319LiveRegs.addLiveOuts(MBB);2320for (const MachineInstr &MI : make_range(MBB.rbegin(), MBBI.getReverse()))2321LiveRegs.stepBackward(MI);2322LiveRegs.stepBackward(*MBBI);23232324CMSEPushCalleeSaves(*TII, MBB, MBBI, JumpReg, LiveRegs,2325AFI->isThumb1OnlyFunction());23262327SmallVector<unsigned, 16> ClearRegs;2328determineGPRegsToClear(*MBBI,2329{ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R4,2330ARM::R5, ARM::R6, ARM::R7, ARM::R8, ARM::R9,2331ARM::R10, ARM::R11, ARM::R12},2332ClearRegs);2333auto OriginalClearRegs = ClearRegs;23342335// Get the first cleared register as a scratch (to use later with tBIC).2336// We need to use the first so we can ensure it is a low register.2337unsigned ScratchReg = ClearRegs.front();23382339// Clear LSB of JumpReg2340if (AFI->isThumb2Function()) {2341BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), JumpReg)2342.addReg(JumpReg)2343.addImm(1)2344.add(predOps(ARMCC::AL))2345.add(condCodeOp());2346} else {2347// We need to use an extra register to cope with 8M Baseline,2348// since we have saved all of the registers we are ok to trash a non2349// argument register here.2350BuildMI(MBB, MBBI, DL, TII->get(ARM::tMOVi8), ScratchReg)2351.add(condCodeOp())2352.addImm(1)2353.add(predOps(ARMCC::AL));2354BuildMI(MBB, MBBI, DL, TII->get(ARM::tBIC), JumpReg)2355.addReg(ARM::CPSR, RegState::Define)2356.addReg(JumpReg)2357.addReg(ScratchReg)2358.add(predOps(ARMCC::AL));2359}23602361CMSESaveClearFPRegs(MBB, MBBI, DL, LiveRegs,2362ClearRegs); // save+clear FP regs with ClearRegs2363CMSEClearGPRegs(MBB, MBBI, DL, ClearRegs, JumpReg);23642365const MachineInstrBuilder NewCall =2366BuildMI(MBB, MBBI, DL, TII->get(ARM::tBLXNSr))2367.add(predOps(ARMCC::AL))2368.addReg(JumpReg, RegState::Kill);23692370for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))2371NewCall->addOperand(MO);2372if (MI.isCandidateForCallSiteEntry())2373MI.getMF()->moveCallSiteInfo(&MI, NewCall.getInstr());23742375CMSERestoreFPRegs(MBB, MBBI, DL, OriginalClearRegs); // restore FP registers23762377CMSEPopCalleeSaves(*TII, MBB, MBBI, JumpReg, AFI->isThumb1OnlyFunction());23782379MI.eraseFromParent();2380return true;2381}2382case ARM::VMOVHcc:2383case ARM::VMOVScc:2384case ARM::VMOVDcc: {2385unsigned newOpc = Opcode != ARM::VMOVDcc ? ARM::VMOVS : ARM::VMOVD;2386BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(newOpc),2387MI.getOperand(1).getReg())2388.add(MI.getOperand(2))2389.addImm(MI.getOperand(3).getImm()) // 'pred'2390.add(MI.getOperand(4))2391.add(makeImplicit(MI.getOperand(1)));23922393MI.eraseFromParent();2394return true;2395}2396case ARM::t2MOVCCr:2397case ARM::MOVCCr: {2398unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVr : ARM::MOVr;2399BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),2400MI.getOperand(1).getReg())2401.add(MI.getOperand(2))2402.addImm(MI.getOperand(3).getImm()) // 'pred'2403.add(MI.getOperand(4))2404.add(condCodeOp()) // 's' bit2405.add(makeImplicit(MI.getOperand(1)));24062407MI.eraseFromParent();2408return true;2409}2410case ARM::MOVCCsi: {2411BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),2412(MI.getOperand(1).getReg()))2413.add(MI.getOperand(2))2414.addImm(MI.getOperand(3).getImm())2415.addImm(MI.getOperand(4).getImm()) // 'pred'2416.add(MI.getOperand(5))2417.add(condCodeOp()) // 's' bit2418.add(makeImplicit(MI.getOperand(1)));24192420MI.eraseFromParent();2421return true;2422}2423case ARM::MOVCCsr: {2424BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsr),2425(MI.getOperand(1).getReg()))2426.add(MI.getOperand(2))2427.add(MI.getOperand(3))2428.addImm(MI.getOperand(4).getImm())2429.addImm(MI.getOperand(5).getImm()) // 'pred'2430.add(MI.getOperand(6))2431.add(condCodeOp()) // 's' bit2432.add(makeImplicit(MI.getOperand(1)));24332434MI.eraseFromParent();2435return true;2436}2437case ARM::t2MOVCCi16:2438case ARM::MOVCCi16: {2439unsigned NewOpc = AFI->isThumbFunction() ? ARM::t2MOVi16 : ARM::MOVi16;2440BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),2441MI.getOperand(1).getReg())2442.addImm(MI.getOperand(2).getImm())2443.addImm(MI.getOperand(3).getImm()) // 'pred'2444.add(MI.getOperand(4))2445.add(makeImplicit(MI.getOperand(1)));2446MI.eraseFromParent();2447return true;2448}2449case ARM::t2MOVCCi:2450case ARM::MOVCCi: {2451unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVi : ARM::MOVi;2452BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),2453MI.getOperand(1).getReg())2454.addImm(MI.getOperand(2).getImm())2455.addImm(MI.getOperand(3).getImm()) // 'pred'2456.add(MI.getOperand(4))2457.add(condCodeOp()) // 's' bit2458.add(makeImplicit(MI.getOperand(1)));24592460MI.eraseFromParent();2461return true;2462}2463case ARM::t2MVNCCi:2464case ARM::MVNCCi: {2465unsigned Opc = AFI->isThumbFunction() ? ARM::t2MVNi : ARM::MVNi;2466BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),2467MI.getOperand(1).getReg())2468.addImm(MI.getOperand(2).getImm())2469.addImm(MI.getOperand(3).getImm()) // 'pred'2470.add(MI.getOperand(4))2471.add(condCodeOp()) // 's' bit2472.add(makeImplicit(MI.getOperand(1)));24732474MI.eraseFromParent();2475return true;2476}2477case ARM::t2MOVCClsl:2478case ARM::t2MOVCClsr:2479case ARM::t2MOVCCasr:2480case ARM::t2MOVCCror: {2481unsigned NewOpc;2482switch (Opcode) {2483case ARM::t2MOVCClsl: NewOpc = ARM::t2LSLri; break;2484case ARM::t2MOVCClsr: NewOpc = ARM::t2LSRri; break;2485case ARM::t2MOVCCasr: NewOpc = ARM::t2ASRri; break;2486case ARM::t2MOVCCror: NewOpc = ARM::t2RORri; break;2487default: llvm_unreachable("unexpeced conditional move");2488}2489BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),2490MI.getOperand(1).getReg())2491.add(MI.getOperand(2))2492.addImm(MI.getOperand(3).getImm())2493.addImm(MI.getOperand(4).getImm()) // 'pred'2494.add(MI.getOperand(5))2495.add(condCodeOp()) // 's' bit2496.add(makeImplicit(MI.getOperand(1)));2497MI.eraseFromParent();2498return true;2499}2500case ARM::Int_eh_sjlj_dispatchsetup: {2501MachineFunction &MF = *MI.getParent()->getParent();2502const ARMBaseInstrInfo *AII =2503static_cast<const ARMBaseInstrInfo*>(TII);2504const ARMBaseRegisterInfo &RI = AII->getRegisterInfo();2505// For functions using a base pointer, we rematerialize it (via the frame2506// pointer) here since eh.sjlj.setjmp and eh.sjlj.longjmp don't do it2507// for us. Otherwise, expand to nothing.2508if (RI.hasBasePointer(MF)) {2509int32_t NumBytes = AFI->getFramePtrSpillOffset();2510Register FramePtr = RI.getFrameRegister(MF);2511assert(MF.getSubtarget().getFrameLowering()->hasFP(MF) &&2512"base pointer without frame pointer?");25132514if (AFI->isThumb2Function()) {2515emitT2RegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,2516FramePtr, -NumBytes, ARMCC::AL, 0, *TII);2517} else if (AFI->isThumbFunction()) {2518emitThumbRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,2519FramePtr, -NumBytes, *TII, RI);2520} else {2521emitARMRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,2522FramePtr, -NumBytes, ARMCC::AL, 0,2523*TII);2524}2525// If there's dynamic realignment, adjust for it.2526if (RI.hasStackRealignment(MF)) {2527MachineFrameInfo &MFI = MF.getFrameInfo();2528Align MaxAlign = MFI.getMaxAlign();2529assert (!AFI->isThumb1OnlyFunction());2530// Emit bic r6, r6, MaxAlign2531assert(MaxAlign <= Align(256) &&2532"The BIC instruction cannot encode "2533"immediates larger than 256 with all lower "2534"bits set.");2535unsigned bicOpc = AFI->isThumbFunction() ?2536ARM::t2BICri : ARM::BICri;2537BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(bicOpc), ARM::R6)2538.addReg(ARM::R6, RegState::Kill)2539.addImm(MaxAlign.value() - 1)2540.add(predOps(ARMCC::AL))2541.add(condCodeOp());2542}2543}2544MI.eraseFromParent();2545return true;2546}25472548case ARM::MOVsrl_glue:2549case ARM::MOVsra_glue: {2550// These are just fancy MOVs instructions.2551BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),2552MI.getOperand(0).getReg())2553.add(MI.getOperand(1))2554.addImm(ARM_AM::getSORegOpc(2555(Opcode == ARM::MOVsrl_glue ? ARM_AM::lsr : ARM_AM::asr), 1))2556.add(predOps(ARMCC::AL))2557.addReg(ARM::CPSR, RegState::Define);2558MI.eraseFromParent();2559return true;2560}2561case ARM::RRX: {2562// This encodes as "MOVs Rd, Rm, rrx2563BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),2564MI.getOperand(0).getReg())2565.add(MI.getOperand(1))2566.addImm(ARM_AM::getSORegOpc(ARM_AM::rrx, 0))2567.add(predOps(ARMCC::AL))2568.add(condCodeOp())2569.copyImplicitOps(MI);2570MI.eraseFromParent();2571return true;2572}2573case ARM::tTPsoft:2574case ARM::TPsoft: {2575const bool Thumb = Opcode == ARM::tTPsoft;25762577MachineInstrBuilder MIB;2578MachineFunction *MF = MBB.getParent();2579if (STI->genLongCalls()) {2580MachineConstantPool *MCP = MF->getConstantPool();2581unsigned PCLabelID = AFI->createPICLabelUId();2582MachineConstantPoolValue *CPV =2583ARMConstantPoolSymbol::Create(MF->getFunction().getContext(),2584"__aeabi_read_tp", PCLabelID, 0);2585Register Reg = MI.getOperand(0).getReg();2586MIB =2587BuildMI(MBB, MBBI, MI.getDebugLoc(),2588TII->get(Thumb ? ARM::tLDRpci : ARM::LDRi12), Reg)2589.addConstantPoolIndex(MCP->getConstantPoolIndex(CPV, Align(4)));2590if (!Thumb)2591MIB.addImm(0);2592MIB.add(predOps(ARMCC::AL));25932594MIB =2595BuildMI(MBB, MBBI, MI.getDebugLoc(),2596TII->get(Thumb ? gettBLXrOpcode(*MF) : getBLXOpcode(*MF)));2597if (Thumb)2598MIB.add(predOps(ARMCC::AL));2599MIB.addReg(Reg, RegState::Kill);2600} else {2601MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),2602TII->get(Thumb ? ARM::tBL : ARM::BL));2603if (Thumb)2604MIB.add(predOps(ARMCC::AL));2605MIB.addExternalSymbol("__aeabi_read_tp", 0);2606}26072608MIB.cloneMemRefs(MI);2609MIB.copyImplicitOps(MI);2610// Update the call site info.2611if (MI.isCandidateForCallSiteEntry())2612MF->moveCallSiteInfo(&MI, &*MIB);2613MI.eraseFromParent();2614return true;2615}2616case ARM::tLDRpci_pic:2617case ARM::t2LDRpci_pic: {2618unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)2619? ARM::tLDRpci : ARM::t2LDRpci;2620Register DstReg = MI.getOperand(0).getReg();2621bool DstIsDead = MI.getOperand(0).isDead();2622BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewLdOpc), DstReg)2623.add(MI.getOperand(1))2624.add(predOps(ARMCC::AL))2625.cloneMemRefs(MI)2626.copyImplicitOps(MI);2627BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPICADD))2628.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2629.addReg(DstReg)2630.add(MI.getOperand(2))2631.copyImplicitOps(MI);2632MI.eraseFromParent();2633return true;2634}26352636case ARM::LDRLIT_ga_abs:2637case ARM::LDRLIT_ga_pcrel:2638case ARM::LDRLIT_ga_pcrel_ldr:2639case ARM::tLDRLIT_ga_abs:2640case ARM::t2LDRLIT_ga_pcrel:2641case ARM::tLDRLIT_ga_pcrel: {2642Register DstReg = MI.getOperand(0).getReg();2643bool DstIsDead = MI.getOperand(0).isDead();2644const MachineOperand &MO1 = MI.getOperand(1);2645auto Flags = MO1.getTargetFlags();2646const GlobalValue *GV = MO1.getGlobal();2647bool IsARM = Opcode != ARM::tLDRLIT_ga_pcrel &&2648Opcode != ARM::tLDRLIT_ga_abs &&2649Opcode != ARM::t2LDRLIT_ga_pcrel;2650bool IsPIC =2651Opcode != ARM::LDRLIT_ga_abs && Opcode != ARM::tLDRLIT_ga_abs;2652unsigned LDRLITOpc = IsARM ? ARM::LDRi12 : ARM::tLDRpci;2653if (Opcode == ARM::t2LDRLIT_ga_pcrel)2654LDRLITOpc = ARM::t2LDRpci;2655unsigned PICAddOpc =2656IsARM2657? (Opcode == ARM::LDRLIT_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)2658: ARM::tPICADD;26592660// We need a new const-pool entry to load from.2661MachineConstantPool *MCP = MBB.getParent()->getConstantPool();2662unsigned ARMPCLabelIndex = 0;2663MachineConstantPoolValue *CPV;26642665if (IsPIC) {2666unsigned PCAdj = IsARM ? 8 : 4;2667auto Modifier = (Flags & ARMII::MO_GOT)2668? ARMCP::GOT_PREL2669: ARMCP::no_modifier;2670ARMPCLabelIndex = AFI->createPICLabelUId();2671CPV = ARMConstantPoolConstant::Create(2672GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj, Modifier,2673/*AddCurrentAddr*/ Modifier == ARMCP::GOT_PREL);2674} else2675CPV = ARMConstantPoolConstant::Create(GV, ARMCP::no_modifier);26762677MachineInstrBuilder MIB =2678BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LDRLITOpc), DstReg)2679.addConstantPoolIndex(MCP->getConstantPoolIndex(CPV, Align(4)));2680if (IsARM)2681MIB.addImm(0);2682MIB.add(predOps(ARMCC::AL));26832684if (IsPIC) {2685MachineInstrBuilder MIB =2686BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(PICAddOpc))2687.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2688.addReg(DstReg)2689.addImm(ARMPCLabelIndex);26902691if (IsARM)2692MIB.add(predOps(ARMCC::AL));2693}26942695MI.eraseFromParent();2696return true;2697}2698case ARM::MOV_ga_pcrel:2699case ARM::MOV_ga_pcrel_ldr:2700case ARM::t2MOV_ga_pcrel: {2701// Expand into movw + movw. Also "add pc" / ldr [pc] in PIC mode.2702unsigned LabelId = AFI->createPICLabelUId();2703Register DstReg = MI.getOperand(0).getReg();2704bool DstIsDead = MI.getOperand(0).isDead();2705const MachineOperand &MO1 = MI.getOperand(1);2706const GlobalValue *GV = MO1.getGlobal();2707unsigned TF = MO1.getTargetFlags();2708bool isARM = Opcode != ARM::t2MOV_ga_pcrel;2709unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel;2710unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel :ARM::t2MOVTi16_ga_pcrel;2711unsigned LO16TF = TF | ARMII::MO_LO16;2712unsigned HI16TF = TF | ARMII::MO_HI16;2713unsigned PICAddOpc = isARM2714? (Opcode == ARM::MOV_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)2715: ARM::tPICADD;2716BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg)2717.addGlobalAddress(GV, MO1.getOffset(), TF | LO16TF)2718.addImm(LabelId)2719.copyImplicitOps(MI);27202721BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc), DstReg)2722.addReg(DstReg)2723.addGlobalAddress(GV, MO1.getOffset(), TF | HI16TF)2724.addImm(LabelId)2725.copyImplicitOps(MI);27262727MachineInstrBuilder MIB3 = BuildMI(MBB, MBBI, MI.getDebugLoc(),2728TII->get(PICAddOpc))2729.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2730.addReg(DstReg).addImm(LabelId);2731if (isARM) {2732MIB3.add(predOps(ARMCC::AL));2733if (Opcode == ARM::MOV_ga_pcrel_ldr)2734MIB3.cloneMemRefs(MI);2735}2736MIB3.copyImplicitOps(MI);2737MI.eraseFromParent();2738return true;2739}27402741case ARM::MOVi32imm:2742case ARM::MOVCCi32imm:2743case ARM::t2MOVi32imm:2744case ARM::t2MOVCCi32imm:2745ExpandMOV32BitImm(MBB, MBBI);2746return true;27472748case ARM::tMOVi32imm:2749ExpandTMOV32BitImm(MBB, MBBI);2750return true;27512752case ARM::tLEApcrelJT:2753// Inline jump tables are handled in ARMAsmPrinter.2754if (MI.getMF()->getJumpTableInfo()->getEntryKind() ==2755MachineJumpTableInfo::EK_Inline)2756return false;27572758// Use a 32-bit immediate move to generate the address of the jump table.2759assert(STI->isThumb() && "Non-inline jump tables expected only in thumb");2760ExpandTMOV32BitImm(MBB, MBBI);2761return true;27622763case ARM::SUBS_PC_LR: {2764BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri), ARM::PC)2765.addReg(ARM::LR)2766.add(MI.getOperand(0))2767.add(MI.getOperand(1))2768.add(MI.getOperand(2))2769.addReg(ARM::CPSR, RegState::Undef)2770.copyImplicitOps(MI);2771MI.eraseFromParent();2772return true;2773}2774case ARM::VLDMQIA: {2775unsigned NewOpc = ARM::VLDMDIA;2776MachineInstrBuilder MIB =2777BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));2778unsigned OpIdx = 0;27792780// Grab the Q register destination.2781bool DstIsDead = MI.getOperand(OpIdx).isDead();2782Register DstReg = MI.getOperand(OpIdx++).getReg();27832784// Copy the source register.2785MIB.add(MI.getOperand(OpIdx++));27862787// Copy the predicate operands.2788MIB.add(MI.getOperand(OpIdx++));2789MIB.add(MI.getOperand(OpIdx++));27902791// Add the destination operands (D subregs).2792Register D0 = TRI->getSubReg(DstReg, ARM::dsub_0);2793Register D1 = TRI->getSubReg(DstReg, ARM::dsub_1);2794MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead))2795.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));27962797// Add an implicit def for the super-register.2798MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));2799MIB.copyImplicitOps(MI);2800MIB.cloneMemRefs(MI);2801MI.eraseFromParent();2802return true;2803}28042805case ARM::VSTMQIA: {2806unsigned NewOpc = ARM::VSTMDIA;2807MachineInstrBuilder MIB =2808BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));2809unsigned OpIdx = 0;28102811// Grab the Q register source.2812bool SrcIsKill = MI.getOperand(OpIdx).isKill();2813Register SrcReg = MI.getOperand(OpIdx++).getReg();28142815// Copy the destination register.2816MachineOperand Dst(MI.getOperand(OpIdx++));2817MIB.add(Dst);28182819// Copy the predicate operands.2820MIB.add(MI.getOperand(OpIdx++));2821MIB.add(MI.getOperand(OpIdx++));28222823// Add the source operands (D subregs).2824Register D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);2825Register D1 = TRI->getSubReg(SrcReg, ARM::dsub_1);2826MIB.addReg(D0, SrcIsKill ? RegState::Kill : 0)2827.addReg(D1, SrcIsKill ? RegState::Kill : 0);28282829if (SrcIsKill) // Add an implicit kill for the Q register.2830MIB->addRegisterKilled(SrcReg, TRI, true);28312832MIB.copyImplicitOps(MI);2833MIB.cloneMemRefs(MI);2834MI.eraseFromParent();2835return true;2836}28372838case ARM::VLD2q8Pseudo:2839case ARM::VLD2q16Pseudo:2840case ARM::VLD2q32Pseudo:2841case ARM::VLD2q8PseudoWB_fixed:2842case ARM::VLD2q16PseudoWB_fixed:2843case ARM::VLD2q32PseudoWB_fixed:2844case ARM::VLD2q8PseudoWB_register:2845case ARM::VLD2q16PseudoWB_register:2846case ARM::VLD2q32PseudoWB_register:2847case ARM::VLD3d8Pseudo:2848case ARM::VLD3d16Pseudo:2849case ARM::VLD3d32Pseudo:2850case ARM::VLD1d8TPseudo:2851case ARM::VLD1d8TPseudoWB_fixed:2852case ARM::VLD1d8TPseudoWB_register:2853case ARM::VLD1d16TPseudo:2854case ARM::VLD1d16TPseudoWB_fixed:2855case ARM::VLD1d16TPseudoWB_register:2856case ARM::VLD1d32TPseudo:2857case ARM::VLD1d32TPseudoWB_fixed:2858case ARM::VLD1d32TPseudoWB_register:2859case ARM::VLD1d64TPseudo:2860case ARM::VLD1d64TPseudoWB_fixed:2861case ARM::VLD1d64TPseudoWB_register:2862case ARM::VLD3d8Pseudo_UPD:2863case ARM::VLD3d16Pseudo_UPD:2864case ARM::VLD3d32Pseudo_UPD:2865case ARM::VLD3q8Pseudo_UPD:2866case ARM::VLD3q16Pseudo_UPD:2867case ARM::VLD3q32Pseudo_UPD:2868case ARM::VLD3q8oddPseudo:2869case ARM::VLD3q16oddPseudo:2870case ARM::VLD3q32oddPseudo:2871case ARM::VLD3q8oddPseudo_UPD:2872case ARM::VLD3q16oddPseudo_UPD:2873case ARM::VLD3q32oddPseudo_UPD:2874case ARM::VLD4d8Pseudo:2875case ARM::VLD4d16Pseudo:2876case ARM::VLD4d32Pseudo:2877case ARM::VLD1d8QPseudo:2878case ARM::VLD1d8QPseudoWB_fixed:2879case ARM::VLD1d8QPseudoWB_register:2880case ARM::VLD1d16QPseudo:2881case ARM::VLD1d16QPseudoWB_fixed:2882case ARM::VLD1d16QPseudoWB_register:2883case ARM::VLD1d32QPseudo:2884case ARM::VLD1d32QPseudoWB_fixed:2885case ARM::VLD1d32QPseudoWB_register:2886case ARM::VLD1d64QPseudo:2887case ARM::VLD1d64QPseudoWB_fixed:2888case ARM::VLD1d64QPseudoWB_register:2889case ARM::VLD1q8HighQPseudo:2890case ARM::VLD1q8HighQPseudo_UPD:2891case ARM::VLD1q8LowQPseudo_UPD:2892case ARM::VLD1q8HighTPseudo:2893case ARM::VLD1q8HighTPseudo_UPD:2894case ARM::VLD1q8LowTPseudo_UPD:2895case ARM::VLD1q16HighQPseudo:2896case ARM::VLD1q16HighQPseudo_UPD:2897case ARM::VLD1q16LowQPseudo_UPD:2898case ARM::VLD1q16HighTPseudo:2899case ARM::VLD1q16HighTPseudo_UPD:2900case ARM::VLD1q16LowTPseudo_UPD:2901case ARM::VLD1q32HighQPseudo:2902case ARM::VLD1q32HighQPseudo_UPD:2903case ARM::VLD1q32LowQPseudo_UPD:2904case ARM::VLD1q32HighTPseudo:2905case ARM::VLD1q32HighTPseudo_UPD:2906case ARM::VLD1q32LowTPseudo_UPD:2907case ARM::VLD1q64HighQPseudo:2908case ARM::VLD1q64HighQPseudo_UPD:2909case ARM::VLD1q64LowQPseudo_UPD:2910case ARM::VLD1q64HighTPseudo:2911case ARM::VLD1q64HighTPseudo_UPD:2912case ARM::VLD1q64LowTPseudo_UPD:2913case ARM::VLD4d8Pseudo_UPD:2914case ARM::VLD4d16Pseudo_UPD:2915case ARM::VLD4d32Pseudo_UPD:2916case ARM::VLD4q8Pseudo_UPD:2917case ARM::VLD4q16Pseudo_UPD:2918case ARM::VLD4q32Pseudo_UPD:2919case ARM::VLD4q8oddPseudo:2920case ARM::VLD4q16oddPseudo:2921case ARM::VLD4q32oddPseudo:2922case ARM::VLD4q8oddPseudo_UPD:2923case ARM::VLD4q16oddPseudo_UPD:2924case ARM::VLD4q32oddPseudo_UPD:2925case ARM::VLD3DUPd8Pseudo:2926case ARM::VLD3DUPd16Pseudo:2927case ARM::VLD3DUPd32Pseudo:2928case ARM::VLD3DUPd8Pseudo_UPD:2929case ARM::VLD3DUPd16Pseudo_UPD:2930case ARM::VLD3DUPd32Pseudo_UPD:2931case ARM::VLD4DUPd8Pseudo:2932case ARM::VLD4DUPd16Pseudo:2933case ARM::VLD4DUPd32Pseudo:2934case ARM::VLD4DUPd8Pseudo_UPD:2935case ARM::VLD4DUPd16Pseudo_UPD:2936case ARM::VLD4DUPd32Pseudo_UPD:2937case ARM::VLD2DUPq8EvenPseudo:2938case ARM::VLD2DUPq8OddPseudo:2939case ARM::VLD2DUPq16EvenPseudo:2940case ARM::VLD2DUPq16OddPseudo:2941case ARM::VLD2DUPq32EvenPseudo:2942case ARM::VLD2DUPq32OddPseudo:2943case ARM::VLD2DUPq8OddPseudoWB_fixed:2944case ARM::VLD2DUPq8OddPseudoWB_register:2945case ARM::VLD2DUPq16OddPseudoWB_fixed:2946case ARM::VLD2DUPq16OddPseudoWB_register:2947case ARM::VLD2DUPq32OddPseudoWB_fixed:2948case ARM::VLD2DUPq32OddPseudoWB_register:2949case ARM::VLD3DUPq8EvenPseudo:2950case ARM::VLD3DUPq8OddPseudo:2951case ARM::VLD3DUPq16EvenPseudo:2952case ARM::VLD3DUPq16OddPseudo:2953case ARM::VLD3DUPq32EvenPseudo:2954case ARM::VLD3DUPq32OddPseudo:2955case ARM::VLD3DUPq8OddPseudo_UPD:2956case ARM::VLD3DUPq16OddPseudo_UPD:2957case ARM::VLD3DUPq32OddPseudo_UPD:2958case ARM::VLD4DUPq8EvenPseudo:2959case ARM::VLD4DUPq8OddPseudo:2960case ARM::VLD4DUPq16EvenPseudo:2961case ARM::VLD4DUPq16OddPseudo:2962case ARM::VLD4DUPq32EvenPseudo:2963case ARM::VLD4DUPq32OddPseudo:2964case ARM::VLD4DUPq8OddPseudo_UPD:2965case ARM::VLD4DUPq16OddPseudo_UPD:2966case ARM::VLD4DUPq32OddPseudo_UPD:2967ExpandVLD(MBBI);2968return true;29692970case ARM::VST2q8Pseudo:2971case ARM::VST2q16Pseudo:2972case ARM::VST2q32Pseudo:2973case ARM::VST2q8PseudoWB_fixed:2974case ARM::VST2q16PseudoWB_fixed:2975case ARM::VST2q32PseudoWB_fixed:2976case ARM::VST2q8PseudoWB_register:2977case ARM::VST2q16PseudoWB_register:2978case ARM::VST2q32PseudoWB_register:2979case ARM::VST3d8Pseudo:2980case ARM::VST3d16Pseudo:2981case ARM::VST3d32Pseudo:2982case ARM::VST1d8TPseudo:2983case ARM::VST1d8TPseudoWB_fixed:2984case ARM::VST1d8TPseudoWB_register:2985case ARM::VST1d16TPseudo:2986case ARM::VST1d16TPseudoWB_fixed:2987case ARM::VST1d16TPseudoWB_register:2988case ARM::VST1d32TPseudo:2989case ARM::VST1d32TPseudoWB_fixed:2990case ARM::VST1d32TPseudoWB_register:2991case ARM::VST1d64TPseudo:2992case ARM::VST1d64TPseudoWB_fixed:2993case ARM::VST1d64TPseudoWB_register:2994case ARM::VST3d8Pseudo_UPD:2995case ARM::VST3d16Pseudo_UPD:2996case ARM::VST3d32Pseudo_UPD:2997case ARM::VST3q8Pseudo_UPD:2998case ARM::VST3q16Pseudo_UPD:2999case ARM::VST3q32Pseudo_UPD:3000case ARM::VST3q8oddPseudo:3001case ARM::VST3q16oddPseudo:3002case ARM::VST3q32oddPseudo:3003case ARM::VST3q8oddPseudo_UPD:3004case ARM::VST3q16oddPseudo_UPD:3005case ARM::VST3q32oddPseudo_UPD:3006case ARM::VST4d8Pseudo:3007case ARM::VST4d16Pseudo:3008case ARM::VST4d32Pseudo:3009case ARM::VST1d8QPseudo:3010case ARM::VST1d8QPseudoWB_fixed:3011case ARM::VST1d8QPseudoWB_register:3012case ARM::VST1d16QPseudo:3013case ARM::VST1d16QPseudoWB_fixed:3014case ARM::VST1d16QPseudoWB_register:3015case ARM::VST1d32QPseudo:3016case ARM::VST1d32QPseudoWB_fixed:3017case ARM::VST1d32QPseudoWB_register:3018case ARM::VST1d64QPseudo:3019case ARM::VST1d64QPseudoWB_fixed:3020case ARM::VST1d64QPseudoWB_register:3021case ARM::VST4d8Pseudo_UPD:3022case ARM::VST4d16Pseudo_UPD:3023case ARM::VST4d32Pseudo_UPD:3024case ARM::VST1q8HighQPseudo:3025case ARM::VST1q8LowQPseudo_UPD:3026case ARM::VST1q8HighTPseudo:3027case ARM::VST1q8LowTPseudo_UPD:3028case ARM::VST1q16HighQPseudo:3029case ARM::VST1q16LowQPseudo_UPD:3030case ARM::VST1q16HighTPseudo:3031case ARM::VST1q16LowTPseudo_UPD:3032case ARM::VST1q32HighQPseudo:3033case ARM::VST1q32LowQPseudo_UPD:3034case ARM::VST1q32HighTPseudo:3035case ARM::VST1q32LowTPseudo_UPD:3036case ARM::VST1q64HighQPseudo:3037case ARM::VST1q64LowQPseudo_UPD:3038case ARM::VST1q64HighTPseudo:3039case ARM::VST1q64LowTPseudo_UPD:3040case ARM::VST1q8HighTPseudo_UPD:3041case ARM::VST1q16HighTPseudo_UPD:3042case ARM::VST1q32HighTPseudo_UPD:3043case ARM::VST1q64HighTPseudo_UPD:3044case ARM::VST1q8HighQPseudo_UPD:3045case ARM::VST1q16HighQPseudo_UPD:3046case ARM::VST1q32HighQPseudo_UPD:3047case ARM::VST1q64HighQPseudo_UPD:3048case ARM::VST4q8Pseudo_UPD:3049case ARM::VST4q16Pseudo_UPD:3050case ARM::VST4q32Pseudo_UPD:3051case ARM::VST4q8oddPseudo:3052case ARM::VST4q16oddPseudo:3053case ARM::VST4q32oddPseudo:3054case ARM::VST4q8oddPseudo_UPD:3055case ARM::VST4q16oddPseudo_UPD:3056case ARM::VST4q32oddPseudo_UPD:3057ExpandVST(MBBI);3058return true;30593060case ARM::VLD1LNq8Pseudo:3061case ARM::VLD1LNq16Pseudo:3062case ARM::VLD1LNq32Pseudo:3063case ARM::VLD1LNq8Pseudo_UPD:3064case ARM::VLD1LNq16Pseudo_UPD:3065case ARM::VLD1LNq32Pseudo_UPD:3066case ARM::VLD2LNd8Pseudo:3067case ARM::VLD2LNd16Pseudo:3068case ARM::VLD2LNd32Pseudo:3069case ARM::VLD2LNq16Pseudo:3070case ARM::VLD2LNq32Pseudo:3071case ARM::VLD2LNd8Pseudo_UPD:3072case ARM::VLD2LNd16Pseudo_UPD:3073case ARM::VLD2LNd32Pseudo_UPD:3074case ARM::VLD2LNq16Pseudo_UPD:3075case ARM::VLD2LNq32Pseudo_UPD:3076case ARM::VLD3LNd8Pseudo:3077case ARM::VLD3LNd16Pseudo:3078case ARM::VLD3LNd32Pseudo:3079case ARM::VLD3LNq16Pseudo:3080case ARM::VLD3LNq32Pseudo:3081case ARM::VLD3LNd8Pseudo_UPD:3082case ARM::VLD3LNd16Pseudo_UPD:3083case ARM::VLD3LNd32Pseudo_UPD:3084case ARM::VLD3LNq16Pseudo_UPD:3085case ARM::VLD3LNq32Pseudo_UPD:3086case ARM::VLD4LNd8Pseudo:3087case ARM::VLD4LNd16Pseudo:3088case ARM::VLD4LNd32Pseudo:3089case ARM::VLD4LNq16Pseudo:3090case ARM::VLD4LNq32Pseudo:3091case ARM::VLD4LNd8Pseudo_UPD:3092case ARM::VLD4LNd16Pseudo_UPD:3093case ARM::VLD4LNd32Pseudo_UPD:3094case ARM::VLD4LNq16Pseudo_UPD:3095case ARM::VLD4LNq32Pseudo_UPD:3096case ARM::VST1LNq8Pseudo:3097case ARM::VST1LNq16Pseudo:3098case ARM::VST1LNq32Pseudo:3099case ARM::VST1LNq8Pseudo_UPD:3100case ARM::VST1LNq16Pseudo_UPD:3101case ARM::VST1LNq32Pseudo_UPD:3102case ARM::VST2LNd8Pseudo:3103case ARM::VST2LNd16Pseudo:3104case ARM::VST2LNd32Pseudo:3105case ARM::VST2LNq16Pseudo:3106case ARM::VST2LNq32Pseudo:3107case ARM::VST2LNd8Pseudo_UPD:3108case ARM::VST2LNd16Pseudo_UPD:3109case ARM::VST2LNd32Pseudo_UPD:3110case ARM::VST2LNq16Pseudo_UPD:3111case ARM::VST2LNq32Pseudo_UPD:3112case ARM::VST3LNd8Pseudo:3113case ARM::VST3LNd16Pseudo:3114case ARM::VST3LNd32Pseudo:3115case ARM::VST3LNq16Pseudo:3116case ARM::VST3LNq32Pseudo:3117case ARM::VST3LNd8Pseudo_UPD:3118case ARM::VST3LNd16Pseudo_UPD:3119case ARM::VST3LNd32Pseudo_UPD:3120case ARM::VST3LNq16Pseudo_UPD:3121case ARM::VST3LNq32Pseudo_UPD:3122case ARM::VST4LNd8Pseudo:3123case ARM::VST4LNd16Pseudo:3124case ARM::VST4LNd32Pseudo:3125case ARM::VST4LNq16Pseudo:3126case ARM::VST4LNq32Pseudo:3127case ARM::VST4LNd8Pseudo_UPD:3128case ARM::VST4LNd16Pseudo_UPD:3129case ARM::VST4LNd32Pseudo_UPD:3130case ARM::VST4LNq16Pseudo_UPD:3131case ARM::VST4LNq32Pseudo_UPD:3132ExpandLaneOp(MBBI);3133return true;31343135case ARM::VTBL3Pseudo: ExpandVTBL(MBBI, ARM::VTBL3, false); return true;3136case ARM::VTBL4Pseudo: ExpandVTBL(MBBI, ARM::VTBL4, false); return true;3137case ARM::VTBX3Pseudo: ExpandVTBL(MBBI, ARM::VTBX3, true); return true;3138case ARM::VTBX4Pseudo: ExpandVTBL(MBBI, ARM::VTBX4, true); return true;31393140case ARM::MQQPRLoad:3141case ARM::MQQPRStore:3142case ARM::MQQQQPRLoad:3143case ARM::MQQQQPRStore:3144ExpandMQQPRLoadStore(MBBI);3145return true;31463147case ARM::tCMP_SWAP_8:3148assert(STI->isThumb());3149return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXB, ARM::t2STREXB, ARM::tUXTB,3150NextMBBI);3151case ARM::tCMP_SWAP_16:3152assert(STI->isThumb());3153return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXH, ARM::t2STREXH, ARM::tUXTH,3154NextMBBI);3155case ARM::tCMP_SWAP_32:3156assert(STI->isThumb());3157return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREX, ARM::t2STREX, 0, NextMBBI);31583159case ARM::CMP_SWAP_8:3160assert(!STI->isThumb());3161return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXB, ARM::STREXB, ARM::UXTB,3162NextMBBI);3163case ARM::CMP_SWAP_16:3164assert(!STI->isThumb());3165return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXH, ARM::STREXH, ARM::UXTH,3166NextMBBI);3167case ARM::CMP_SWAP_32:3168assert(!STI->isThumb());3169return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREX, ARM::STREX, 0, NextMBBI);31703171case ARM::CMP_SWAP_64:3172return ExpandCMP_SWAP_64(MBB, MBBI, NextMBBI);31733174case ARM::tBL_PUSHLR:3175case ARM::BL_PUSHLR: {3176const bool Thumb = Opcode == ARM::tBL_PUSHLR;3177Register Reg = MI.getOperand(0).getReg();3178assert(Reg == ARM::LR && "expect LR register!");3179MachineInstrBuilder MIB;3180if (Thumb) {3181// push {lr}3182BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPUSH))3183.add(predOps(ARMCC::AL))3184.addReg(Reg);31853186// bl __gnu_mcount_nc3187MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tBL));3188} else {3189// stmdb sp!, {lr}3190BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::STMDB_UPD))3191.addReg(ARM::SP, RegState::Define)3192.addReg(ARM::SP)3193.add(predOps(ARMCC::AL))3194.addReg(Reg);31953196// bl __gnu_mcount_nc3197MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::BL));3198}3199MIB.cloneMemRefs(MI);3200for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))3201MIB.add(MO);3202MI.eraseFromParent();3203return true;3204}3205case ARM::t2CALL_BTI: {3206MachineFunction &MF = *MI.getMF();3207MachineInstrBuilder MIB =3208BuildMI(MF, MI.getDebugLoc(), TII->get(ARM::tBL));3209MIB.cloneMemRefs(MI);3210for (unsigned i = 0; i < MI.getNumOperands(); ++i)3211MIB.add(MI.getOperand(i));3212if (MI.isCandidateForCallSiteEntry())3213MF.moveCallSiteInfo(&MI, MIB.getInstr());3214MIBundleBuilder Bundler(MBB, MI);3215Bundler.append(MIB);3216Bundler.append(BuildMI(MF, MI.getDebugLoc(), TII->get(ARM::t2BTI)));3217finalizeBundle(MBB, Bundler.begin(), Bundler.end());3218MI.eraseFromParent();3219return true;3220}3221case ARM::LOADDUAL:3222case ARM::STOREDUAL: {3223Register PairReg = MI.getOperand(0).getReg();32243225MachineInstrBuilder MIB =3226BuildMI(MBB, MBBI, MI.getDebugLoc(),3227TII->get(Opcode == ARM::LOADDUAL ? ARM::LDRD : ARM::STRD))3228.addReg(TRI->getSubReg(PairReg, ARM::gsub_0),3229Opcode == ARM::LOADDUAL ? RegState::Define : 0)3230.addReg(TRI->getSubReg(PairReg, ARM::gsub_1),3231Opcode == ARM::LOADDUAL ? RegState::Define : 0);3232for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))3233MIB.add(MO);3234MIB.add(predOps(ARMCC::AL));3235MIB.cloneMemRefs(MI);3236MI.eraseFromParent();3237return true;3238}3239}3240}32413242bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {3243bool Modified = false;32443245MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();3246while (MBBI != E) {3247MachineBasicBlock::iterator NMBBI = std::next(MBBI);3248Modified |= ExpandMI(MBB, MBBI, NMBBI);3249MBBI = NMBBI;3250}32513252return Modified;3253}32543255bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {3256STI = &MF.getSubtarget<ARMSubtarget>();3257TII = STI->getInstrInfo();3258TRI = STI->getRegisterInfo();3259AFI = MF.getInfo<ARMFunctionInfo>();32603261LLVM_DEBUG(dbgs() << "********** ARM EXPAND PSEUDO INSTRUCTIONS **********\n"3262<< "********** Function: " << MF.getName() << '\n');32633264bool Modified = false;3265for (MachineBasicBlock &MBB : MF)3266Modified |= ExpandMBB(MBB);3267if (VerifyARMPseudo)3268MF.verify(this, "After expanding ARM pseudo instructions.");32693270LLVM_DEBUG(dbgs() << "***************************************************\n");3271return Modified;3272}32733274/// createARMExpandPseudoPass - returns an instance of the pseudo instruction3275/// expansion pass.3276FunctionPass *llvm::createARMExpandPseudoPass() {3277return new ARMExpandPseudo();3278}327932803281