ARMISelDAGToDAG.cpp revision 280031
1193323Sed//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines an instruction selector for the ARM target. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "ARM.h" 15218893Sdim#include "ARMBaseInstrInfo.h" 16193323Sed#include "ARMTargetMachine.h" 17226633Sdim#include "MCTargetDesc/ARMAddressingModes.h" 18193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 19193323Sed#include "llvm/CodeGen/MachineFunction.h" 20193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 21249423Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 22193323Sed#include "llvm/CodeGen/SelectionDAG.h" 23193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 24249423Sdim#include "llvm/IR/CallingConv.h" 25249423Sdim#include "llvm/IR/Constants.h" 26249423Sdim#include "llvm/IR/DerivedTypes.h" 27249423Sdim#include "llvm/IR/Function.h" 28249423Sdim#include "llvm/IR/Intrinsics.h" 29249423Sdim#include "llvm/IR/LLVMContext.h" 30207631Srdivacky#include "llvm/Support/CommandLine.h" 31193323Sed#include "llvm/Support/Compiler.h" 32193323Sed#include "llvm/Support/Debug.h" 33198090Srdivacky#include "llvm/Support/ErrorHandling.h" 34249423Sdim#include "llvm/Target/TargetLowering.h" 35249423Sdim#include "llvm/Target/TargetOptions.h" 36198090Srdivacky 37193323Sedusing namespace llvm; 38193323Sed 39276479Sdim#define DEBUG_TYPE "arm-isel" 40276479Sdim 41212904Sdimstatic cl::opt<bool> 42212904SdimDisableShifterOp("disable-shifter-op", cl::Hidden, 43212904Sdim cl::desc("Disable isel of shifter-op"), 44212904Sdim cl::init(false)); 45212904Sdim 46218893Sdimstatic cl::opt<bool> 47218893SdimCheckVMLxHazard("check-vmlx-hazard", cl::Hidden, 48218893Sdim cl::desc("Check fp vmla / vmls hazard at isel time"), 49221345Sdim cl::init(true)); 50218893Sdim 51193323Sed//===--------------------------------------------------------------------===// 52193323Sed/// ARMDAGToDAGISel - ARM specific code to select ARM machine 53193323Sed/// instructions for SelectionDAG operations. 54193323Sed/// 55193323Sednamespace { 56218893Sdim 57218893Sdimenum AddrMode2Type { 58218893Sdim AM2_BASE, // Simple AM2 (+-imm12) 59218893Sdim AM2_SHOP // Shifter-op AM2 60218893Sdim}; 61218893Sdim 62193323Sedclass ARMDAGToDAGISel : public SelectionDAGISel { 63193323Sed /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 64193323Sed /// make the right decision when generating code for different targets. 65193323Sed const ARMSubtarget *Subtarget; 66193323Sed 67193323Sedpublic: 68276479Sdim explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel) 69276479Sdim : SelectionDAGISel(tm, OptLevel) {} 70276479Sdim 71276479Sdim bool runOnMachineFunction(MachineFunction &MF) override { 72276479Sdim // Reset the subtarget each time through. 73276479Sdim Subtarget = &MF.getTarget().getSubtarget<ARMSubtarget>(); 74276479Sdim SelectionDAGISel::runOnMachineFunction(MF); 75276479Sdim return true; 76193323Sed } 77193323Sed 78276479Sdim const char *getPassName() const override { 79193323Sed return "ARM Instruction Selection"; 80194612Sed } 81194612Sed 82276479Sdim void PreprocessISelDAG() override; 83249423Sdim 84198090Srdivacky /// getI32Imm - Return a target constant of type i32 with the specified 85198090Srdivacky /// value. 86194612Sed inline SDValue getI32Imm(unsigned Imm) { 87194612Sed return CurDAG->getTargetConstant(Imm, MVT::i32); 88194612Sed } 89194612Sed 90276479Sdim SDNode *Select(SDNode *N) override; 91203954Srdivacky 92218893Sdim 93218893Sdim bool hasNoVMLxHazardUse(SDNode *N) const; 94218893Sdim bool isShifterOpProfitable(const SDValue &Shift, 95218893Sdim ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt); 96226633Sdim bool SelectRegShifterOperand(SDValue N, SDValue &A, 97221345Sdim SDValue &B, SDValue &C, 98221345Sdim bool CheckProfitability = true); 99226633Sdim bool SelectImmShifterOperand(SDValue N, SDValue &A, 100226633Sdim SDValue &B, bool CheckProfitability = true); 101226633Sdim bool SelectShiftRegShifterOperand(SDValue N, SDValue &A, 102221345Sdim SDValue &B, SDValue &C) { 103221345Sdim // Don't apply the profitability check 104226633Sdim return SelectRegShifterOperand(N, A, B, C, false); 105221345Sdim } 106226633Sdim bool SelectShiftImmShifterOperand(SDValue N, SDValue &A, 107226633Sdim SDValue &B) { 108226633Sdim // Don't apply the profitability check 109226633Sdim return SelectImmShifterOperand(N, A, B, false); 110226633Sdim } 111221345Sdim 112218893Sdim bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); 113218893Sdim bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); 114218893Sdim 115218893Sdim AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base, 116218893Sdim SDValue &Offset, SDValue &Opc); 117218893Sdim bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset, 118218893Sdim SDValue &Opc) { 119218893Sdim return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE; 120218893Sdim } 121218893Sdim 122218893Sdim bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset, 123218893Sdim SDValue &Opc) { 124218893Sdim return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP; 125218893Sdim } 126218893Sdim 127218893Sdim bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset, 128218893Sdim SDValue &Opc) { 129218893Sdim SelectAddrMode2Worker(N, Base, Offset, Opc); 130218893Sdim// return SelectAddrMode2ShOp(N, Base, Offset, Opc); 131218893Sdim // This always matches one way or another. 132218893Sdim return true; 133218893Sdim } 134218893Sdim 135261991Sdim bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) { 136261991Sdim const ConstantSDNode *CN = cast<ConstantSDNode>(N); 137261991Sdim Pred = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); 138261991Sdim Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32); 139261991Sdim return true; 140261991Sdim } 141261991Sdim 142226633Sdim bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, 143193323Sed SDValue &Offset, SDValue &Opc); 144226633Sdim bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, 145226633Sdim SDValue &Offset, SDValue &Opc); 146226633Sdim bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N, 147226633Sdim SDValue &Offset, SDValue &Opc); 148226633Sdim bool SelectAddrOffsetNone(SDValue N, SDValue &Base); 149218893Sdim bool SelectAddrMode3(SDValue N, SDValue &Base, 150193323Sed SDValue &Offset, SDValue &Opc); 151202375Srdivacky bool SelectAddrMode3Offset(SDNode *Op, SDValue N, 152193323Sed SDValue &Offset, SDValue &Opc); 153218893Sdim bool SelectAddrMode5(SDValue N, SDValue &Base, 154193323Sed SDValue &Offset); 155218893Sdim bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align); 156219077Sdim bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset); 157193323Sed 158218893Sdim bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label); 159193323Sed 160218893Sdim // Thumb Addressing Modes: 161218893Sdim bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset); 162218893Sdim bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset, 163218893Sdim unsigned Scale); 164218893Sdim bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset); 165218893Sdim bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset); 166218893Sdim bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset); 167218893Sdim bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base, 168218893Sdim SDValue &OffImm); 169218893Sdim bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, 170218893Sdim SDValue &OffImm); 171218893Sdim bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, 172218893Sdim SDValue &OffImm); 173218893Sdim bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, 174218893Sdim SDValue &OffImm); 175218893Sdim bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm); 176193323Sed 177218893Sdim // Thumb 2 Addressing Modes: 178218893Sdim bool SelectT2ShifterOperandReg(SDValue N, 179195098Sed SDValue &BaseReg, SDValue &Opc); 180218893Sdim bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); 181218893Sdim bool SelectT2AddrModeImm8(SDValue N, SDValue &Base, 182195340Sed SDValue &OffImm); 183202375Srdivacky bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 184195340Sed SDValue &OffImm); 185218893Sdim bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base, 186195340Sed SDValue &OffReg, SDValue &ShImm); 187261991Sdim bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm); 188195340Sed 189218893Sdim inline bool is_so_imm(unsigned Imm) const { 190218893Sdim return ARM_AM::getSOImmVal(Imm) != -1; 191218893Sdim } 192218893Sdim 193218893Sdim inline bool is_so_imm_not(unsigned Imm) const { 194218893Sdim return ARM_AM::getSOImmVal(~Imm) != -1; 195218893Sdim } 196218893Sdim 197218893Sdim inline bool is_t2_so_imm(unsigned Imm) const { 198218893Sdim return ARM_AM::getT2SOImmVal(Imm) != -1; 199218893Sdim } 200218893Sdim 201218893Sdim inline bool is_t2_so_imm_not(unsigned Imm) const { 202218893Sdim return ARM_AM::getT2SOImmVal(~Imm) != -1; 203218893Sdim } 204218893Sdim 205193323Sed // Include the pieces autogenerated from the target description. 206193323Sed#include "ARMGenDAGISel.inc" 207193323Sed 208193323Sedprivate: 209195340Sed /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for 210195340Sed /// ARM. 211202375Srdivacky SDNode *SelectARMIndexedLoad(SDNode *N); 212202375Srdivacky SDNode *SelectT2IndexedLoad(SDNode *N); 213195340Sed 214206083Srdivacky /// SelectVLD - Select NEON load intrinsics. NumVecs should be 215206083Srdivacky /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for 216198090Srdivacky /// loads of D registers and even subregs and odd subregs of Q registers. 217206083Srdivacky /// For NumVecs <= 2, QOpcodes1 is not used. 218218893Sdim SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, 219239462Sdim const uint16_t *DOpcodes, 220239462Sdim const uint16_t *QOpcodes0, const uint16_t *QOpcodes1); 221198090Srdivacky 222198113Srdivacky /// SelectVST - Select NEON store intrinsics. NumVecs should 223206083Srdivacky /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for 224198113Srdivacky /// stores of D registers and even subregs and odd subregs of Q registers. 225206083Srdivacky /// For NumVecs <= 2, QOpcodes1 is not used. 226218893Sdim SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, 227239462Sdim const uint16_t *DOpcodes, 228239462Sdim const uint16_t *QOpcodes0, const uint16_t *QOpcodes1); 229198113Srdivacky 230198090Srdivacky /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 231198090Srdivacky /// be 2, 3 or 4. The opcode arrays specify the instructions used for 232218893Sdim /// load/store of D registers and Q registers. 233218893Sdim SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, 234218893Sdim bool isUpdating, unsigned NumVecs, 235239462Sdim const uint16_t *DOpcodes, const uint16_t *QOpcodes); 236198090Srdivacky 237218893Sdim /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs 238218893Sdim /// should be 2, 3 or 4. The opcode array specifies the instructions used 239218893Sdim /// for loading D registers. (Q registers are not supported.) 240218893Sdim SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs, 241239462Sdim const uint16_t *Opcodes); 242218893Sdim 243210299Sed /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2, 244210299Sed /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be 245210299Sed /// generated to force the table registers to be consecutive. 246210299Sed SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc); 247210299Sed 248198090Srdivacky /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 249207618Srdivacky SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned); 250198090Srdivacky 251226633Sdim // Select special operations if node forms integer ABS pattern 252226633Sdim SDNode *SelectABSOp(SDNode *N); 253226633Sdim 254249423Sdim SDNode *SelectInlineAsm(SDNode *N); 255249423Sdim 256208599Srdivacky SDNode *SelectConcatVector(SDNode *N); 257208599Srdivacky 258195340Sed /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 259195340Sed /// inline asm expressions. 260276479Sdim bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 261276479Sdim std::vector<SDValue> &OutOps) override; 262198090Srdivacky 263249423Sdim // Form pairs of consecutive R, S, D, or Q registers. 264249423Sdim SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1); 265249423Sdim SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1); 266249423Sdim SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1); 267249423Sdim SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1); 268208599Srdivacky 269210299Sed // Form sequences of 4 consecutive S, D, or Q registers. 270249423Sdim SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 271249423Sdim SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 272249423Sdim SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 273208599Srdivacky 274218893Sdim // Get the alignment operand for a NEON VLD or VST instruction. 275218893Sdim SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector); 276193323Sed}; 277193323Sed} 278193323Sed 279198090Srdivacky/// isInt32Immediate - This method tests to see if the node is a 32-bit constant 280198090Srdivacky/// operand. If so Imm will receive the 32-bit value. 281198090Srdivackystatic bool isInt32Immediate(SDNode *N, unsigned &Imm) { 282198090Srdivacky if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 283198090Srdivacky Imm = cast<ConstantSDNode>(N)->getZExtValue(); 284198090Srdivacky return true; 285198090Srdivacky } 286198090Srdivacky return false; 287198090Srdivacky} 288198090Srdivacky 289198090Srdivacky// isInt32Immediate - This method tests to see if a constant operand. 290198090Srdivacky// If so Imm will receive the 32 bit value. 291198090Srdivackystatic bool isInt32Immediate(SDValue N, unsigned &Imm) { 292198090Srdivacky return isInt32Immediate(N.getNode(), Imm); 293198090Srdivacky} 294198090Srdivacky 295198090Srdivacky// isOpcWithIntImmediate - This method tests to see if the node is a specific 296198090Srdivacky// opcode and that it has a immediate integer right operand. 297198090Srdivacky// If so Imm will receive the 32 bit value. 298198090Srdivackystatic bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 299198090Srdivacky return N->getOpcode() == Opc && 300198090Srdivacky isInt32Immediate(N->getOperand(1).getNode(), Imm); 301198090Srdivacky} 302198090Srdivacky 303218893Sdim/// \brief Check whether a particular node is a constant value representable as 304243830Sdim/// (N * Scale) where (N in [\p RangeMin, \p RangeMax). 305218893Sdim/// 306218893Sdim/// \param ScaledConstant [out] - On success, the pre-scaled constant value. 307226633Sdimstatic bool isScaledConstantInRange(SDValue Node, int Scale, 308218893Sdim int RangeMin, int RangeMax, 309218893Sdim int &ScaledConstant) { 310226633Sdim assert(Scale > 0 && "Invalid scale!"); 311198090Srdivacky 312218893Sdim // Check that this is a constant. 313218893Sdim const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node); 314218893Sdim if (!C) 315218893Sdim return false; 316218893Sdim 317218893Sdim ScaledConstant = (int) C->getZExtValue(); 318218893Sdim if ((ScaledConstant % Scale) != 0) 319218893Sdim return false; 320218893Sdim 321218893Sdim ScaledConstant /= Scale; 322218893Sdim return ScaledConstant >= RangeMin && ScaledConstant < RangeMax; 323218893Sdim} 324218893Sdim 325249423Sdimvoid ARMDAGToDAGISel::PreprocessISelDAG() { 326249423Sdim if (!Subtarget->hasV6T2Ops()) 327249423Sdim return; 328249423Sdim 329249423Sdim bool isThumb2 = Subtarget->isThumb(); 330249423Sdim for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), 331249423Sdim E = CurDAG->allnodes_end(); I != E; ) { 332249423Sdim SDNode *N = I++; // Preincrement iterator to avoid invalidation issues. 333249423Sdim 334249423Sdim if (N->getOpcode() != ISD::ADD) 335249423Sdim continue; 336249423Sdim 337249423Sdim // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with 338249423Sdim // leading zeros, followed by consecutive set bits, followed by 1 or 2 339249423Sdim // trailing zeros, e.g. 1020. 340249423Sdim // Transform the expression to 341249423Sdim // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number 342249423Sdim // of trailing zeros of c2. The left shift would be folded as an shifter 343249423Sdim // operand of 'add' and the 'and' and 'srl' would become a bits extraction 344249423Sdim // node (UBFX). 345249423Sdim 346249423Sdim SDValue N0 = N->getOperand(0); 347249423Sdim SDValue N1 = N->getOperand(1); 348249423Sdim unsigned And_imm = 0; 349249423Sdim if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) { 350249423Sdim if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm)) 351249423Sdim std::swap(N0, N1); 352249423Sdim } 353249423Sdim if (!And_imm) 354249423Sdim continue; 355249423Sdim 356249423Sdim // Check if the AND mask is an immediate of the form: 000.....1111111100 357261991Sdim unsigned TZ = countTrailingZeros(And_imm); 358249423Sdim if (TZ != 1 && TZ != 2) 359249423Sdim // Be conservative here. Shifter operands aren't always free. e.g. On 360249423Sdim // Swift, left shifter operand of 1 / 2 for free but others are not. 361249423Sdim // e.g. 362249423Sdim // ubfx r3, r1, #16, #8 363249423Sdim // ldr.w r3, [r0, r3, lsl #2] 364249423Sdim // vs. 365249423Sdim // mov.w r9, #1020 366249423Sdim // and.w r2, r9, r1, lsr #14 367249423Sdim // ldr r2, [r0, r2] 368249423Sdim continue; 369249423Sdim And_imm >>= TZ; 370249423Sdim if (And_imm & (And_imm + 1)) 371249423Sdim continue; 372249423Sdim 373249423Sdim // Look for (and (srl X, c1), c2). 374249423Sdim SDValue Srl = N1.getOperand(0); 375249423Sdim unsigned Srl_imm = 0; 376249423Sdim if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) || 377249423Sdim (Srl_imm <= 2)) 378249423Sdim continue; 379249423Sdim 380249423Sdim // Make sure first operand is not a shifter operand which would prevent 381249423Sdim // folding of the left shift. 382249423Sdim SDValue CPTmp0; 383249423Sdim SDValue CPTmp1; 384249423Sdim SDValue CPTmp2; 385249423Sdim if (isThumb2) { 386249423Sdim if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1)) 387249423Sdim continue; 388249423Sdim } else { 389249423Sdim if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) || 390249423Sdim SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2)) 391249423Sdim continue; 392249423Sdim } 393249423Sdim 394249423Sdim // Now make the transformation. 395261991Sdim Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32, 396249423Sdim Srl.getOperand(0), 397249423Sdim CurDAG->getConstant(Srl_imm+TZ, MVT::i32)); 398261991Sdim N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32, 399249423Sdim Srl, CurDAG->getConstant(And_imm, MVT::i32)); 400261991Sdim N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32, 401249423Sdim N1, CurDAG->getConstant(TZ, MVT::i32)); 402249423Sdim CurDAG->UpdateNodeOperands(N, N0, N1); 403276479Sdim } 404249423Sdim} 405249423Sdim 406218893Sdim/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS 407218893Sdim/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at 408218893Sdim/// least on current ARM implementations) which should be avoidded. 409218893Sdimbool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const { 410218893Sdim if (OptLevel == CodeGenOpt::None) 411218893Sdim return true; 412218893Sdim 413218893Sdim if (!CheckVMLxHazard) 414218893Sdim return true; 415218893Sdim 416276479Sdim if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() && 417276479Sdim !Subtarget->isCortexA9() && !Subtarget->isSwift()) 418218893Sdim return true; 419218893Sdim 420218893Sdim if (!N->hasOneUse()) 421218893Sdim return false; 422218893Sdim 423218893Sdim SDNode *Use = *N->use_begin(); 424218893Sdim if (Use->getOpcode() == ISD::CopyToReg) 425218893Sdim return true; 426218893Sdim if (Use->isMachineOpcode()) { 427276479Sdim const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>( 428280031Sdim CurDAG->getSubtarget().getInstrInfo()); 429261991Sdim 430224145Sdim const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode()); 431224145Sdim if (MCID.mayStore()) 432218893Sdim return true; 433224145Sdim unsigned Opcode = MCID.getOpcode(); 434218893Sdim if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) 435218893Sdim return true; 436218893Sdim // vmlx feeding into another vmlx. We actually want to unfold 437218893Sdim // the use later in the MLxExpansion pass. e.g. 438218893Sdim // vmla 439218893Sdim // vmla (stall 8 cycles) 440218893Sdim // 441218893Sdim // vmul (5 cycles) 442218893Sdim // vadd (5 cycles) 443218893Sdim // vmla 444218893Sdim // This adds up to about 18 - 19 cycles. 445218893Sdim // 446218893Sdim // vmla 447218893Sdim // vmul (stall 4 cycles) 448218893Sdim // vadd adds up to about 14 cycles. 449218893Sdim return TII->isFpMLxInstruction(Opcode); 450218893Sdim } 451218893Sdim 452218893Sdim return false; 453218893Sdim} 454218893Sdim 455218893Sdimbool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift, 456218893Sdim ARM_AM::ShiftOpc ShOpcVal, 457218893Sdim unsigned ShAmt) { 458243830Sdim if (!Subtarget->isLikeA9() && !Subtarget->isSwift()) 459218893Sdim return true; 460218893Sdim if (Shift.hasOneUse()) 461218893Sdim return true; 462218893Sdim // R << 2 is free. 463243830Sdim return ShOpcVal == ARM_AM::lsl && 464243830Sdim (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1)); 465218893Sdim} 466218893Sdim 467226633Sdimbool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N, 468195340Sed SDValue &BaseReg, 469226633Sdim SDValue &Opc, 470226633Sdim bool CheckProfitability) { 471226633Sdim if (DisableShifterOp) 472226633Sdim return false; 473226633Sdim 474226633Sdim ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 475226633Sdim 476226633Sdim // Don't match base register only case. That is matched to a separate 477226633Sdim // lower complexity pattern with explicit register operand. 478226633Sdim if (ShOpcVal == ARM_AM::no_shift) return false; 479226633Sdim 480226633Sdim BaseReg = N.getOperand(0); 481226633Sdim unsigned ShImmVal = 0; 482226633Sdim ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 483226633Sdim if (!RHS) return false; 484226633Sdim ShImmVal = RHS->getZExtValue() & 31; 485226633Sdim Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 486226633Sdim MVT::i32); 487226633Sdim return true; 488226633Sdim} 489226633Sdim 490226633Sdimbool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N, 491226633Sdim SDValue &BaseReg, 492195340Sed SDValue &ShReg, 493221345Sdim SDValue &Opc, 494221345Sdim bool CheckProfitability) { 495212904Sdim if (DisableShifterOp) 496212904Sdim return false; 497212904Sdim 498226633Sdim ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 499195340Sed 500195340Sed // Don't match base register only case. That is matched to a separate 501195340Sed // lower complexity pattern with explicit register operand. 502195340Sed if (ShOpcVal == ARM_AM::no_shift) return false; 503198090Srdivacky 504195340Sed BaseReg = N.getOperand(0); 505195340Sed unsigned ShImmVal = 0; 506226633Sdim ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 507226633Sdim if (RHS) return false; 508226633Sdim 509226633Sdim ShReg = N.getOperand(1); 510226633Sdim if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal)) 511226633Sdim return false; 512195340Sed Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 513195340Sed MVT::i32); 514195340Sed return true; 515195340Sed} 516195340Sed 517226633Sdim 518218893Sdimbool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N, 519218893Sdim SDValue &Base, 520218893Sdim SDValue &OffImm) { 521218893Sdim // Match simple R + imm12 operands. 522218893Sdim 523218893Sdim // Base only. 524218893Sdim if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 525218893Sdim !CurDAG->isBaseWithConstantOffset(N)) { 526218893Sdim if (N.getOpcode() == ISD::FrameIndex) { 527218893Sdim // Match frame index. 528218893Sdim int FI = cast<FrameIndexSDNode>(N)->getIndex(); 529280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 530218893Sdim OffImm = CurDAG->getTargetConstant(0, MVT::i32); 531218893Sdim return true; 532218893Sdim } 533221345Sdim 534218893Sdim if (N.getOpcode() == ARMISD::Wrapper && 535276479Sdim N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 536218893Sdim Base = N.getOperand(0); 537218893Sdim } else 538218893Sdim Base = N; 539218893Sdim OffImm = CurDAG->getTargetConstant(0, MVT::i32); 540218893Sdim return true; 541218893Sdim } 542218893Sdim 543218893Sdim if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 544280031Sdim int RHSC = (int)RHS->getSExtValue(); 545218893Sdim if (N.getOpcode() == ISD::SUB) 546218893Sdim RHSC = -RHSC; 547218893Sdim 548280031Sdim if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits 549218893Sdim Base = N.getOperand(0); 550218893Sdim if (Base.getOpcode() == ISD::FrameIndex) { 551218893Sdim int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 552280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 553218893Sdim } 554218893Sdim OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 555218893Sdim return true; 556218893Sdim } 557218893Sdim } 558218893Sdim 559218893Sdim // Base only. 560218893Sdim Base = N; 561218893Sdim OffImm = CurDAG->getTargetConstant(0, MVT::i32); 562218893Sdim return true; 563218893Sdim} 564218893Sdim 565218893Sdim 566218893Sdim 567218893Sdimbool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, 568193323Sed SDValue &Opc) { 569218893Sdim if (N.getOpcode() == ISD::MUL && 570243830Sdim ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) { 571193323Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 572193323Sed // X * [3,5,9] -> X + X * [2,4,8] etc. 573193323Sed int RHSC = (int)RHS->getZExtValue(); 574193323Sed if (RHSC & 1) { 575193323Sed RHSC = RHSC & ~1; 576193323Sed ARM_AM::AddrOpc AddSub = ARM_AM::add; 577193323Sed if (RHSC < 0) { 578193323Sed AddSub = ARM_AM::sub; 579193323Sed RHSC = - RHSC; 580193323Sed } 581193323Sed if (isPowerOf2_32(RHSC)) { 582193323Sed unsigned ShAmt = Log2_32(RHSC); 583193323Sed Base = Offset = N.getOperand(0); 584193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 585193323Sed ARM_AM::lsl), 586193323Sed MVT::i32); 587193323Sed return true; 588193323Sed } 589193323Sed } 590193323Sed } 591193323Sed } 592193323Sed 593218893Sdim if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 594218893Sdim // ISD::OR that is equivalent to an ISD::ADD. 595218893Sdim !CurDAG->isBaseWithConstantOffset(N)) 596218893Sdim return false; 597218893Sdim 598218893Sdim // Leave simple R +/- imm12 operands for LDRi12 599218893Sdim if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { 600218893Sdim int RHSC; 601218893Sdim if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, 602218893Sdim -0x1000+1, 0x1000, RHSC)) // 12 bits. 603218893Sdim return false; 604218893Sdim } 605218893Sdim 606218893Sdim // Otherwise this is R +/- [possibly shifted] R. 607218893Sdim ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add; 608226633Sdim ARM_AM::ShiftOpc ShOpcVal = 609226633Sdim ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); 610218893Sdim unsigned ShAmt = 0; 611218893Sdim 612218893Sdim Base = N.getOperand(0); 613218893Sdim Offset = N.getOperand(1); 614218893Sdim 615218893Sdim if (ShOpcVal != ARM_AM::no_shift) { 616218893Sdim // Check to see if the RHS of the shift is a constant, if not, we can't fold 617218893Sdim // it. 618218893Sdim if (ConstantSDNode *Sh = 619218893Sdim dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 620218893Sdim ShAmt = Sh->getZExtValue(); 621218893Sdim if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) 622218893Sdim Offset = N.getOperand(1).getOperand(0); 623218893Sdim else { 624218893Sdim ShAmt = 0; 625218893Sdim ShOpcVal = ARM_AM::no_shift; 626218893Sdim } 627218893Sdim } else { 628218893Sdim ShOpcVal = ARM_AM::no_shift; 629218893Sdim } 630218893Sdim } 631218893Sdim 632218893Sdim // Try matching (R shl C) + (R). 633218893Sdim if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && 634243830Sdim !(Subtarget->isLikeA9() || Subtarget->isSwift() || 635243830Sdim N.getOperand(0).hasOneUse())) { 636226633Sdim ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); 637218893Sdim if (ShOpcVal != ARM_AM::no_shift) { 638218893Sdim // Check to see if the RHS of the shift is a constant, if not, we can't 639218893Sdim // fold it. 640218893Sdim if (ConstantSDNode *Sh = 641218893Sdim dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 642218893Sdim ShAmt = Sh->getZExtValue(); 643226633Sdim if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { 644218893Sdim Offset = N.getOperand(0).getOperand(0); 645218893Sdim Base = N.getOperand(1); 646218893Sdim } else { 647218893Sdim ShAmt = 0; 648218893Sdim ShOpcVal = ARM_AM::no_shift; 649218893Sdim } 650218893Sdim } else { 651218893Sdim ShOpcVal = ARM_AM::no_shift; 652218893Sdim } 653218893Sdim } 654218893Sdim } 655218893Sdim 656218893Sdim Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 657218893Sdim MVT::i32); 658218893Sdim return true; 659218893Sdim} 660218893Sdim 661218893Sdim 662218893Sdim//----- 663218893Sdim 664218893SdimAddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, 665218893Sdim SDValue &Base, 666218893Sdim SDValue &Offset, 667218893Sdim SDValue &Opc) { 668218893Sdim if (N.getOpcode() == ISD::MUL && 669243830Sdim (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) { 670218893Sdim if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 671218893Sdim // X * [3,5,9] -> X + X * [2,4,8] etc. 672218893Sdim int RHSC = (int)RHS->getZExtValue(); 673218893Sdim if (RHSC & 1) { 674218893Sdim RHSC = RHSC & ~1; 675218893Sdim ARM_AM::AddrOpc AddSub = ARM_AM::add; 676218893Sdim if (RHSC < 0) { 677218893Sdim AddSub = ARM_AM::sub; 678218893Sdim RHSC = - RHSC; 679218893Sdim } 680218893Sdim if (isPowerOf2_32(RHSC)) { 681218893Sdim unsigned ShAmt = Log2_32(RHSC); 682218893Sdim Base = Offset = N.getOperand(0); 683218893Sdim Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 684218893Sdim ARM_AM::lsl), 685218893Sdim MVT::i32); 686218893Sdim return AM2_SHOP; 687218893Sdim } 688218893Sdim } 689218893Sdim } 690218893Sdim } 691218893Sdim 692218893Sdim if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 693218893Sdim // ISD::OR that is equivalent to an ADD. 694218893Sdim !CurDAG->isBaseWithConstantOffset(N)) { 695193323Sed Base = N; 696193323Sed if (N.getOpcode() == ISD::FrameIndex) { 697193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 698280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 699199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 700276479Sdim N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 701193323Sed Base = N.getOperand(0); 702193323Sed } 703193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 704193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 705193323Sed ARM_AM::no_shift), 706193323Sed MVT::i32); 707218893Sdim return AM2_BASE; 708193323Sed } 709198090Srdivacky 710193323Sed // Match simple R +/- imm12 operands. 711218893Sdim if (N.getOpcode() != ISD::SUB) { 712218893Sdim int RHSC; 713218893Sdim if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, 714218893Sdim -0x1000+1, 0x1000, RHSC)) { // 12 bits. 715218893Sdim Base = N.getOperand(0); 716218893Sdim if (Base.getOpcode() == ISD::FrameIndex) { 717218893Sdim int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 718280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 719218893Sdim } 720218893Sdim Offset = CurDAG->getRegister(0, MVT::i32); 721193323Sed 722218893Sdim ARM_AM::AddrOpc AddSub = ARM_AM::add; 723218893Sdim if (RHSC < 0) { 724218893Sdim AddSub = ARM_AM::sub; 725218893Sdim RHSC = - RHSC; 726193323Sed } 727218893Sdim Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 728218893Sdim ARM_AM::no_shift), 729218893Sdim MVT::i32); 730218893Sdim return AM2_BASE; 731193323Sed } 732218893Sdim } 733198090Srdivacky 734243830Sdim if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) { 735218893Sdim // Compute R +/- (R << N) and reuse it. 736218893Sdim Base = N; 737218893Sdim Offset = CurDAG->getRegister(0, MVT::i32); 738218893Sdim Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 739218893Sdim ARM_AM::no_shift), 740218893Sdim MVT::i32); 741218893Sdim return AM2_BASE; 742218893Sdim } 743218893Sdim 744198892Srdivacky // Otherwise this is R +/- [possibly shifted] R. 745218893Sdim ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub; 746226633Sdim ARM_AM::ShiftOpc ShOpcVal = 747226633Sdim ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); 748193323Sed unsigned ShAmt = 0; 749198090Srdivacky 750193323Sed Base = N.getOperand(0); 751193323Sed Offset = N.getOperand(1); 752198090Srdivacky 753193323Sed if (ShOpcVal != ARM_AM::no_shift) { 754193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 755193323Sed // it. 756193323Sed if (ConstantSDNode *Sh = 757193323Sed dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 758193323Sed ShAmt = Sh->getZExtValue(); 759218893Sdim if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) 760218893Sdim Offset = N.getOperand(1).getOperand(0); 761218893Sdim else { 762218893Sdim ShAmt = 0; 763218893Sdim ShOpcVal = ARM_AM::no_shift; 764218893Sdim } 765193323Sed } else { 766193323Sed ShOpcVal = ARM_AM::no_shift; 767193323Sed } 768193323Sed } 769198090Srdivacky 770193323Sed // Try matching (R shl C) + (R). 771218893Sdim if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && 772243830Sdim !(Subtarget->isLikeA9() || Subtarget->isSwift() || 773243830Sdim N.getOperand(0).hasOneUse())) { 774226633Sdim ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); 775193323Sed if (ShOpcVal != ARM_AM::no_shift) { 776193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't 777193323Sed // fold it. 778193323Sed if (ConstantSDNode *Sh = 779193323Sed dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 780193323Sed ShAmt = Sh->getZExtValue(); 781226633Sdim if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { 782218893Sdim Offset = N.getOperand(0).getOperand(0); 783218893Sdim Base = N.getOperand(1); 784218893Sdim } else { 785218893Sdim ShAmt = 0; 786218893Sdim ShOpcVal = ARM_AM::no_shift; 787218893Sdim } 788193323Sed } else { 789193323Sed ShOpcVal = ARM_AM::no_shift; 790193323Sed } 791193323Sed } 792193323Sed } 793198090Srdivacky 794193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 795193323Sed MVT::i32); 796218893Sdim return AM2_SHOP; 797193323Sed} 798193323Sed 799226633Sdimbool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, 800193323Sed SDValue &Offset, SDValue &Opc) { 801202375Srdivacky unsigned Opcode = Op->getOpcode(); 802193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 803193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 804193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 805193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 806193323Sed ? ARM_AM::add : ARM_AM::sub; 807218893Sdim int Val; 808226633Sdim if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) 809226633Sdim return false; 810193323Sed 811193323Sed Offset = N; 812226633Sdim ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 813193323Sed unsigned ShAmt = 0; 814193323Sed if (ShOpcVal != ARM_AM::no_shift) { 815193323Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 816193323Sed // it. 817193323Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 818193323Sed ShAmt = Sh->getZExtValue(); 819218893Sdim if (isShifterOpProfitable(N, ShOpcVal, ShAmt)) 820218893Sdim Offset = N.getOperand(0); 821218893Sdim else { 822218893Sdim ShAmt = 0; 823218893Sdim ShOpcVal = ARM_AM::no_shift; 824218893Sdim } 825193323Sed } else { 826193323Sed ShOpcVal = ARM_AM::no_shift; 827193323Sed } 828193323Sed } 829193323Sed 830193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 831193323Sed MVT::i32); 832193323Sed return true; 833193323Sed} 834193323Sed 835226633Sdimbool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N, 836226633Sdim SDValue &Offset, SDValue &Opc) { 837226633Sdim unsigned Opcode = Op->getOpcode(); 838226633Sdim ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 839226633Sdim ? cast<LoadSDNode>(Op)->getAddressingMode() 840226633Sdim : cast<StoreSDNode>(Op)->getAddressingMode(); 841226633Sdim ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 842226633Sdim ? ARM_AM::add : ARM_AM::sub; 843226633Sdim int Val; 844226633Sdim if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. 845226633Sdim if (AddSub == ARM_AM::sub) Val *= -1; 846226633Sdim Offset = CurDAG->getRegister(0, MVT::i32); 847226633Sdim Opc = CurDAG->getTargetConstant(Val, MVT::i32); 848226633Sdim return true; 849226633Sdim } 850193323Sed 851226633Sdim return false; 852226633Sdim} 853226633Sdim 854226633Sdim 855226633Sdimbool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, 856226633Sdim SDValue &Offset, SDValue &Opc) { 857226633Sdim unsigned Opcode = Op->getOpcode(); 858226633Sdim ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 859226633Sdim ? cast<LoadSDNode>(Op)->getAddressingMode() 860226633Sdim : cast<StoreSDNode>(Op)->getAddressingMode(); 861226633Sdim ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 862226633Sdim ? ARM_AM::add : ARM_AM::sub; 863226633Sdim int Val; 864226633Sdim if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. 865226633Sdim Offset = CurDAG->getRegister(0, MVT::i32); 866226633Sdim Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 867226633Sdim ARM_AM::no_shift), 868226633Sdim MVT::i32); 869226633Sdim return true; 870226633Sdim } 871226633Sdim 872226633Sdim return false; 873226633Sdim} 874226633Sdim 875226633Sdimbool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) { 876226633Sdim Base = N; 877226633Sdim return true; 878226633Sdim} 879226633Sdim 880218893Sdimbool ARMDAGToDAGISel::SelectAddrMode3(SDValue N, 881193323Sed SDValue &Base, SDValue &Offset, 882193323Sed SDValue &Opc) { 883193323Sed if (N.getOpcode() == ISD::SUB) { 884193323Sed // X - C is canonicalize to X + -C, no need to handle it here. 885193323Sed Base = N.getOperand(0); 886193323Sed Offset = N.getOperand(1); 887193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 888193323Sed return true; 889193323Sed } 890198090Srdivacky 891218893Sdim if (!CurDAG->isBaseWithConstantOffset(N)) { 892193323Sed Base = N; 893193323Sed if (N.getOpcode() == ISD::FrameIndex) { 894193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 895280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 896193323Sed } 897193323Sed Offset = CurDAG->getRegister(0, MVT::i32); 898193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 899193323Sed return true; 900193323Sed } 901198090Srdivacky 902193323Sed // If the RHS is +/- imm8, fold into addr mode. 903218893Sdim int RHSC; 904218893Sdim if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, 905218893Sdim -256 + 1, 256, RHSC)) { // 8 bits. 906218893Sdim Base = N.getOperand(0); 907218893Sdim if (Base.getOpcode() == ISD::FrameIndex) { 908218893Sdim int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 909280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 910218893Sdim } 911218893Sdim Offset = CurDAG->getRegister(0, MVT::i32); 912193323Sed 913218893Sdim ARM_AM::AddrOpc AddSub = ARM_AM::add; 914218893Sdim if (RHSC < 0) { 915218893Sdim AddSub = ARM_AM::sub; 916218893Sdim RHSC = -RHSC; 917193323Sed } 918218893Sdim Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 919218893Sdim return true; 920193323Sed } 921198090Srdivacky 922193323Sed Base = N.getOperand(0); 923193323Sed Offset = N.getOperand(1); 924193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 925193323Sed return true; 926193323Sed} 927193323Sed 928202375Srdivackybool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, 929193323Sed SDValue &Offset, SDValue &Opc) { 930202375Srdivacky unsigned Opcode = Op->getOpcode(); 931193323Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 932193323Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 933193323Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 934193323Sed ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 935193323Sed ? ARM_AM::add : ARM_AM::sub; 936218893Sdim int Val; 937218893Sdim if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits. 938218893Sdim Offset = CurDAG->getRegister(0, MVT::i32); 939218893Sdim Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 940218893Sdim return true; 941193323Sed } 942193323Sed 943193323Sed Offset = N; 944193323Sed Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 945193323Sed return true; 946193323Sed} 947193323Sed 948218893Sdimbool ARMDAGToDAGISel::SelectAddrMode5(SDValue N, 949193323Sed SDValue &Base, SDValue &Offset) { 950218893Sdim if (!CurDAG->isBaseWithConstantOffset(N)) { 951193323Sed Base = N; 952193323Sed if (N.getOpcode() == ISD::FrameIndex) { 953193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 954280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 955199989Srdivacky } else if (N.getOpcode() == ARMISD::Wrapper && 956276479Sdim N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 957193323Sed Base = N.getOperand(0); 958193323Sed } 959193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 960193323Sed MVT::i32); 961193323Sed return true; 962193323Sed } 963198090Srdivacky 964193323Sed // If the RHS is +/- imm8, fold into addr mode. 965218893Sdim int RHSC; 966218893Sdim if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 967218893Sdim -256 + 1, 256, RHSC)) { 968218893Sdim Base = N.getOperand(0); 969218893Sdim if (Base.getOpcode() == ISD::FrameIndex) { 970218893Sdim int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 971280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 972218893Sdim } 973193323Sed 974218893Sdim ARM_AM::AddrOpc AddSub = ARM_AM::add; 975218893Sdim if (RHSC < 0) { 976218893Sdim AddSub = ARM_AM::sub; 977218893Sdim RHSC = -RHSC; 978193323Sed } 979218893Sdim Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 980218893Sdim MVT::i32); 981218893Sdim return true; 982193323Sed } 983198090Srdivacky 984193323Sed Base = N; 985193323Sed Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 986193323Sed MVT::i32); 987193323Sed return true; 988193323Sed} 989193323Sed 990218893Sdimbool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr, 991218893Sdim SDValue &Align) { 992195340Sed Addr = N; 993218893Sdim 994218893Sdim unsigned Alignment = 0; 995218893Sdim if (LSBaseSDNode *LSN = dyn_cast<LSBaseSDNode>(Parent)) { 996218893Sdim // This case occurs only for VLD1-lane/dup and VST1-lane instructions. 997218893Sdim // The maximum alignment is equal to the memory size being referenced. 998218893Sdim unsigned LSNAlign = LSN->getAlignment(); 999218893Sdim unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8; 1000234353Sdim if (LSNAlign >= MemSize && MemSize > 1) 1001218893Sdim Alignment = MemSize; 1002218893Sdim } else { 1003218893Sdim // All other uses of addrmode6 are for intrinsics. For now just record 1004218893Sdim // the raw alignment value; it will be refined later based on the legal 1005218893Sdim // alignment operands for the intrinsic. 1006218893Sdim Alignment = cast<MemIntrinsicSDNode>(Parent)->getAlignment(); 1007218893Sdim } 1008218893Sdim 1009218893Sdim Align = CurDAG->getTargetConstant(Alignment, MVT::i32); 1010195340Sed return true; 1011195340Sed} 1012195340Sed 1013219077Sdimbool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N, 1014219077Sdim SDValue &Offset) { 1015219077Sdim LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op); 1016219077Sdim ISD::MemIndexedMode AM = LdSt->getAddressingMode(); 1017219077Sdim if (AM != ISD::POST_INC) 1018219077Sdim return false; 1019219077Sdim Offset = N; 1020219077Sdim if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) { 1021219077Sdim if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits()) 1022219077Sdim Offset = CurDAG->getRegister(0, MVT::i32); 1023219077Sdim } 1024219077Sdim return true; 1025219077Sdim} 1026219077Sdim 1027218893Sdimbool ARMDAGToDAGISel::SelectAddrModePC(SDValue N, 1028198090Srdivacky SDValue &Offset, SDValue &Label) { 1029193323Sed if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 1030193323Sed Offset = N.getOperand(0); 1031193323Sed SDValue N1 = N.getOperand(1); 1032218893Sdim Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 1033218893Sdim MVT::i32); 1034193323Sed return true; 1035193323Sed } 1036218893Sdim 1037193323Sed return false; 1038193323Sed} 1039193323Sed 1040218893Sdim 1041218893Sdim//===----------------------------------------------------------------------===// 1042218893Sdim// Thumb Addressing Modes 1043218893Sdim//===----------------------------------------------------------------------===// 1044218893Sdim 1045218893Sdimbool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, 1046193323Sed SDValue &Base, SDValue &Offset){ 1047218893Sdim if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) { 1048198090Srdivacky ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 1049210299Sed if (!NC || !NC->isNullValue()) 1050198090Srdivacky return false; 1051198090Srdivacky 1052198090Srdivacky Base = Offset = N; 1053193323Sed return true; 1054193323Sed } 1055193323Sed 1056193323Sed Base = N.getOperand(0); 1057193323Sed Offset = N.getOperand(1); 1058193323Sed return true; 1059193323Sed} 1060193323Sed 1061193323Sedbool 1062218893SdimARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base, 1063218893Sdim SDValue &Offset, unsigned Scale) { 1064193323Sed if (Scale == 4) { 1065193323Sed SDValue TmpBase, TmpOffImm; 1066218893Sdim if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm)) 1067193323Sed return false; // We want to select tLDRspi / tSTRspi instead. 1068218893Sdim 1069193323Sed if (N.getOpcode() == ARMISD::Wrapper && 1070193323Sed N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 1071193323Sed return false; // We want to select tLDRpci instead. 1072193323Sed } 1073193323Sed 1074218893Sdim if (!CurDAG->isBaseWithConstantOffset(N)) 1075218893Sdim return false; 1076218893Sdim 1077218893Sdim // Thumb does not have [sp, r] address mode. 1078218893Sdim RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 1079218893Sdim RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 1080218893Sdim if ((LHSR && LHSR->getReg() == ARM::SP) || 1081218893Sdim (RHSR && RHSR->getReg() == ARM::SP)) 1082218893Sdim return false; 1083218893Sdim 1084218893Sdim // FIXME: Why do we explicitly check for a match here and then return false? 1085218893Sdim // Presumably to allow something else to match, but shouldn't this be 1086218893Sdim // documented? 1087218893Sdim int RHSC; 1088218893Sdim if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) 1089218893Sdim return false; 1090218893Sdim 1091218893Sdim Base = N.getOperand(0); 1092218893Sdim Offset = N.getOperand(1); 1093218893Sdim return true; 1094218893Sdim} 1095218893Sdim 1096218893Sdimbool 1097218893SdimARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N, 1098218893Sdim SDValue &Base, 1099218893Sdim SDValue &Offset) { 1100218893Sdim return SelectThumbAddrModeRI(N, Base, Offset, 1); 1101218893Sdim} 1102218893Sdim 1103218893Sdimbool 1104218893SdimARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N, 1105218893Sdim SDValue &Base, 1106218893Sdim SDValue &Offset) { 1107218893Sdim return SelectThumbAddrModeRI(N, Base, Offset, 2); 1108218893Sdim} 1109218893Sdim 1110218893Sdimbool 1111218893SdimARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N, 1112218893Sdim SDValue &Base, 1113218893Sdim SDValue &Offset) { 1114218893Sdim return SelectThumbAddrModeRI(N, Base, Offset, 4); 1115218893Sdim} 1116218893Sdim 1117218893Sdimbool 1118218893SdimARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, 1119218893Sdim SDValue &Base, SDValue &OffImm) { 1120218893Sdim if (Scale == 4) { 1121218893Sdim SDValue TmpBase, TmpOffImm; 1122218893Sdim if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm)) 1123218893Sdim return false; // We want to select tLDRspi / tSTRspi instead. 1124218893Sdim 1125199989Srdivacky if (N.getOpcode() == ARMISD::Wrapper && 1126218893Sdim N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 1127218893Sdim return false; // We want to select tLDRpci instead. 1128218893Sdim } 1129218893Sdim 1130218893Sdim if (!CurDAG->isBaseWithConstantOffset(N)) { 1131218893Sdim if (N.getOpcode() == ARMISD::Wrapper && 1132276479Sdim N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 1133199989Srdivacky Base = N.getOperand(0); 1134218893Sdim } else { 1135199989Srdivacky Base = N; 1136218893Sdim } 1137199989Srdivacky 1138193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 1139193323Sed return true; 1140193323Sed } 1141193323Sed 1142193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 1143193323Sed RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 1144193323Sed if ((LHSR && LHSR->getReg() == ARM::SP) || 1145193323Sed (RHSR && RHSR->getReg() == ARM::SP)) { 1146218893Sdim ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0)); 1147218893Sdim ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 1148218893Sdim unsigned LHSC = LHS ? LHS->getZExtValue() : 0; 1149218893Sdim unsigned RHSC = RHS ? RHS->getZExtValue() : 0; 1150218893Sdim 1151218893Sdim // Thumb does not have [sp, #imm5] address mode for non-zero imm5. 1152218893Sdim if (LHSC != 0 || RHSC != 0) return false; 1153218893Sdim 1154193323Sed Base = N; 1155193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 1156193323Sed return true; 1157193323Sed } 1158193323Sed 1159193323Sed // If the RHS is + imm5 * scale, fold into addr mode. 1160218893Sdim int RHSC; 1161218893Sdim if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) { 1162218893Sdim Base = N.getOperand(0); 1163218893Sdim OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 1164218893Sdim return true; 1165193323Sed } 1166193323Sed 1167193323Sed Base = N.getOperand(0); 1168193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 1169193323Sed return true; 1170193323Sed} 1171193323Sed 1172218893Sdimbool 1173218893SdimARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, 1174218893Sdim SDValue &OffImm) { 1175218893Sdim return SelectThumbAddrModeImm5S(N, 4, Base, OffImm); 1176193323Sed} 1177193323Sed 1178218893Sdimbool 1179218893SdimARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, 1180218893Sdim SDValue &OffImm) { 1181218893Sdim return SelectThumbAddrModeImm5S(N, 2, Base, OffImm); 1182193323Sed} 1183193323Sed 1184218893Sdimbool 1185218893SdimARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, 1186218893Sdim SDValue &OffImm) { 1187218893Sdim return SelectThumbAddrModeImm5S(N, 1, Base, OffImm); 1188193323Sed} 1189193323Sed 1190218893Sdimbool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N, 1191218893Sdim SDValue &Base, SDValue &OffImm) { 1192193323Sed if (N.getOpcode() == ISD::FrameIndex) { 1193193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1194280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 1195193323Sed OffImm = CurDAG->getTargetConstant(0, MVT::i32); 1196193323Sed return true; 1197193323Sed } 1198193323Sed 1199218893Sdim if (!CurDAG->isBaseWithConstantOffset(N)) 1200193323Sed return false; 1201193323Sed 1202193323Sed RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 1203193323Sed if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 1204193323Sed (LHSR && LHSR->getReg() == ARM::SP)) { 1205193323Sed // If the RHS is + imm8 * scale, fold into addr mode. 1206218893Sdim int RHSC; 1207218893Sdim if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) { 1208218893Sdim Base = N.getOperand(0); 1209218893Sdim if (Base.getOpcode() == ISD::FrameIndex) { 1210218893Sdim int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1211280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 1212193323Sed } 1213218893Sdim OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 1214218893Sdim return true; 1215193323Sed } 1216193323Sed } 1217198090Srdivacky 1218193323Sed return false; 1219193323Sed} 1220193323Sed 1221218893Sdim 1222218893Sdim//===----------------------------------------------------------------------===// 1223218893Sdim// Thumb 2 Addressing Modes 1224218893Sdim//===----------------------------------------------------------------------===// 1225218893Sdim 1226218893Sdim 1227218893Sdimbool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg, 1228195098Sed SDValue &Opc) { 1229212904Sdim if (DisableShifterOp) 1230212904Sdim return false; 1231212904Sdim 1232226633Sdim ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 1233195098Sed 1234195098Sed // Don't match base register only case. That is matched to a separate 1235195098Sed // lower complexity pattern with explicit register operand. 1236195098Sed if (ShOpcVal == ARM_AM::no_shift) return false; 1237195098Sed 1238195098Sed BaseReg = N.getOperand(0); 1239195098Sed unsigned ShImmVal = 0; 1240195098Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 1241195098Sed ShImmVal = RHS->getZExtValue() & 31; 1242195098Sed Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); 1243195098Sed return true; 1244195098Sed } 1245195098Sed 1246195098Sed return false; 1247195098Sed} 1248195098Sed 1249218893Sdimbool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N, 1250195340Sed SDValue &Base, SDValue &OffImm) { 1251195340Sed // Match simple R + imm12 operands. 1252195340Sed 1253198090Srdivacky // Base only. 1254218893Sdim if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 1255218893Sdim !CurDAG->isBaseWithConstantOffset(N)) { 1256198090Srdivacky if (N.getOpcode() == ISD::FrameIndex) { 1257218893Sdim // Match frame index. 1258198090Srdivacky int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1259280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 1260198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 1261198090Srdivacky return true; 1262218893Sdim } 1263221345Sdim 1264218893Sdim if (N.getOpcode() == ARMISD::Wrapper && 1265276479Sdim N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 1266198090Srdivacky Base = N.getOperand(0); 1267198090Srdivacky if (Base.getOpcode() == ISD::TargetConstantPool) 1268198090Srdivacky return false; // We want to select t2LDRpci instead. 1269198090Srdivacky } else 1270198090Srdivacky Base = N; 1271198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 1272198090Srdivacky return true; 1273198090Srdivacky } 1274198090Srdivacky 1275195340Sed if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 1276218893Sdim if (SelectT2AddrModeImm8(N, Base, OffImm)) 1277198090Srdivacky // Let t2LDRi8 handle (R - imm8). 1278198090Srdivacky return false; 1279198090Srdivacky 1280195340Sed int RHSC = (int)RHS->getZExtValue(); 1281198090Srdivacky if (N.getOpcode() == ISD::SUB) 1282198090Srdivacky RHSC = -RHSC; 1283198090Srdivacky 1284198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 1285195340Sed Base = N.getOperand(0); 1286198090Srdivacky if (Base.getOpcode() == ISD::FrameIndex) { 1287198090Srdivacky int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1288280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 1289198090Srdivacky } 1290195340Sed OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 1291195340Sed return true; 1292195340Sed } 1293195340Sed } 1294195340Sed 1295198090Srdivacky // Base only. 1296198090Srdivacky Base = N; 1297198090Srdivacky OffImm = CurDAG->getTargetConstant(0, MVT::i32); 1298198090Srdivacky return true; 1299195340Sed} 1300195340Sed 1301218893Sdimbool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N, 1302195340Sed SDValue &Base, SDValue &OffImm) { 1303198090Srdivacky // Match simple R - imm8 operands. 1304218893Sdim if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 1305218893Sdim !CurDAG->isBaseWithConstantOffset(N)) 1306218893Sdim return false; 1307221345Sdim 1308218893Sdim if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 1309218893Sdim int RHSC = (int)RHS->getSExtValue(); 1310218893Sdim if (N.getOpcode() == ISD::SUB) 1311218893Sdim RHSC = -RHSC; 1312198090Srdivacky 1313218893Sdim if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 1314218893Sdim Base = N.getOperand(0); 1315218893Sdim if (Base.getOpcode() == ISD::FrameIndex) { 1316218893Sdim int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1317280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 1318195340Sed } 1319218893Sdim OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 1320218893Sdim return true; 1321195340Sed } 1322195340Sed } 1323195340Sed 1324195340Sed return false; 1325195340Sed} 1326195340Sed 1327202375Srdivackybool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 1328195340Sed SDValue &OffImm){ 1329202375Srdivacky unsigned Opcode = Op->getOpcode(); 1330195340Sed ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 1331195340Sed ? cast<LoadSDNode>(Op)->getAddressingMode() 1332195340Sed : cast<StoreSDNode>(Op)->getAddressingMode(); 1333218893Sdim int RHSC; 1334218893Sdim if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits. 1335218893Sdim OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 1336218893Sdim ? CurDAG->getTargetConstant(RHSC, MVT::i32) 1337218893Sdim : CurDAG->getTargetConstant(-RHSC, MVT::i32); 1338218893Sdim return true; 1339195340Sed } 1340195340Sed 1341195340Sed return false; 1342195340Sed} 1343195340Sed 1344218893Sdimbool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N, 1345195340Sed SDValue &Base, 1346195340Sed SDValue &OffReg, SDValue &ShImm) { 1347198090Srdivacky // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 1348218893Sdim if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) 1349198090Srdivacky return false; 1350198090Srdivacky 1351198090Srdivacky // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 1352198090Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 1353198090Srdivacky int RHSC = (int)RHS->getZExtValue(); 1354198090Srdivacky if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 1355198090Srdivacky return false; 1356198090Srdivacky else if (RHSC < 0 && RHSC >= -255) // 8 bits 1357198090Srdivacky return false; 1358195340Sed } 1359195340Sed 1360195340Sed // Look for (R + R) or (R + (R << [1,2,3])). 1361195340Sed unsigned ShAmt = 0; 1362195340Sed Base = N.getOperand(0); 1363195340Sed OffReg = N.getOperand(1); 1364195340Sed 1365195340Sed // Swap if it is ((R << c) + R). 1366226633Sdim ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode()); 1367195340Sed if (ShOpcVal != ARM_AM::lsl) { 1368226633Sdim ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode()); 1369195340Sed if (ShOpcVal == ARM_AM::lsl) 1370195340Sed std::swap(Base, OffReg); 1371198090Srdivacky } 1372198090Srdivacky 1373195340Sed if (ShOpcVal == ARM_AM::lsl) { 1374195340Sed // Check to see if the RHS of the shift is a constant, if not, we can't fold 1375195340Sed // it. 1376195340Sed if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 1377195340Sed ShAmt = Sh->getZExtValue(); 1378218893Sdim if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt)) 1379218893Sdim OffReg = OffReg.getOperand(0); 1380218893Sdim else { 1381195340Sed ShAmt = 0; 1382218893Sdim } 1383195340Sed } 1384198090Srdivacky } 1385198090Srdivacky 1386195340Sed ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); 1387195340Sed 1388195340Sed return true; 1389195340Sed} 1390195340Sed 1391261991Sdimbool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base, 1392261991Sdim SDValue &OffImm) { 1393276479Sdim // This *must* succeed since it's used for the irreplaceable ldrex and strex 1394261991Sdim // instructions. 1395261991Sdim Base = N; 1396261991Sdim OffImm = CurDAG->getTargetConstant(0, MVT::i32); 1397261991Sdim 1398261991Sdim if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N)) 1399261991Sdim return true; 1400261991Sdim 1401261991Sdim ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 1402261991Sdim if (!RHS) 1403261991Sdim return true; 1404261991Sdim 1405261991Sdim uint32_t RHSC = (int)RHS->getZExtValue(); 1406261991Sdim if (RHSC > 1020 || RHSC % 4 != 0) 1407261991Sdim return true; 1408261991Sdim 1409261991Sdim Base = N.getOperand(0); 1410261991Sdim if (Base.getOpcode() == ISD::FrameIndex) { 1411261991Sdim int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1412280031Sdim Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 1413261991Sdim } 1414261991Sdim 1415261991Sdim OffImm = CurDAG->getTargetConstant(RHSC / 4, MVT::i32); 1416261991Sdim return true; 1417261991Sdim} 1418261991Sdim 1419195340Sed//===--------------------------------------------------------------------===// 1420195340Sed 1421193323Sed/// getAL - Returns a ARMCC::AL immediate node. 1422193323Sedstatic inline SDValue getAL(SelectionDAG *CurDAG) { 1423193323Sed return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 1424193323Sed} 1425193323Sed 1426202375SrdivackySDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { 1427202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 1428195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 1429195340Sed if (AM == ISD::UNINDEXED) 1430276479Sdim return nullptr; 1431193323Sed 1432198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 1433195340Sed SDValue Offset, AMOpc; 1434195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 1435195340Sed unsigned Opcode = 0; 1436195340Sed bool Match = false; 1437226633Sdim if (LoadedVT == MVT::i32 && isPre && 1438226633Sdim SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) { 1439226633Sdim Opcode = ARM::LDR_PRE_IMM; 1440195340Sed Match = true; 1441226633Sdim } else if (LoadedVT == MVT::i32 && !isPre && 1442226633Sdim SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { 1443226633Sdim Opcode = ARM::LDR_POST_IMM; 1444226633Sdim Match = true; 1445226633Sdim } else if (LoadedVT == MVT::i32 && 1446226633Sdim SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { 1447226633Sdim Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG; 1448226633Sdim Match = true; 1449226633Sdim 1450195340Sed } else if (LoadedVT == MVT::i16 && 1451202375Srdivacky SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 1452195340Sed Match = true; 1453195340Sed Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 1454195340Sed ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 1455195340Sed : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 1456195340Sed } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 1457195340Sed if (LD->getExtensionType() == ISD::SEXTLOAD) { 1458202375Srdivacky if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 1459195340Sed Match = true; 1460195340Sed Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 1461195340Sed } 1462195340Sed } else { 1463226633Sdim if (isPre && 1464226633Sdim SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) { 1465195340Sed Match = true; 1466226633Sdim Opcode = ARM::LDRB_PRE_IMM; 1467226633Sdim } else if (!isPre && 1468226633Sdim SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { 1469226633Sdim Match = true; 1470226633Sdim Opcode = ARM::LDRB_POST_IMM; 1471226633Sdim } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { 1472226633Sdim Match = true; 1473226633Sdim Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG; 1474195340Sed } 1475195340Sed } 1476195340Sed } 1477195340Sed 1478195340Sed if (Match) { 1479226633Sdim if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) { 1480226633Sdim SDValue Chain = LD->getChain(); 1481226633Sdim SDValue Base = LD->getBasePtr(); 1482226633Sdim SDValue Ops[]= { Base, AMOpc, getAL(CurDAG), 1483226633Sdim CurDAG->getRegister(0, MVT::i32), Chain }; 1484261991Sdim return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, 1485251662Sdim MVT::i32, MVT::Other, Ops); 1486226633Sdim } else { 1487226633Sdim SDValue Chain = LD->getChain(); 1488226633Sdim SDValue Base = LD->getBasePtr(); 1489226633Sdim SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 1490226633Sdim CurDAG->getRegister(0, MVT::i32), Chain }; 1491261991Sdim return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, 1492251662Sdim MVT::i32, MVT::Other, Ops); 1493226633Sdim } 1494195340Sed } 1495195340Sed 1496276479Sdim return nullptr; 1497195340Sed} 1498195340Sed 1499202375SrdivackySDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { 1500202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 1501195340Sed ISD::MemIndexedMode AM = LD->getAddressingMode(); 1502195340Sed if (AM == ISD::UNINDEXED) 1503276479Sdim return nullptr; 1504195340Sed 1505198090Srdivacky EVT LoadedVT = LD->getMemoryVT(); 1506195340Sed bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 1507195340Sed SDValue Offset; 1508195340Sed bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 1509195340Sed unsigned Opcode = 0; 1510195340Sed bool Match = false; 1511202375Srdivacky if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) { 1512198090Srdivacky switch (LoadedVT.getSimpleVT().SimpleTy) { 1513195340Sed case MVT::i32: 1514195340Sed Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 1515195340Sed break; 1516195340Sed case MVT::i16: 1517195340Sed if (isSExtLd) 1518195340Sed Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 1519195340Sed else 1520195340Sed Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 1521195340Sed break; 1522195340Sed case MVT::i8: 1523195340Sed case MVT::i1: 1524195340Sed if (isSExtLd) 1525195340Sed Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 1526195340Sed else 1527195340Sed Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 1528195340Sed break; 1529195340Sed default: 1530276479Sdim return nullptr; 1531195340Sed } 1532195340Sed Match = true; 1533195340Sed } 1534195340Sed 1535195340Sed if (Match) { 1536195340Sed SDValue Chain = LD->getChain(); 1537195340Sed SDValue Base = LD->getBasePtr(); 1538195340Sed SDValue Ops[]= { Base, Offset, getAL(CurDAG), 1539195340Sed CurDAG->getRegister(0, MVT::i32), Chain }; 1540261991Sdim return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32, 1541251662Sdim MVT::Other, Ops); 1542195340Sed } 1543195340Sed 1544276479Sdim return nullptr; 1545195340Sed} 1546195340Sed 1547249423Sdim/// \brief Form a GPRPair pseudo register from a pair of GPR regs. 1548249423SdimSDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) { 1549261991Sdim SDLoc dl(V0.getNode()); 1550224145Sdim SDValue RegClass = 1551249423Sdim CurDAG->getTargetConstant(ARM::GPRPairRegClassID, MVT::i32); 1552249423Sdim SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32); 1553249423Sdim SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32); 1554249423Sdim const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 1555251662Sdim return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1556249423Sdim} 1557249423Sdim 1558249423Sdim/// \brief Form a D register from a pair of S registers. 1559249423SdimSDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) { 1560261991Sdim SDLoc dl(V0.getNode()); 1561249423Sdim SDValue RegClass = 1562224145Sdim CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32); 1563210299Sed SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); 1564210299Sed SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); 1565224145Sdim const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 1566251662Sdim return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1567210299Sed} 1568210299Sed 1569249423Sdim/// \brief Form a quad register from a pair of D registers. 1570249423SdimSDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) { 1571261991Sdim SDLoc dl(V0.getNode()); 1572224145Sdim SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32); 1573208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 1574208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 1575224145Sdim const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 1576251662Sdim return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1577198090Srdivacky} 1578198090Srdivacky 1579249423Sdim/// \brief Form 4 consecutive D registers from a pair of Q registers. 1580249423SdimSDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) { 1581261991Sdim SDLoc dl(V0.getNode()); 1582224145Sdim SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32); 1583208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); 1584208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); 1585224145Sdim const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 1586251662Sdim return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1587208599Srdivacky} 1588208599Srdivacky 1589249423Sdim/// \brief Form 4 consecutive S registers. 1590249423SdimSDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, 1591210299Sed SDValue V2, SDValue V3) { 1592261991Sdim SDLoc dl(V0.getNode()); 1593224145Sdim SDValue RegClass = 1594224145Sdim CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32); 1595210299Sed SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); 1596210299Sed SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); 1597210299Sed SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32); 1598210299Sed SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32); 1599224145Sdim const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 1600224145Sdim V2, SubReg2, V3, SubReg3 }; 1601251662Sdim return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1602210299Sed} 1603210299Sed 1604249423Sdim/// \brief Form 4 consecutive D registers. 1605249423SdimSDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, 1606208599Srdivacky SDValue V2, SDValue V3) { 1607261991Sdim SDLoc dl(V0.getNode()); 1608224145Sdim SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32); 1609208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 1610208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 1611208599Srdivacky SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32); 1612208599Srdivacky SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32); 1613224145Sdim const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 1614224145Sdim V2, SubReg2, V3, SubReg3 }; 1615251662Sdim return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1616208599Srdivacky} 1617208599Srdivacky 1618249423Sdim/// \brief Form 4 consecutive Q registers. 1619249423SdimSDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, 1620208599Srdivacky SDValue V2, SDValue V3) { 1621261991Sdim SDLoc dl(V0.getNode()); 1622224145Sdim SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32); 1623208599Srdivacky SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); 1624208599Srdivacky SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); 1625208599Srdivacky SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32); 1626208599Srdivacky SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32); 1627224145Sdim const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 1628224145Sdim V2, SubReg2, V3, SubReg3 }; 1629251662Sdim return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1630208599Srdivacky} 1631208599Srdivacky 1632218893Sdim/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand 1633218893Sdim/// of a NEON VLD or VST instruction. The supported values depend on the 1634218893Sdim/// number of registers being loaded. 1635218893SdimSDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs, 1636218893Sdim bool is64BitVector) { 1637218893Sdim unsigned NumRegs = NumVecs; 1638218893Sdim if (!is64BitVector && NumVecs < 3) 1639218893Sdim NumRegs *= 2; 1640208599Srdivacky 1641218893Sdim unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 1642218893Sdim if (Alignment >= 32 && NumRegs == 4) 1643218893Sdim Alignment = 32; 1644218893Sdim else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4)) 1645218893Sdim Alignment = 16; 1646218893Sdim else if (Alignment >= 8) 1647218893Sdim Alignment = 8; 1648218893Sdim else 1649218893Sdim Alignment = 0; 1650218893Sdim 1651218893Sdim return CurDAG->getTargetConstant(Alignment, MVT::i32); 1652198090Srdivacky} 1653198090Srdivacky 1654265925Sdimstatic bool isVLDfixed(unsigned Opc) 1655265925Sdim{ 1656265925Sdim switch (Opc) { 1657265925Sdim default: return false; 1658265925Sdim case ARM::VLD1d8wb_fixed : return true; 1659265925Sdim case ARM::VLD1d16wb_fixed : return true; 1660265925Sdim case ARM::VLD1d64Qwb_fixed : return true; 1661265925Sdim case ARM::VLD1d32wb_fixed : return true; 1662265925Sdim case ARM::VLD1d64wb_fixed : return true; 1663265925Sdim case ARM::VLD1d64TPseudoWB_fixed : return true; 1664265925Sdim case ARM::VLD1d64QPseudoWB_fixed : return true; 1665265925Sdim case ARM::VLD1q8wb_fixed : return true; 1666265925Sdim case ARM::VLD1q16wb_fixed : return true; 1667265925Sdim case ARM::VLD1q32wb_fixed : return true; 1668265925Sdim case ARM::VLD1q64wb_fixed : return true; 1669265925Sdim case ARM::VLD2d8wb_fixed : return true; 1670265925Sdim case ARM::VLD2d16wb_fixed : return true; 1671265925Sdim case ARM::VLD2d32wb_fixed : return true; 1672265925Sdim case ARM::VLD2q8PseudoWB_fixed : return true; 1673265925Sdim case ARM::VLD2q16PseudoWB_fixed : return true; 1674265925Sdim case ARM::VLD2q32PseudoWB_fixed : return true; 1675265925Sdim case ARM::VLD2DUPd8wb_fixed : return true; 1676265925Sdim case ARM::VLD2DUPd16wb_fixed : return true; 1677265925Sdim case ARM::VLD2DUPd32wb_fixed : return true; 1678265925Sdim } 1679265925Sdim} 1680265925Sdim 1681265925Sdimstatic bool isVSTfixed(unsigned Opc) 1682265925Sdim{ 1683265925Sdim switch (Opc) { 1684265925Sdim default: return false; 1685265925Sdim case ARM::VST1d8wb_fixed : return true; 1686265925Sdim case ARM::VST1d16wb_fixed : return true; 1687265925Sdim case ARM::VST1d32wb_fixed : return true; 1688265925Sdim case ARM::VST1d64wb_fixed : return true; 1689276479Sdim case ARM::VST1q8wb_fixed : return true; 1690276479Sdim case ARM::VST1q16wb_fixed : return true; 1691276479Sdim case ARM::VST1q32wb_fixed : return true; 1692276479Sdim case ARM::VST1q64wb_fixed : return true; 1693265925Sdim case ARM::VST1d64TPseudoWB_fixed : return true; 1694265925Sdim case ARM::VST1d64QPseudoWB_fixed : return true; 1695265925Sdim case ARM::VST2d8wb_fixed : return true; 1696265925Sdim case ARM::VST2d16wb_fixed : return true; 1697265925Sdim case ARM::VST2d32wb_fixed : return true; 1698265925Sdim case ARM::VST2q8PseudoWB_fixed : return true; 1699265925Sdim case ARM::VST2q16PseudoWB_fixed : return true; 1700265925Sdim case ARM::VST2q32PseudoWB_fixed : return true; 1701265925Sdim } 1702265925Sdim} 1703265925Sdim 1704234353Sdim// Get the register stride update opcode of a VLD/VST instruction that 1705234353Sdim// is otherwise equivalent to the given fixed stride updating instruction. 1706234353Sdimstatic unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) { 1707265925Sdim assert((isVLDfixed(Opc) || isVSTfixed(Opc)) 1708265925Sdim && "Incorrect fixed stride updating instruction."); 1709234353Sdim switch (Opc) { 1710234353Sdim default: break; 1711234353Sdim case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register; 1712234353Sdim case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register; 1713234353Sdim case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register; 1714234353Sdim case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register; 1715234353Sdim case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register; 1716234353Sdim case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register; 1717234353Sdim case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register; 1718234353Sdim case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register; 1719265925Sdim case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register; 1720265925Sdim case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register; 1721265925Sdim case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register; 1722265925Sdim case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register; 1723234353Sdim 1724234353Sdim case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register; 1725234353Sdim case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register; 1726234353Sdim case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register; 1727234353Sdim case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register; 1728234353Sdim case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register; 1729234353Sdim case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register; 1730234353Sdim case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register; 1731234353Sdim case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register; 1732234353Sdim case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register; 1733234353Sdim case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register; 1734234353Sdim 1735234353Sdim case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register; 1736234353Sdim case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register; 1737234353Sdim case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register; 1738234353Sdim case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register; 1739234353Sdim case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register; 1740234353Sdim case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register; 1741234353Sdim 1742234353Sdim case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register; 1743234353Sdim case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register; 1744234353Sdim case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register; 1745234353Sdim case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register; 1746234353Sdim case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register; 1747234353Sdim case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register; 1748234353Sdim 1749234353Sdim case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register; 1750234353Sdim case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register; 1751234353Sdim case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register; 1752234353Sdim } 1753234353Sdim return Opc; // If not one we handle, return it unchanged. 1754234353Sdim} 1755234353Sdim 1756218893SdimSDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, 1757239462Sdim const uint16_t *DOpcodes, 1758239462Sdim const uint16_t *QOpcodes0, 1759239462Sdim const uint16_t *QOpcodes1) { 1760206083Srdivacky assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 1761261991Sdim SDLoc dl(N); 1762198090Srdivacky 1763205407Srdivacky SDValue MemAddr, Align; 1764218893Sdim unsigned AddrOpIdx = isUpdating ? 1 : 2; 1765218893Sdim if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 1766276479Sdim return nullptr; 1767198090Srdivacky 1768198090Srdivacky SDValue Chain = N->getOperand(0); 1769198090Srdivacky EVT VT = N->getValueType(0); 1770198090Srdivacky bool is64BitVector = VT.is64BitVector(); 1771218893Sdim Align = GetVLDSTAlign(Align, NumVecs, is64BitVector); 1772198090Srdivacky 1773198090Srdivacky unsigned OpcodeIndex; 1774198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1775198090Srdivacky default: llvm_unreachable("unhandled vld type"); 1776198090Srdivacky // Double-register operations: 1777198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1778198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1779198090Srdivacky case MVT::v2f32: 1780198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1781198090Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1782198090Srdivacky // Quad-register operations: 1783198090Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1784198090Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1785198090Srdivacky case MVT::v4f32: 1786198090Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1787280031Sdim case MVT::v2f64: 1788206083Srdivacky case MVT::v2i64: OpcodeIndex = 3; 1789206083Srdivacky assert(NumVecs == 1 && "v2i64 type only supported for VLD1"); 1790206083Srdivacky break; 1791198090Srdivacky } 1792198090Srdivacky 1793212904Sdim EVT ResTy; 1794212904Sdim if (NumVecs == 1) 1795212904Sdim ResTy = VT; 1796212904Sdim else { 1797212904Sdim unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 1798212904Sdim if (!is64BitVector) 1799212904Sdim ResTyElts *= 2; 1800212904Sdim ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts); 1801212904Sdim } 1802218893Sdim std::vector<EVT> ResTys; 1803218893Sdim ResTys.push_back(ResTy); 1804218893Sdim if (isUpdating) 1805218893Sdim ResTys.push_back(MVT::i32); 1806218893Sdim ResTys.push_back(MVT::Other); 1807212904Sdim 1808207618Srdivacky SDValue Pred = getAL(CurDAG); 1809205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1810218893Sdim SDNode *VLd; 1811218893Sdim SmallVector<SDValue, 7> Ops; 1812208599Srdivacky 1813218893Sdim // Double registers and VLD1/VLD2 quad registers are directly supported. 1814218893Sdim if (is64BitVector || NumVecs <= 2) { 1815218893Sdim unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 1816218893Sdim QOpcodes0[OpcodeIndex]); 1817218893Sdim Ops.push_back(MemAddr); 1818218893Sdim Ops.push_back(Align); 1819218893Sdim if (isUpdating) { 1820218893Sdim SDValue Inc = N->getOperand(AddrOpIdx + 1); 1821234353Sdim // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0 1822234353Sdim // case entirely when the rest are updated to that form, too. 1823265925Sdim if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode())) 1824234353Sdim Opc = getVLDSTRegisterUpdateOpcode(Opc); 1825265925Sdim // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so 1826234353Sdim // check for that explicitly too. Horribly hacky, but temporary. 1827265925Sdim if ((NumVecs > 2 && !isVLDfixed(Opc)) || 1828234353Sdim !isa<ConstantSDNode>(Inc.getNode())) 1829234353Sdim Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc); 1830208599Srdivacky } 1831218893Sdim Ops.push_back(Pred); 1832218893Sdim Ops.push_back(Reg0); 1833218893Sdim Ops.push_back(Chain); 1834251662Sdim VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 1835198090Srdivacky 1836198090Srdivacky } else { 1837198090Srdivacky // Otherwise, quad registers are loaded with two separate instructions, 1838198090Srdivacky // where one loads the even registers and the other loads the odd registers. 1839212904Sdim EVT AddrTy = MemAddr.getValueType(); 1840198090Srdivacky 1841218893Sdim // Load the even subregs. This is always an updating load, so that it 1842218893Sdim // provides the address to the second load for the odd subregs. 1843212904Sdim SDValue ImplDef = 1844212904Sdim SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0); 1845212904Sdim const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain }; 1846218893Sdim SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, 1847251662Sdim ResTy, AddrTy, MVT::Other, OpsA); 1848212904Sdim Chain = SDValue(VLdA, 2); 1849198090Srdivacky 1850198113Srdivacky // Load the odd subregs. 1851218893Sdim Ops.push_back(SDValue(VLdA, 1)); 1852218893Sdim Ops.push_back(Align); 1853218893Sdim if (isUpdating) { 1854218893Sdim SDValue Inc = N->getOperand(AddrOpIdx + 1); 1855218893Sdim assert(isa<ConstantSDNode>(Inc.getNode()) && 1856218893Sdim "only constant post-increment update allowed for VLD3/4"); 1857218893Sdim (void)Inc; 1858218893Sdim Ops.push_back(Reg0); 1859218893Sdim } 1860218893Sdim Ops.push_back(SDValue(VLdA, 0)); 1861218893Sdim Ops.push_back(Pred); 1862218893Sdim Ops.push_back(Reg0); 1863218893Sdim Ops.push_back(Chain); 1864251662Sdim VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops); 1865212904Sdim } 1866198090Srdivacky 1867221345Sdim // Transfer memoperands. 1868221345Sdim MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 1869221345Sdim MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 1870221345Sdim cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1); 1871221345Sdim 1872218893Sdim if (NumVecs == 1) 1873218893Sdim return VLd; 1874218893Sdim 1875218893Sdim // Extract out the subregisters. 1876218893Sdim SDValue SuperReg = SDValue(VLd, 0); 1877218893Sdim assert(ARM::dsub_7 == ARM::dsub_0+7 && 1878218893Sdim ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); 1879218893Sdim unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0); 1880218893Sdim for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 1881218893Sdim ReplaceUses(SDValue(N, Vec), 1882218893Sdim CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg)); 1883218893Sdim ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1)); 1884218893Sdim if (isUpdating) 1885218893Sdim ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2)); 1886276479Sdim return nullptr; 1887198090Srdivacky} 1888198090Srdivacky 1889218893SdimSDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, 1890239462Sdim const uint16_t *DOpcodes, 1891239462Sdim const uint16_t *QOpcodes0, 1892239462Sdim const uint16_t *QOpcodes1) { 1893210299Sed assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range"); 1894261991Sdim SDLoc dl(N); 1895198113Srdivacky 1896205407Srdivacky SDValue MemAddr, Align; 1897218893Sdim unsigned AddrOpIdx = isUpdating ? 1 : 2; 1898218893Sdim unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1) 1899218893Sdim if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 1900276479Sdim return nullptr; 1901198113Srdivacky 1902221345Sdim MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 1903221345Sdim MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 1904221345Sdim 1905198113Srdivacky SDValue Chain = N->getOperand(0); 1906218893Sdim EVT VT = N->getOperand(Vec0Idx).getValueType(); 1907198113Srdivacky bool is64BitVector = VT.is64BitVector(); 1908218893Sdim Align = GetVLDSTAlign(Align, NumVecs, is64BitVector); 1909198113Srdivacky 1910198113Srdivacky unsigned OpcodeIndex; 1911198113Srdivacky switch (VT.getSimpleVT().SimpleTy) { 1912198113Srdivacky default: llvm_unreachable("unhandled vst type"); 1913198113Srdivacky // Double-register operations: 1914198113Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 1915198113Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 1916198113Srdivacky case MVT::v2f32: 1917198113Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 1918198113Srdivacky case MVT::v1i64: OpcodeIndex = 3; break; 1919198113Srdivacky // Quad-register operations: 1920198113Srdivacky case MVT::v16i8: OpcodeIndex = 0; break; 1921198113Srdivacky case MVT::v8i16: OpcodeIndex = 1; break; 1922198113Srdivacky case MVT::v4f32: 1923198113Srdivacky case MVT::v4i32: OpcodeIndex = 2; break; 1924280031Sdim case MVT::v2f64: 1925206083Srdivacky case MVT::v2i64: OpcodeIndex = 3; 1926206083Srdivacky assert(NumVecs == 1 && "v2i64 type only supported for VST1"); 1927206083Srdivacky break; 1928198113Srdivacky } 1929198113Srdivacky 1930218893Sdim std::vector<EVT> ResTys; 1931218893Sdim if (isUpdating) 1932218893Sdim ResTys.push_back(MVT::i32); 1933218893Sdim ResTys.push_back(MVT::Other); 1934218893Sdim 1935207618Srdivacky SDValue Pred = getAL(CurDAG); 1936205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 1937212904Sdim SmallVector<SDValue, 7> Ops; 1938198113Srdivacky 1939218893Sdim // Double registers and VST1/VST2 quad registers are directly supported. 1940218893Sdim if (is64BitVector || NumVecs <= 2) { 1941218893Sdim SDValue SrcReg; 1942212904Sdim if (NumVecs == 1) { 1943218893Sdim SrcReg = N->getOperand(Vec0Idx); 1944218893Sdim } else if (is64BitVector) { 1945208599Srdivacky // Form a REG_SEQUENCE to force register allocation. 1946218893Sdim SDValue V0 = N->getOperand(Vec0Idx + 0); 1947218893Sdim SDValue V1 = N->getOperand(Vec0Idx + 1); 1948208599Srdivacky if (NumVecs == 2) 1949249423Sdim SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0); 1950208599Srdivacky else { 1951218893Sdim SDValue V2 = N->getOperand(Vec0Idx + 2); 1952218893Sdim // If it's a vst3, form a quad D-register and leave the last part as 1953208599Srdivacky // an undef. 1954208599Srdivacky SDValue V3 = (NumVecs == 3) 1955208599Srdivacky ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 1956218893Sdim : N->getOperand(Vec0Idx + 3); 1957249423Sdim SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0); 1958208599Srdivacky } 1959212904Sdim } else { 1960212904Sdim // Form a QQ register. 1961218893Sdim SDValue Q0 = N->getOperand(Vec0Idx); 1962218893Sdim SDValue Q1 = N->getOperand(Vec0Idx + 1); 1963249423Sdim SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0); 1964198113Srdivacky } 1965218893Sdim 1966218893Sdim unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 1967218893Sdim QOpcodes0[OpcodeIndex]); 1968218893Sdim Ops.push_back(MemAddr); 1969218893Sdim Ops.push_back(Align); 1970218893Sdim if (isUpdating) { 1971218893Sdim SDValue Inc = N->getOperand(AddrOpIdx + 1); 1972234353Sdim // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0 1973234353Sdim // case entirely when the rest are updated to that form, too. 1974234353Sdim if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode())) 1975234353Sdim Opc = getVLDSTRegisterUpdateOpcode(Opc); 1976265925Sdim // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so 1977234353Sdim // check for that explicitly too. Horribly hacky, but temporary. 1978265925Sdim if (!isa<ConstantSDNode>(Inc.getNode())) 1979265925Sdim Ops.push_back(Inc); 1980265925Sdim else if (NumVecs > 2 && !isVSTfixed(Opc)) 1981265925Sdim Ops.push_back(Reg0); 1982218893Sdim } 1983218893Sdim Ops.push_back(SrcReg); 1984212904Sdim Ops.push_back(Pred); 1985218893Sdim Ops.push_back(Reg0); 1986212904Sdim Ops.push_back(Chain); 1987251662Sdim SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 1988221345Sdim 1989221345Sdim // Transfer memoperands. 1990221345Sdim cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1); 1991221345Sdim 1992221345Sdim return VSt; 1993198113Srdivacky } 1994198113Srdivacky 1995198113Srdivacky // Otherwise, quad registers are stored with two separate instructions, 1996198113Srdivacky // where one stores the even registers and the other stores the odd registers. 1997198113Srdivacky 1998210299Sed // Form the QQQQ REG_SEQUENCE. 1999218893Sdim SDValue V0 = N->getOperand(Vec0Idx + 0); 2000218893Sdim SDValue V1 = N->getOperand(Vec0Idx + 1); 2001218893Sdim SDValue V2 = N->getOperand(Vec0Idx + 2); 2002212904Sdim SDValue V3 = (NumVecs == 3) 2003212904Sdim ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 2004218893Sdim : N->getOperand(Vec0Idx + 3); 2005249423Sdim SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0); 2006198113Srdivacky 2007218893Sdim // Store the even D registers. This is always an updating store, so that it 2008218893Sdim // provides the address to the second store for the odd subregs. 2009218893Sdim const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain }; 2010218893Sdim SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, 2011218893Sdim MemAddr.getValueType(), 2012251662Sdim MVT::Other, OpsA); 2013221345Sdim cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1); 2014218893Sdim Chain = SDValue(VStA, 1); 2015218893Sdim 2016218893Sdim // Store the odd D registers. 2017218893Sdim Ops.push_back(SDValue(VStA, 0)); 2018218893Sdim Ops.push_back(Align); 2019218893Sdim if (isUpdating) { 2020218893Sdim SDValue Inc = N->getOperand(AddrOpIdx + 1); 2021218893Sdim assert(isa<ConstantSDNode>(Inc.getNode()) && 2022218893Sdim "only constant post-increment update allowed for VST3/4"); 2023218893Sdim (void)Inc; 2024218893Sdim Ops.push_back(Reg0); 2025218893Sdim } 2026212904Sdim Ops.push_back(RegSeq); 2027210299Sed Ops.push_back(Pred); 2028218893Sdim Ops.push_back(Reg0); 2029210299Sed Ops.push_back(Chain); 2030221345Sdim SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, 2031251662Sdim Ops); 2032221345Sdim cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1); 2033221345Sdim return VStB; 2034198113Srdivacky} 2035198113Srdivacky 2036202375SrdivackySDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, 2037218893Sdim bool isUpdating, unsigned NumVecs, 2038239462Sdim const uint16_t *DOpcodes, 2039239462Sdim const uint16_t *QOpcodes) { 2040198090Srdivacky assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 2041261991Sdim SDLoc dl(N); 2042198090Srdivacky 2043205407Srdivacky SDValue MemAddr, Align; 2044218893Sdim unsigned AddrOpIdx = isUpdating ? 1 : 2; 2045218893Sdim unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1) 2046218893Sdim if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 2047276479Sdim return nullptr; 2048198090Srdivacky 2049221345Sdim MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 2050221345Sdim MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 2051221345Sdim 2052198090Srdivacky SDValue Chain = N->getOperand(0); 2053198090Srdivacky unsigned Lane = 2054218893Sdim cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue(); 2055218893Sdim EVT VT = N->getOperand(Vec0Idx).getValueType(); 2056198090Srdivacky bool is64BitVector = VT.is64BitVector(); 2057198090Srdivacky 2058218893Sdim unsigned Alignment = 0; 2059218893Sdim if (NumVecs != 3) { 2060218893Sdim Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 2061218893Sdim unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8; 2062218893Sdim if (Alignment > NumBytes) 2063218893Sdim Alignment = NumBytes; 2064218893Sdim if (Alignment < 8 && Alignment < NumBytes) 2065218893Sdim Alignment = 0; 2066218893Sdim // Alignment must be a power of two; make sure of that. 2067218893Sdim Alignment = (Alignment & -Alignment); 2068218893Sdim if (Alignment == 1) 2069218893Sdim Alignment = 0; 2070198090Srdivacky } 2071218893Sdim Align = CurDAG->getTargetConstant(Alignment, MVT::i32); 2072198090Srdivacky 2073198090Srdivacky unsigned OpcodeIndex; 2074198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2075198090Srdivacky default: llvm_unreachable("unhandled vld/vst lane type"); 2076198090Srdivacky // Double-register operations: 2077198090Srdivacky case MVT::v8i8: OpcodeIndex = 0; break; 2078198090Srdivacky case MVT::v4i16: OpcodeIndex = 1; break; 2079198090Srdivacky case MVT::v2f32: 2080198090Srdivacky case MVT::v2i32: OpcodeIndex = 2; break; 2081198090Srdivacky // Quad-register operations: 2082198090Srdivacky case MVT::v8i16: OpcodeIndex = 0; break; 2083198090Srdivacky case MVT::v4f32: 2084198090Srdivacky case MVT::v4i32: OpcodeIndex = 1; break; 2085198090Srdivacky } 2086198090Srdivacky 2087218893Sdim std::vector<EVT> ResTys; 2088218893Sdim if (IsLoad) { 2089218893Sdim unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 2090218893Sdim if (!is64BitVector) 2091218893Sdim ResTyElts *= 2; 2092218893Sdim ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), 2093218893Sdim MVT::i64, ResTyElts)); 2094218893Sdim } 2095218893Sdim if (isUpdating) 2096218893Sdim ResTys.push_back(MVT::i32); 2097218893Sdim ResTys.push_back(MVT::Other); 2098218893Sdim 2099207618Srdivacky SDValue Pred = getAL(CurDAG); 2100205407Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2101199989Srdivacky 2102218893Sdim SmallVector<SDValue, 8> Ops; 2103198090Srdivacky Ops.push_back(MemAddr); 2104199481Srdivacky Ops.push_back(Align); 2105218893Sdim if (isUpdating) { 2106218893Sdim SDValue Inc = N->getOperand(AddrOpIdx + 1); 2107218893Sdim Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc); 2108218893Sdim } 2109198090Srdivacky 2110218893Sdim SDValue SuperReg; 2111218893Sdim SDValue V0 = N->getOperand(Vec0Idx + 0); 2112218893Sdim SDValue V1 = N->getOperand(Vec0Idx + 1); 2113218893Sdim if (NumVecs == 2) { 2114218893Sdim if (is64BitVector) 2115249423Sdim SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0); 2116218893Sdim else 2117249423Sdim SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0); 2118198090Srdivacky } else { 2119218893Sdim SDValue V2 = N->getOperand(Vec0Idx + 2); 2120218893Sdim SDValue V3 = (NumVecs == 3) 2121218893Sdim ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 2122218893Sdim : N->getOperand(Vec0Idx + 3); 2123218893Sdim if (is64BitVector) 2124249423Sdim SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0); 2125218893Sdim else 2126249423Sdim SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0); 2127198090Srdivacky } 2128218893Sdim Ops.push_back(SuperReg); 2129198090Srdivacky Ops.push_back(getI32Imm(Lane)); 2130199989Srdivacky Ops.push_back(Pred); 2131205407Srdivacky Ops.push_back(Reg0); 2132198090Srdivacky Ops.push_back(Chain); 2133198090Srdivacky 2134218893Sdim unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 2135218893Sdim QOpcodes[OpcodeIndex]); 2136251662Sdim SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 2137221345Sdim cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1); 2138198090Srdivacky if (!IsLoad) 2139218893Sdim return VLdLn; 2140198090Srdivacky 2141218893Sdim // Extract the subregisters. 2142218893Sdim SuperReg = SDValue(VLdLn, 0); 2143218893Sdim assert(ARM::dsub_7 == ARM::dsub_0+7 && 2144218893Sdim ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); 2145218893Sdim unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0; 2146218893Sdim for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 2147218893Sdim ReplaceUses(SDValue(N, Vec), 2148218893Sdim CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg)); 2149218893Sdim ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1)); 2150218893Sdim if (isUpdating) 2151218893Sdim ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2)); 2152276479Sdim return nullptr; 2153218893Sdim} 2154208599Srdivacky 2155218893SdimSDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, 2156239462Sdim unsigned NumVecs, 2157239462Sdim const uint16_t *Opcodes) { 2158218893Sdim assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range"); 2159261991Sdim SDLoc dl(N); 2160208599Srdivacky 2161218893Sdim SDValue MemAddr, Align; 2162218893Sdim if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align)) 2163276479Sdim return nullptr; 2164218893Sdim 2165221345Sdim MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 2166221345Sdim MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 2167221345Sdim 2168218893Sdim SDValue Chain = N->getOperand(0); 2169218893Sdim EVT VT = N->getValueType(0); 2170218893Sdim 2171218893Sdim unsigned Alignment = 0; 2172218893Sdim if (NumVecs != 3) { 2173218893Sdim Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 2174218893Sdim unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8; 2175218893Sdim if (Alignment > NumBytes) 2176218893Sdim Alignment = NumBytes; 2177218893Sdim if (Alignment < 8 && Alignment < NumBytes) 2178218893Sdim Alignment = 0; 2179218893Sdim // Alignment must be a power of two; make sure of that. 2180218893Sdim Alignment = (Alignment & -Alignment); 2181218893Sdim if (Alignment == 1) 2182218893Sdim Alignment = 0; 2183208599Srdivacky } 2184218893Sdim Align = CurDAG->getTargetConstant(Alignment, MVT::i32); 2185208599Srdivacky 2186218893Sdim unsigned OpcodeIndex; 2187218893Sdim switch (VT.getSimpleVT().SimpleTy) { 2188218893Sdim default: llvm_unreachable("unhandled vld-dup type"); 2189218893Sdim case MVT::v8i8: OpcodeIndex = 0; break; 2190218893Sdim case MVT::v4i16: OpcodeIndex = 1; break; 2191218893Sdim case MVT::v2f32: 2192218893Sdim case MVT::v2i32: OpcodeIndex = 2; break; 2193218893Sdim } 2194218893Sdim 2195218893Sdim SDValue Pred = getAL(CurDAG); 2196218893Sdim SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2197218893Sdim SDValue SuperReg; 2198218893Sdim unsigned Opc = Opcodes[OpcodeIndex]; 2199218893Sdim SmallVector<SDValue, 6> Ops; 2200218893Sdim Ops.push_back(MemAddr); 2201218893Sdim Ops.push_back(Align); 2202218893Sdim if (isUpdating) { 2203234353Sdim // fixed-stride update instructions don't have an explicit writeback 2204234353Sdim // operand. It's implicit in the opcode itself. 2205218893Sdim SDValue Inc = N->getOperand(2); 2206234353Sdim if (!isa<ConstantSDNode>(Inc.getNode())) 2207234353Sdim Ops.push_back(Inc); 2208234353Sdim // FIXME: VLD3 and VLD4 haven't been updated to that form yet. 2209234353Sdim else if (NumVecs > 2) 2210234353Sdim Ops.push_back(Reg0); 2211218893Sdim } 2212218893Sdim Ops.push_back(Pred); 2213218893Sdim Ops.push_back(Reg0); 2214218893Sdim Ops.push_back(Chain); 2215218893Sdim 2216218893Sdim unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 2217218893Sdim std::vector<EVT> ResTys; 2218221345Sdim ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts)); 2219218893Sdim if (isUpdating) 2220218893Sdim ResTys.push_back(MVT::i32); 2221218893Sdim ResTys.push_back(MVT::Other); 2222251662Sdim SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 2223221345Sdim cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1); 2224218893Sdim SuperReg = SDValue(VLdDup, 0); 2225218893Sdim 2226218893Sdim // Extract the subregisters. 2227210299Sed assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering"); 2228218893Sdim unsigned SubIdx = ARM::dsub_0; 2229210299Sed for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 2230210299Sed ReplaceUses(SDValue(N, Vec), 2231218893Sdim CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg)); 2232218893Sdim ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1)); 2233218893Sdim if (isUpdating) 2234218893Sdim ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2)); 2235276479Sdim return nullptr; 2236210299Sed} 2237198090Srdivacky 2238210299SedSDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, 2239210299Sed unsigned Opc) { 2240210299Sed assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range"); 2241261991Sdim SDLoc dl(N); 2242210299Sed EVT VT = N->getValueType(0); 2243210299Sed unsigned FirstTblReg = IsExt ? 2 : 1; 2244210299Sed 2245210299Sed // Form a REG_SEQUENCE to force register allocation. 2246210299Sed SDValue RegSeq; 2247210299Sed SDValue V0 = N->getOperand(FirstTblReg + 0); 2248210299Sed SDValue V1 = N->getOperand(FirstTblReg + 1); 2249210299Sed if (NumVecs == 2) 2250249423Sdim RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0); 2251210299Sed else { 2252210299Sed SDValue V2 = N->getOperand(FirstTblReg + 2); 2253218893Sdim // If it's a vtbl3, form a quad D-register and leave the last part as 2254210299Sed // an undef. 2255210299Sed SDValue V3 = (NumVecs == 3) 2256210299Sed ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 2257210299Sed : N->getOperand(FirstTblReg + 3); 2258249423Sdim RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0); 2259198090Srdivacky } 2260198090Srdivacky 2261210299Sed SmallVector<SDValue, 6> Ops; 2262210299Sed if (IsExt) 2263210299Sed Ops.push_back(N->getOperand(1)); 2264218893Sdim Ops.push_back(RegSeq); 2265210299Sed Ops.push_back(N->getOperand(FirstTblReg + NumVecs)); 2266210299Sed Ops.push_back(getAL(CurDAG)); // predicate 2267210299Sed Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register 2268251662Sdim return CurDAG->getMachineNode(Opc, dl, VT, Ops); 2269198090Srdivacky} 2270198090Srdivacky 2271202375SrdivackySDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, 2272207618Srdivacky bool isSigned) { 2273198090Srdivacky if (!Subtarget->hasV6T2Ops()) 2274276479Sdim return nullptr; 2275198090Srdivacky 2276249423Sdim unsigned Opc = isSigned 2277249423Sdim ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX) 2278207618Srdivacky : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX); 2279207618Srdivacky 2280207618Srdivacky // For unsigned extracts, check for a shift right and mask 2281207618Srdivacky unsigned And_imm = 0; 2282207618Srdivacky if (N->getOpcode() == ISD::AND) { 2283207618Srdivacky if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) { 2284207618Srdivacky 2285207618Srdivacky // The immediate is a mask of the low bits iff imm & (imm+1) == 0 2286207618Srdivacky if (And_imm & (And_imm + 1)) 2287276479Sdim return nullptr; 2288207618Srdivacky 2289207618Srdivacky unsigned Srl_imm = 0; 2290207618Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, 2291207618Srdivacky Srl_imm)) { 2292207618Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 2293207618Srdivacky 2294226633Sdim // Note: The width operand is encoded as width-1. 2295226633Sdim unsigned Width = CountTrailingOnes_32(And_imm) - 1; 2296207618Srdivacky unsigned LSB = Srl_imm; 2297249423Sdim 2298207618Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2299249423Sdim 2300249423Sdim if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) { 2301249423Sdim // It's cheaper to use a right shift to extract the top bits. 2302249423Sdim if (Subtarget->isThumb()) { 2303249423Sdim Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri; 2304249423Sdim SDValue Ops[] = { N->getOperand(0).getOperand(0), 2305249423Sdim CurDAG->getTargetConstant(LSB, MVT::i32), 2306249423Sdim getAL(CurDAG), Reg0, Reg0 }; 2307276479Sdim return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 2308249423Sdim } 2309249423Sdim 2310249423Sdim // ARM models shift instructions as MOVsi with shifter operand. 2311249423Sdim ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL); 2312249423Sdim SDValue ShOpc = 2313249423Sdim CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), 2314249423Sdim MVT::i32); 2315249423Sdim SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc, 2316249423Sdim getAL(CurDAG), Reg0, Reg0 }; 2317276479Sdim return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops); 2318249423Sdim } 2319249423Sdim 2320207618Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 2321207618Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 2322207618Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 2323276479Sdim getAL(CurDAG), Reg0 }; 2324276479Sdim return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 2325207618Srdivacky } 2326207618Srdivacky } 2327276479Sdim return nullptr; 2328207618Srdivacky } 2329207618Srdivacky 2330207618Srdivacky // Otherwise, we're looking for a shift of a shift 2331198090Srdivacky unsigned Shl_imm = 0; 2332202375Srdivacky if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 2333198090Srdivacky assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 2334198090Srdivacky unsigned Srl_imm = 0; 2335202375Srdivacky if (isInt32Immediate(N->getOperand(1), Srl_imm)) { 2336198090Srdivacky assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 2337226633Sdim // Note: The width operand is encoded as width-1. 2338226633Sdim unsigned Width = 32 - Srl_imm - 1; 2339198090Srdivacky int LSB = Srl_imm - Shl_imm; 2340198396Srdivacky if (LSB < 0) 2341276479Sdim return nullptr; 2342198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2343202375Srdivacky SDValue Ops[] = { N->getOperand(0).getOperand(0), 2344198090Srdivacky CurDAG->getTargetConstant(LSB, MVT::i32), 2345198090Srdivacky CurDAG->getTargetConstant(Width, MVT::i32), 2346198090Srdivacky getAL(CurDAG), Reg0 }; 2347276479Sdim return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 2348198090Srdivacky } 2349198090Srdivacky } 2350280031Sdim 2351280031Sdim if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) { 2352280031Sdim unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits(); 2353280031Sdim unsigned LSB = 0; 2354280031Sdim if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) && 2355280031Sdim !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB)) 2356280031Sdim return nullptr; 2357280031Sdim 2358280031Sdim if (LSB + Width > 32) 2359280031Sdim return nullptr; 2360280031Sdim 2361280031Sdim SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2362280031Sdim SDValue Ops[] = { N->getOperand(0).getOperand(0), 2363280031Sdim CurDAG->getTargetConstant(LSB, MVT::i32), 2364280031Sdim CurDAG->getTargetConstant(Width - 1, MVT::i32), 2365280031Sdim getAL(CurDAG), Reg0 }; 2366280031Sdim return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 2367280031Sdim } 2368280031Sdim 2369276479Sdim return nullptr; 2370198090Srdivacky} 2371198090Srdivacky 2372226633Sdim/// Target-specific DAG combining for ISD::XOR. 2373226633Sdim/// Target-independent combining lowers SELECT_CC nodes of the form 2374226633Sdim/// select_cc setg[ge] X, 0, X, -X 2375226633Sdim/// select_cc setgt X, -1, X, -X 2376226633Sdim/// select_cc setl[te] X, 0, -X, X 2377226633Sdim/// select_cc setlt X, 1, -X, X 2378226633Sdim/// which represent Integer ABS into: 2379226633Sdim/// Y = sra (X, size(X)-1); xor (add (X, Y), Y) 2380226633Sdim/// ARM instruction selection detects the latter and matches it to 2381226633Sdim/// ARM::ABS or ARM::t2ABS machine node. 2382226633SdimSDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){ 2383226633Sdim SDValue XORSrc0 = N->getOperand(0); 2384226633Sdim SDValue XORSrc1 = N->getOperand(1); 2385226633Sdim EVT VT = N->getValueType(0); 2386226633Sdim 2387226633Sdim if (Subtarget->isThumb1Only()) 2388276479Sdim return nullptr; 2389226633Sdim 2390239462Sdim if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA) 2391276479Sdim return nullptr; 2392226633Sdim 2393226633Sdim SDValue ADDSrc0 = XORSrc0.getOperand(0); 2394226633Sdim SDValue ADDSrc1 = XORSrc0.getOperand(1); 2395226633Sdim SDValue SRASrc0 = XORSrc1.getOperand(0); 2396226633Sdim SDValue SRASrc1 = XORSrc1.getOperand(1); 2397226633Sdim ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1); 2398226633Sdim EVT XType = SRASrc0.getValueType(); 2399226633Sdim unsigned Size = XType.getSizeInBits() - 1; 2400226633Sdim 2401239462Sdim if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 && 2402276479Sdim XType.isInteger() && SRAConstant != nullptr && 2403226633Sdim Size == SRAConstant->getZExtValue()) { 2404239462Sdim unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS; 2405226633Sdim return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0); 2406226633Sdim } 2407226633Sdim 2408276479Sdim return nullptr; 2409226633Sdim} 2410226633Sdim 2411208599SrdivackySDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) { 2412208599Srdivacky // The only time a CONCAT_VECTORS operation can have legal types is when 2413208599Srdivacky // two 64-bit vectors are concatenated to a 128-bit vector. 2414208599Srdivacky EVT VT = N->getValueType(0); 2415208599Srdivacky if (!VT.is128BitVector() || N->getNumOperands() != 2) 2416208599Srdivacky llvm_unreachable("unexpected CONCAT_VECTORS"); 2417249423Sdim return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1)); 2418208599Srdivacky} 2419208599Srdivacky 2420202375SrdivackySDNode *ARMDAGToDAGISel::Select(SDNode *N) { 2421261991Sdim SDLoc dl(N); 2422193323Sed 2423255804Sdim if (N->isMachineOpcode()) { 2424255804Sdim N->setNodeId(-1); 2425276479Sdim return nullptr; // Already selected. 2426255804Sdim } 2427193323Sed 2428193323Sed switch (N->getOpcode()) { 2429193323Sed default: break; 2430249423Sdim case ISD::INLINEASM: { 2431249423Sdim SDNode *ResNode = SelectInlineAsm(N); 2432249423Sdim if (ResNode) 2433249423Sdim return ResNode; 2434249423Sdim break; 2435249423Sdim } 2436226633Sdim case ISD::XOR: { 2437226633Sdim // Select special operations if XOR node forms integer ABS pattern 2438226633Sdim SDNode *ResNode = SelectABSOp(N); 2439226633Sdim if (ResNode) 2440226633Sdim return ResNode; 2441226633Sdim // Other cases are autogenerated. 2442226633Sdim break; 2443226633Sdim } 2444193323Sed case ISD::Constant: { 2445193323Sed unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 2446193323Sed bool UseCP = true; 2447276479Sdim if (Subtarget->useMovt(*MF)) 2448198090Srdivacky // Thumb2-aware targets have the MOVT instruction, so all immediates can 2449198090Srdivacky // be done with MOV + MOVT, at worst. 2450276479Sdim UseCP = false; 2451198090Srdivacky else { 2452198090Srdivacky if (Subtarget->isThumb()) { 2453276479Sdim UseCP = (Val > 255 && // MOV 2454276479Sdim ~Val > 255 && // MOV + MVN 2455276479Sdim !ARM_AM::isThumbImmShiftedVal(Val) && // MOV + LSL 2456276479Sdim !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW 2457198090Srdivacky } else 2458276479Sdim UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 2459276479Sdim ARM_AM::getSOImmVal(~Val) == -1 && // MVN 2460276479Sdim !ARM_AM::isSOImmTwoPartVal(Val) && // two instrs. 2461276479Sdim !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW 2462198090Srdivacky } 2463198090Srdivacky 2464193323Sed if (UseCP) { 2465280031Sdim SDValue CPIdx = CurDAG->getTargetConstantPool( 2466280031Sdim ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val), 2467280031Sdim TLI->getPointerTy()); 2468193323Sed 2469193323Sed SDNode *ResNode; 2470276479Sdim if (Subtarget->isThumb()) { 2471207618Srdivacky SDValue Pred = getAL(CurDAG); 2472198090Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2473198090Srdivacky SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 2474218893Sdim ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other, 2475251662Sdim Ops); 2476198090Srdivacky } else { 2477193323Sed SDValue Ops[] = { 2478198090Srdivacky CPIdx, 2479193323Sed CurDAG->getTargetConstant(0, MVT::i32), 2480193323Sed getAL(CurDAG), 2481193323Sed CurDAG->getRegister(0, MVT::i32), 2482193323Sed CurDAG->getEntryNode() 2483193323Sed }; 2484198090Srdivacky ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 2485251662Sdim Ops); 2486193323Sed } 2487202375Srdivacky ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 2488276479Sdim return nullptr; 2489193323Sed } 2490198090Srdivacky 2491193323Sed // Other cases are autogenerated. 2492193323Sed break; 2493193323Sed } 2494193323Sed case ISD::FrameIndex: { 2495193323Sed // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 2496193323Sed int FI = cast<FrameIndexSDNode>(N)->getIndex(); 2497280031Sdim SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy()); 2498198090Srdivacky if (Subtarget->isThumb1Only()) { 2499280031Sdim return CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI, 2500280031Sdim CurDAG->getTargetConstant(0, MVT::i32)); 2501193323Sed } else { 2502198090Srdivacky unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 2503198090Srdivacky ARM::t2ADDri : ARM::ADDri); 2504193323Sed SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 2505198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 2506198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 2507276479Sdim return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 2508193323Sed } 2509193323Sed } 2510198090Srdivacky case ISD::SRL: 2511207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) 2512198090Srdivacky return I; 2513193323Sed break; 2514280031Sdim case ISD::SIGN_EXTEND_INREG: 2515198090Srdivacky case ISD::SRA: 2516207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true)) 2517198090Srdivacky return I; 2518198090Srdivacky break; 2519193323Sed case ISD::MUL: 2520198090Srdivacky if (Subtarget->isThumb1Only()) 2521193323Sed break; 2522202375Srdivacky if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 2523193323Sed unsigned RHSV = C->getZExtValue(); 2524193323Sed if (!RHSV) break; 2525193323Sed if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 2526198090Srdivacky unsigned ShImm = Log2_32(RHSV-1); 2527198090Srdivacky if (ShImm >= 32) 2528198090Srdivacky break; 2529202375Srdivacky SDValue V = N->getOperand(0); 2530198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 2531198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 2532198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2533198090Srdivacky if (Subtarget->isThumb()) { 2534198090Srdivacky SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 2535276479Sdim return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops); 2536198090Srdivacky } else { 2537198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 2538276479Sdim return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops); 2539198090Srdivacky } 2540193323Sed } 2541193323Sed if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 2542198090Srdivacky unsigned ShImm = Log2_32(RHSV+1); 2543198090Srdivacky if (ShImm >= 32) 2544198090Srdivacky break; 2545202375Srdivacky SDValue V = N->getOperand(0); 2546198090Srdivacky ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 2547198090Srdivacky SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 2548198090Srdivacky SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2549198090Srdivacky if (Subtarget->isThumb()) { 2550210299Sed SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 2551276479Sdim return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops); 2552198090Srdivacky } else { 2553198090Srdivacky SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 2554276479Sdim return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops); 2555198090Srdivacky } 2556193323Sed } 2557193323Sed } 2558193323Sed break; 2559198396Srdivacky case ISD::AND: { 2560207618Srdivacky // Check for unsigned bitfield extract 2561207618Srdivacky if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) 2562207618Srdivacky return I; 2563207618Srdivacky 2564198396Srdivacky // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 2565198396Srdivacky // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 2566198396Srdivacky // are entirely contributed by c2 and lower 16-bits are entirely contributed 2567198396Srdivacky // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 2568198396Srdivacky // Select it to: "movt x, ((c1 & 0xffff) >> 16) 2569202375Srdivacky EVT VT = N->getValueType(0); 2570198396Srdivacky if (VT != MVT::i32) 2571198396Srdivacky break; 2572198396Srdivacky unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 2573198396Srdivacky ? ARM::t2MOVTi16 2574198396Srdivacky : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 2575198396Srdivacky if (!Opc) 2576198396Srdivacky break; 2577202375Srdivacky SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 2578198396Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 2579198396Srdivacky if (!N1C) 2580198396Srdivacky break; 2581198396Srdivacky if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 2582198396Srdivacky SDValue N2 = N0.getOperand(1); 2583198396Srdivacky ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 2584198396Srdivacky if (!N2C) 2585198396Srdivacky break; 2586198396Srdivacky unsigned N1CVal = N1C->getZExtValue(); 2587198396Srdivacky unsigned N2CVal = N2C->getZExtValue(); 2588198396Srdivacky if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 2589198396Srdivacky (N1CVal & 0xffffU) == 0xffffU && 2590198396Srdivacky (N2CVal & 0xffffU) == 0x0U) { 2591198396Srdivacky SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 2592198396Srdivacky MVT::i32); 2593198396Srdivacky SDValue Ops[] = { N0.getOperand(0), Imm16, 2594198396Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 2595251662Sdim return CurDAG->getMachineNode(Opc, dl, VT, Ops); 2596198396Srdivacky } 2597198396Srdivacky } 2598198396Srdivacky break; 2599198396Srdivacky } 2600199481Srdivacky case ARMISD::VMOVRRD: 2601199481Srdivacky return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, 2602202375Srdivacky N->getOperand(0), getAL(CurDAG), 2603198090Srdivacky CurDAG->getRegister(0, MVT::i32)); 2604193323Sed case ISD::UMUL_LOHI: { 2605198090Srdivacky if (Subtarget->isThumb1Only()) 2606198090Srdivacky break; 2607198090Srdivacky if (Subtarget->isThumb()) { 2608202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 2609251662Sdim getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 2610251662Sdim return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops); 2611198090Srdivacky } else { 2612202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 2613198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 2614198090Srdivacky CurDAG->getRegister(0, MVT::i32) }; 2615218893Sdim return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? 2616218893Sdim ARM::UMULL : ARM::UMULLv5, 2617251662Sdim dl, MVT::i32, MVT::i32, Ops); 2618198090Srdivacky } 2619193323Sed } 2620193323Sed case ISD::SMUL_LOHI: { 2621198090Srdivacky if (Subtarget->isThumb1Only()) 2622198090Srdivacky break; 2623198090Srdivacky if (Subtarget->isThumb()) { 2624202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 2625198090Srdivacky getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 2626251662Sdim return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops); 2627198090Srdivacky } else { 2628202375Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 2629193323Sed getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 2630193323Sed CurDAG->getRegister(0, MVT::i32) }; 2631218893Sdim return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? 2632218893Sdim ARM::SMULL : ARM::SMULLv5, 2633251662Sdim dl, MVT::i32, MVT::i32, Ops); 2634198090Srdivacky } 2635193323Sed } 2636243830Sdim case ARMISD::UMLAL:{ 2637243830Sdim if (Subtarget->isThumb()) { 2638243830Sdim SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 2639243830Sdim N->getOperand(3), getAL(CurDAG), 2640243830Sdim CurDAG->getRegister(0, MVT::i32)}; 2641251662Sdim return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops); 2642243830Sdim }else{ 2643243830Sdim SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 2644243830Sdim N->getOperand(3), getAL(CurDAG), 2645243830Sdim CurDAG->getRegister(0, MVT::i32), 2646243830Sdim CurDAG->getRegister(0, MVT::i32) }; 2647243830Sdim return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? 2648243830Sdim ARM::UMLAL : ARM::UMLALv5, 2649251662Sdim dl, MVT::i32, MVT::i32, Ops); 2650243830Sdim } 2651243830Sdim } 2652243830Sdim case ARMISD::SMLAL:{ 2653243830Sdim if (Subtarget->isThumb()) { 2654243830Sdim SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 2655243830Sdim N->getOperand(3), getAL(CurDAG), 2656243830Sdim CurDAG->getRegister(0, MVT::i32)}; 2657251662Sdim return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops); 2658243830Sdim }else{ 2659243830Sdim SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 2660243830Sdim N->getOperand(3), getAL(CurDAG), 2661243830Sdim CurDAG->getRegister(0, MVT::i32), 2662243830Sdim CurDAG->getRegister(0, MVT::i32) }; 2663243830Sdim return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? 2664243830Sdim ARM::SMLAL : ARM::SMLALv5, 2665251662Sdim dl, MVT::i32, MVT::i32, Ops); 2666243830Sdim } 2667243830Sdim } 2668193323Sed case ISD::LOAD: { 2669276479Sdim SDNode *ResNode = nullptr; 2670198090Srdivacky if (Subtarget->isThumb() && Subtarget->hasThumb2()) 2671202375Srdivacky ResNode = SelectT2IndexedLoad(N); 2672195340Sed else 2673202375Srdivacky ResNode = SelectARMIndexedLoad(N); 2674195340Sed if (ResNode) 2675195340Sed return ResNode; 2676193323Sed // Other cases are autogenerated. 2677193323Sed break; 2678193323Sed } 2679193323Sed case ARMISD::BRCOND: { 2680193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 2681193323Sed // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 2682193323Sed // Pattern complexity = 6 cost = 1 size = 0 2683193323Sed 2684193323Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 2685193323Sed // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 2686193323Sed // Pattern complexity = 6 cost = 1 size = 0 2687193323Sed 2688195340Sed // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 2689195340Sed // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 2690195340Sed // Pattern complexity = 6 cost = 1 size = 0 2691195340Sed 2692198090Srdivacky unsigned Opc = Subtarget->isThumb() ? 2693195340Sed ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 2694202375Srdivacky SDValue Chain = N->getOperand(0); 2695202375Srdivacky SDValue N1 = N->getOperand(1); 2696202375Srdivacky SDValue N2 = N->getOperand(2); 2697202375Srdivacky SDValue N3 = N->getOperand(3); 2698202375Srdivacky SDValue InFlag = N->getOperand(4); 2699193323Sed assert(N1.getOpcode() == ISD::BasicBlock); 2700193323Sed assert(N2.getOpcode() == ISD::Constant); 2701193323Sed assert(N3.getOpcode() == ISD::Register); 2702193323Sed 2703193323Sed SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 2704193323Sed cast<ConstantSDNode>(N2)->getZExtValue()), 2705193323Sed MVT::i32); 2706193323Sed SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 2707198090Srdivacky SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 2708251662Sdim MVT::Glue, Ops); 2709193323Sed Chain = SDValue(ResNode, 0); 2710202375Srdivacky if (N->getNumValues() == 2) { 2711193323Sed InFlag = SDValue(ResNode, 1); 2712202375Srdivacky ReplaceUses(SDValue(N, 1), InFlag); 2713193323Sed } 2714202375Srdivacky ReplaceUses(SDValue(N, 0), 2715199511Srdivacky SDValue(Chain.getNode(), Chain.getResNo())); 2716276479Sdim return nullptr; 2717193323Sed } 2718198090Srdivacky case ARMISD::VZIP: { 2719198090Srdivacky unsigned Opc = 0; 2720198090Srdivacky EVT VT = N->getValueType(0); 2721198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2722276479Sdim default: return nullptr; 2723198090Srdivacky case MVT::v8i8: Opc = ARM::VZIPd8; break; 2724198090Srdivacky case MVT::v4i16: Opc = ARM::VZIPd16; break; 2725198090Srdivacky case MVT::v2f32: 2726234353Sdim // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm. 2727234353Sdim case MVT::v2i32: Opc = ARM::VTRNd32; break; 2728198090Srdivacky case MVT::v16i8: Opc = ARM::VZIPq8; break; 2729198090Srdivacky case MVT::v8i16: Opc = ARM::VZIPq16; break; 2730198090Srdivacky case MVT::v4f32: 2731198090Srdivacky case MVT::v4i32: Opc = ARM::VZIPq32; break; 2732193323Sed } 2733207618Srdivacky SDValue Pred = getAL(CurDAG); 2734199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2735199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2736251662Sdim return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops); 2737198090Srdivacky } 2738198090Srdivacky case ARMISD::VUZP: { 2739198090Srdivacky unsigned Opc = 0; 2740198090Srdivacky EVT VT = N->getValueType(0); 2741198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2742276479Sdim default: return nullptr; 2743198090Srdivacky case MVT::v8i8: Opc = ARM::VUZPd8; break; 2744198090Srdivacky case MVT::v4i16: Opc = ARM::VUZPd16; break; 2745198090Srdivacky case MVT::v2f32: 2746234353Sdim // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm. 2747234353Sdim case MVT::v2i32: Opc = ARM::VTRNd32; break; 2748198090Srdivacky case MVT::v16i8: Opc = ARM::VUZPq8; break; 2749198090Srdivacky case MVT::v8i16: Opc = ARM::VUZPq16; break; 2750198090Srdivacky case MVT::v4f32: 2751198090Srdivacky case MVT::v4i32: Opc = ARM::VUZPq32; break; 2752193323Sed } 2753207618Srdivacky SDValue Pred = getAL(CurDAG); 2754199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2755199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2756251662Sdim return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops); 2757198090Srdivacky } 2758198090Srdivacky case ARMISD::VTRN: { 2759198090Srdivacky unsigned Opc = 0; 2760198090Srdivacky EVT VT = N->getValueType(0); 2761198090Srdivacky switch (VT.getSimpleVT().SimpleTy) { 2762276479Sdim default: return nullptr; 2763198090Srdivacky case MVT::v8i8: Opc = ARM::VTRNd8; break; 2764198090Srdivacky case MVT::v4i16: Opc = ARM::VTRNd16; break; 2765198090Srdivacky case MVT::v2f32: 2766198090Srdivacky case MVT::v2i32: Opc = ARM::VTRNd32; break; 2767198090Srdivacky case MVT::v16i8: Opc = ARM::VTRNq8; break; 2768198090Srdivacky case MVT::v8i16: Opc = ARM::VTRNq16; break; 2769198090Srdivacky case MVT::v4f32: 2770198090Srdivacky case MVT::v4i32: Opc = ARM::VTRNq32; break; 2771193323Sed } 2772207618Srdivacky SDValue Pred = getAL(CurDAG); 2773199989Srdivacky SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2774199989Srdivacky SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 2775251662Sdim return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops); 2776193323Sed } 2777210299Sed case ARMISD::BUILD_VECTOR: { 2778210299Sed EVT VecVT = N->getValueType(0); 2779210299Sed EVT EltVT = VecVT.getVectorElementType(); 2780210299Sed unsigned NumElts = VecVT.getVectorNumElements(); 2781218893Sdim if (EltVT == MVT::f64) { 2782210299Sed assert(NumElts == 2 && "unexpected type for BUILD_VECTOR"); 2783249423Sdim return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)); 2784210299Sed } 2785218893Sdim assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR"); 2786210299Sed if (NumElts == 2) 2787249423Sdim return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)); 2788210299Sed assert(NumElts == 4 && "unexpected type for BUILD_VECTOR"); 2789249423Sdim return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1), 2790210299Sed N->getOperand(2), N->getOperand(3)); 2791210299Sed } 2792194710Sed 2793218893Sdim case ARMISD::VLD2DUP: { 2794239462Sdim static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16, 2795239462Sdim ARM::VLD2DUPd32 }; 2796218893Sdim return SelectVLDDup(N, false, 2, Opcodes); 2797218893Sdim } 2798218893Sdim 2799218893Sdim case ARMISD::VLD3DUP: { 2800239462Sdim static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo, 2801239462Sdim ARM::VLD3DUPd16Pseudo, 2802239462Sdim ARM::VLD3DUPd32Pseudo }; 2803218893Sdim return SelectVLDDup(N, false, 3, Opcodes); 2804218893Sdim } 2805218893Sdim 2806218893Sdim case ARMISD::VLD4DUP: { 2807239462Sdim static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo, 2808239462Sdim ARM::VLD4DUPd16Pseudo, 2809239462Sdim ARM::VLD4DUPd32Pseudo }; 2810218893Sdim return SelectVLDDup(N, false, 4, Opcodes); 2811218893Sdim } 2812218893Sdim 2813218893Sdim case ARMISD::VLD2DUP_UPD: { 2814239462Sdim static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed, 2815239462Sdim ARM::VLD2DUPd16wb_fixed, 2816239462Sdim ARM::VLD2DUPd32wb_fixed }; 2817218893Sdim return SelectVLDDup(N, true, 2, Opcodes); 2818218893Sdim } 2819218893Sdim 2820218893Sdim case ARMISD::VLD3DUP_UPD: { 2821239462Sdim static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD, 2822239462Sdim ARM::VLD3DUPd16Pseudo_UPD, 2823239462Sdim ARM::VLD3DUPd32Pseudo_UPD }; 2824218893Sdim return SelectVLDDup(N, true, 3, Opcodes); 2825218893Sdim } 2826218893Sdim 2827218893Sdim case ARMISD::VLD4DUP_UPD: { 2828239462Sdim static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD, 2829239462Sdim ARM::VLD4DUPd16Pseudo_UPD, 2830239462Sdim ARM::VLD4DUPd32Pseudo_UPD }; 2831218893Sdim return SelectVLDDup(N, true, 4, Opcodes); 2832218893Sdim } 2833218893Sdim 2834218893Sdim case ARMISD::VLD1_UPD: { 2835239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed, 2836239462Sdim ARM::VLD1d16wb_fixed, 2837239462Sdim ARM::VLD1d32wb_fixed, 2838239462Sdim ARM::VLD1d64wb_fixed }; 2839239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed, 2840239462Sdim ARM::VLD1q16wb_fixed, 2841239462Sdim ARM::VLD1q32wb_fixed, 2842239462Sdim ARM::VLD1q64wb_fixed }; 2843276479Sdim return SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr); 2844218893Sdim } 2845218893Sdim 2846218893Sdim case ARMISD::VLD2_UPD: { 2847239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed, 2848239462Sdim ARM::VLD2d16wb_fixed, 2849239462Sdim ARM::VLD2d32wb_fixed, 2850239462Sdim ARM::VLD1q64wb_fixed}; 2851239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed, 2852239462Sdim ARM::VLD2q16PseudoWB_fixed, 2853239462Sdim ARM::VLD2q32PseudoWB_fixed }; 2854276479Sdim return SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr); 2855218893Sdim } 2856218893Sdim 2857218893Sdim case ARMISD::VLD3_UPD: { 2858239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD, 2859239462Sdim ARM::VLD3d16Pseudo_UPD, 2860239462Sdim ARM::VLD3d32Pseudo_UPD, 2861265925Sdim ARM::VLD1d64TPseudoWB_fixed}; 2862239462Sdim static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, 2863239462Sdim ARM::VLD3q16Pseudo_UPD, 2864239462Sdim ARM::VLD3q32Pseudo_UPD }; 2865239462Sdim static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD, 2866239462Sdim ARM::VLD3q16oddPseudo_UPD, 2867239462Sdim ARM::VLD3q32oddPseudo_UPD }; 2868218893Sdim return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 2869218893Sdim } 2870218893Sdim 2871218893Sdim case ARMISD::VLD4_UPD: { 2872239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD, 2873239462Sdim ARM::VLD4d16Pseudo_UPD, 2874239462Sdim ARM::VLD4d32Pseudo_UPD, 2875265925Sdim ARM::VLD1d64QPseudoWB_fixed}; 2876239462Sdim static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, 2877239462Sdim ARM::VLD4q16Pseudo_UPD, 2878239462Sdim ARM::VLD4q32Pseudo_UPD }; 2879239462Sdim static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD, 2880239462Sdim ARM::VLD4q16oddPseudo_UPD, 2881239462Sdim ARM::VLD4q32oddPseudo_UPD }; 2882218893Sdim return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 2883218893Sdim } 2884218893Sdim 2885218893Sdim case ARMISD::VLD2LN_UPD: { 2886239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD, 2887239462Sdim ARM::VLD2LNd16Pseudo_UPD, 2888239462Sdim ARM::VLD2LNd32Pseudo_UPD }; 2889239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD, 2890239462Sdim ARM::VLD2LNq32Pseudo_UPD }; 2891218893Sdim return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes); 2892218893Sdim } 2893218893Sdim 2894218893Sdim case ARMISD::VLD3LN_UPD: { 2895239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD, 2896239462Sdim ARM::VLD3LNd16Pseudo_UPD, 2897239462Sdim ARM::VLD3LNd32Pseudo_UPD }; 2898239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD, 2899239462Sdim ARM::VLD3LNq32Pseudo_UPD }; 2900218893Sdim return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes); 2901218893Sdim } 2902218893Sdim 2903218893Sdim case ARMISD::VLD4LN_UPD: { 2904239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD, 2905239462Sdim ARM::VLD4LNd16Pseudo_UPD, 2906239462Sdim ARM::VLD4LNd32Pseudo_UPD }; 2907239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD, 2908239462Sdim ARM::VLD4LNq32Pseudo_UPD }; 2909218893Sdim return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes); 2910218893Sdim } 2911218893Sdim 2912218893Sdim case ARMISD::VST1_UPD: { 2913239462Sdim static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed, 2914239462Sdim ARM::VST1d16wb_fixed, 2915239462Sdim ARM::VST1d32wb_fixed, 2916239462Sdim ARM::VST1d64wb_fixed }; 2917239462Sdim static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed, 2918239462Sdim ARM::VST1q16wb_fixed, 2919239462Sdim ARM::VST1q32wb_fixed, 2920239462Sdim ARM::VST1q64wb_fixed }; 2921276479Sdim return SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr); 2922218893Sdim } 2923218893Sdim 2924218893Sdim case ARMISD::VST2_UPD: { 2925239462Sdim static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed, 2926239462Sdim ARM::VST2d16wb_fixed, 2927239462Sdim ARM::VST2d32wb_fixed, 2928239462Sdim ARM::VST1q64wb_fixed}; 2929239462Sdim static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed, 2930239462Sdim ARM::VST2q16PseudoWB_fixed, 2931239462Sdim ARM::VST2q32PseudoWB_fixed }; 2932276479Sdim return SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr); 2933218893Sdim } 2934218893Sdim 2935218893Sdim case ARMISD::VST3_UPD: { 2936239462Sdim static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD, 2937239462Sdim ARM::VST3d16Pseudo_UPD, 2938239462Sdim ARM::VST3d32Pseudo_UPD, 2939239462Sdim ARM::VST1d64TPseudoWB_fixed}; 2940239462Sdim static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, 2941239462Sdim ARM::VST3q16Pseudo_UPD, 2942239462Sdim ARM::VST3q32Pseudo_UPD }; 2943239462Sdim static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD, 2944239462Sdim ARM::VST3q16oddPseudo_UPD, 2945239462Sdim ARM::VST3q32oddPseudo_UPD }; 2946218893Sdim return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 2947218893Sdim } 2948218893Sdim 2949218893Sdim case ARMISD::VST4_UPD: { 2950239462Sdim static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD, 2951239462Sdim ARM::VST4d16Pseudo_UPD, 2952239462Sdim ARM::VST4d32Pseudo_UPD, 2953239462Sdim ARM::VST1d64QPseudoWB_fixed}; 2954239462Sdim static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD, 2955239462Sdim ARM::VST4q16Pseudo_UPD, 2956239462Sdim ARM::VST4q32Pseudo_UPD }; 2957239462Sdim static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD, 2958239462Sdim ARM::VST4q16oddPseudo_UPD, 2959239462Sdim ARM::VST4q32oddPseudo_UPD }; 2960218893Sdim return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 2961218893Sdim } 2962218893Sdim 2963218893Sdim case ARMISD::VST2LN_UPD: { 2964239462Sdim static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD, 2965239462Sdim ARM::VST2LNd16Pseudo_UPD, 2966239462Sdim ARM::VST2LNd32Pseudo_UPD }; 2967239462Sdim static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD, 2968239462Sdim ARM::VST2LNq32Pseudo_UPD }; 2969218893Sdim return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes); 2970218893Sdim } 2971218893Sdim 2972218893Sdim case ARMISD::VST3LN_UPD: { 2973239462Sdim static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD, 2974239462Sdim ARM::VST3LNd16Pseudo_UPD, 2975239462Sdim ARM::VST3LNd32Pseudo_UPD }; 2976239462Sdim static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD, 2977239462Sdim ARM::VST3LNq32Pseudo_UPD }; 2978218893Sdim return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes); 2979218893Sdim } 2980218893Sdim 2981218893Sdim case ARMISD::VST4LN_UPD: { 2982239462Sdim static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD, 2983239462Sdim ARM::VST4LNd16Pseudo_UPD, 2984239462Sdim ARM::VST4LNd32Pseudo_UPD }; 2985239462Sdim static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD, 2986239462Sdim ARM::VST4LNq32Pseudo_UPD }; 2987218893Sdim return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes); 2988218893Sdim } 2989218893Sdim 2990198090Srdivacky case ISD::INTRINSIC_VOID: 2991198090Srdivacky case ISD::INTRINSIC_W_CHAIN: { 2992198090Srdivacky unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 2993198090Srdivacky switch (IntNo) { 2994198090Srdivacky default: 2995198090Srdivacky break; 2996194710Sed 2997276479Sdim case Intrinsic::arm_ldaexd: 2998223017Sdim case Intrinsic::arm_ldrexd: { 2999261991Sdim SDLoc dl(N); 3000223017Sdim SDValue Chain = N->getOperand(0); 3001276479Sdim SDValue MemAddr = N->getOperand(2); 3002249423Sdim bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2(); 3003223017Sdim 3004276479Sdim bool IsAcquire = IntNo == Intrinsic::arm_ldaexd; 3005276479Sdim unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD) 3006276479Sdim : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD); 3007276479Sdim 3008223017Sdim // arm_ldrexd returns a i64 value in {i32, i32} 3009223017Sdim std::vector<EVT> ResTys; 3010249423Sdim if (isThumb) { 3011249423Sdim ResTys.push_back(MVT::i32); 3012249423Sdim ResTys.push_back(MVT::i32); 3013249423Sdim } else 3014249423Sdim ResTys.push_back(MVT::Untyped); 3015223017Sdim ResTys.push_back(MVT::Other); 3016223017Sdim 3017249423Sdim // Place arguments in the right order. 3018223017Sdim SmallVector<SDValue, 7> Ops; 3019223017Sdim Ops.push_back(MemAddr); 3020223017Sdim Ops.push_back(getAL(CurDAG)); 3021223017Sdim Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 3022223017Sdim Ops.push_back(Chain); 3023251662Sdim SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops); 3024223017Sdim // Transfer memoperands. 3025223017Sdim MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 3026223017Sdim MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 3027223017Sdim cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1); 3028223017Sdim 3029223017Sdim // Remap uses. 3030249423Sdim SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1); 3031223017Sdim if (!SDValue(N, 0).use_empty()) { 3032249423Sdim SDValue Result; 3033249423Sdim if (isThumb) 3034249423Sdim Result = SDValue(Ld, 0); 3035249423Sdim else { 3036249423Sdim SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32); 3037249423Sdim SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 3038249423Sdim dl, MVT::i32, SDValue(Ld, 0), SubRegIdx); 3039249423Sdim Result = SDValue(ResNode,0); 3040249423Sdim } 3041223017Sdim ReplaceUses(SDValue(N, 0), Result); 3042223017Sdim } 3043223017Sdim if (!SDValue(N, 1).use_empty()) { 3044249423Sdim SDValue Result; 3045249423Sdim if (isThumb) 3046249423Sdim Result = SDValue(Ld, 1); 3047249423Sdim else { 3048249423Sdim SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32); 3049249423Sdim SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 3050249423Sdim dl, MVT::i32, SDValue(Ld, 0), SubRegIdx); 3051249423Sdim Result = SDValue(ResNode,0); 3052249423Sdim } 3053223017Sdim ReplaceUses(SDValue(N, 1), Result); 3054223017Sdim } 3055249423Sdim ReplaceUses(SDValue(N, 2), OutChain); 3056276479Sdim return nullptr; 3057223017Sdim } 3058276479Sdim case Intrinsic::arm_stlexd: 3059223017Sdim case Intrinsic::arm_strexd: { 3060261991Sdim SDLoc dl(N); 3061223017Sdim SDValue Chain = N->getOperand(0); 3062223017Sdim SDValue Val0 = N->getOperand(2); 3063223017Sdim SDValue Val1 = N->getOperand(3); 3064223017Sdim SDValue MemAddr = N->getOperand(4); 3065223017Sdim 3066223017Sdim // Store exclusive double return a i32 value which is the return status 3067223017Sdim // of the issued store. 3068249423Sdim EVT ResTys[] = { MVT::i32, MVT::Other }; 3069223017Sdim 3070249423Sdim bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2(); 3071249423Sdim // Place arguments in the right order. 3072223017Sdim SmallVector<SDValue, 7> Ops; 3073249423Sdim if (isThumb) { 3074249423Sdim Ops.push_back(Val0); 3075249423Sdim Ops.push_back(Val1); 3076249423Sdim } else 3077249423Sdim // arm_strexd uses GPRPair. 3078249423Sdim Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0)); 3079223017Sdim Ops.push_back(MemAddr); 3080223017Sdim Ops.push_back(getAL(CurDAG)); 3081223017Sdim Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 3082223017Sdim Ops.push_back(Chain); 3083223017Sdim 3084276479Sdim bool IsRelease = IntNo == Intrinsic::arm_stlexd; 3085276479Sdim unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD) 3086276479Sdim : (IsRelease ? ARM::STLEXD : ARM::STREXD); 3087223017Sdim 3088251662Sdim SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops); 3089223017Sdim // Transfer memoperands. 3090223017Sdim MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 3091223017Sdim MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 3092223017Sdim cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1); 3093223017Sdim 3094223017Sdim return St; 3095223017Sdim } 3096223017Sdim 3097206083Srdivacky case Intrinsic::arm_neon_vld1: { 3098239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16, 3099239462Sdim ARM::VLD1d32, ARM::VLD1d64 }; 3100239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16, 3101239462Sdim ARM::VLD1q32, ARM::VLD1q64}; 3102276479Sdim return SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr); 3103206083Srdivacky } 3104206083Srdivacky 3105198090Srdivacky case Intrinsic::arm_neon_vld2: { 3106239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 3107239462Sdim ARM::VLD2d32, ARM::VLD1q64 }; 3108239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo, 3109239462Sdim ARM::VLD2q32Pseudo }; 3110276479Sdim return SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr); 3111198090Srdivacky } 3112194710Sed 3113198090Srdivacky case Intrinsic::arm_neon_vld3: { 3114239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo, 3115239462Sdim ARM::VLD3d16Pseudo, 3116239462Sdim ARM::VLD3d32Pseudo, 3117239462Sdim ARM::VLD1d64TPseudo }; 3118239462Sdim static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, 3119239462Sdim ARM::VLD3q16Pseudo_UPD, 3120239462Sdim ARM::VLD3q32Pseudo_UPD }; 3121239462Sdim static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo, 3122239462Sdim ARM::VLD3q16oddPseudo, 3123239462Sdim ARM::VLD3q32oddPseudo }; 3124218893Sdim return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 3125198090Srdivacky } 3126198090Srdivacky 3127198090Srdivacky case Intrinsic::arm_neon_vld4: { 3128239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo, 3129239462Sdim ARM::VLD4d16Pseudo, 3130239462Sdim ARM::VLD4d32Pseudo, 3131239462Sdim ARM::VLD1d64QPseudo }; 3132239462Sdim static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, 3133239462Sdim ARM::VLD4q16Pseudo_UPD, 3134239462Sdim ARM::VLD4q32Pseudo_UPD }; 3135239462Sdim static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo, 3136239462Sdim ARM::VLD4q16oddPseudo, 3137239462Sdim ARM::VLD4q32oddPseudo }; 3138218893Sdim return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 3139198090Srdivacky } 3140198090Srdivacky 3141198090Srdivacky case Intrinsic::arm_neon_vld2lane: { 3142239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo, 3143239462Sdim ARM::VLD2LNd16Pseudo, 3144239462Sdim ARM::VLD2LNd32Pseudo }; 3145239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo, 3146239462Sdim ARM::VLD2LNq32Pseudo }; 3147218893Sdim return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes); 3148198090Srdivacky } 3149198090Srdivacky 3150198090Srdivacky case Intrinsic::arm_neon_vld3lane: { 3151239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo, 3152239462Sdim ARM::VLD3LNd16Pseudo, 3153239462Sdim ARM::VLD3LNd32Pseudo }; 3154239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo, 3155239462Sdim ARM::VLD3LNq32Pseudo }; 3156218893Sdim return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes); 3157198090Srdivacky } 3158198090Srdivacky 3159198090Srdivacky case Intrinsic::arm_neon_vld4lane: { 3160239462Sdim static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo, 3161239462Sdim ARM::VLD4LNd16Pseudo, 3162239462Sdim ARM::VLD4LNd32Pseudo }; 3163239462Sdim static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo, 3164239462Sdim ARM::VLD4LNq32Pseudo }; 3165218893Sdim return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes); 3166198090Srdivacky } 3167198090Srdivacky 3168206083Srdivacky case Intrinsic::arm_neon_vst1: { 3169239462Sdim static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16, 3170239462Sdim ARM::VST1d32, ARM::VST1d64 }; 3171239462Sdim static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16, 3172239462Sdim ARM::VST1q32, ARM::VST1q64 }; 3173276479Sdim return SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr); 3174206083Srdivacky } 3175206083Srdivacky 3176198090Srdivacky case Intrinsic::arm_neon_vst2: { 3177239462Sdim static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, 3178239462Sdim ARM::VST2d32, ARM::VST1q64 }; 3179239462Sdim static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo, 3180239462Sdim ARM::VST2q32Pseudo }; 3181276479Sdim return SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr); 3182198090Srdivacky } 3183194710Sed 3184198090Srdivacky case Intrinsic::arm_neon_vst3: { 3185239462Sdim static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo, 3186239462Sdim ARM::VST3d16Pseudo, 3187239462Sdim ARM::VST3d32Pseudo, 3188239462Sdim ARM::VST1d64TPseudo }; 3189239462Sdim static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, 3190239462Sdim ARM::VST3q16Pseudo_UPD, 3191239462Sdim ARM::VST3q32Pseudo_UPD }; 3192239462Sdim static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo, 3193239462Sdim ARM::VST3q16oddPseudo, 3194239462Sdim ARM::VST3q32oddPseudo }; 3195218893Sdim return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 3196194710Sed } 3197194710Sed 3198198090Srdivacky case Intrinsic::arm_neon_vst4: { 3199239462Sdim static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo, 3200239462Sdim ARM::VST4d16Pseudo, 3201239462Sdim ARM::VST4d32Pseudo, 3202239462Sdim ARM::VST1d64QPseudo }; 3203239462Sdim static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD, 3204239462Sdim ARM::VST4q16Pseudo_UPD, 3205239462Sdim ARM::VST4q32Pseudo_UPD }; 3206239462Sdim static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo, 3207239462Sdim ARM::VST4q16oddPseudo, 3208239462Sdim ARM::VST4q32oddPseudo }; 3209218893Sdim return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 3210198090Srdivacky } 3211198090Srdivacky 3212198090Srdivacky case Intrinsic::arm_neon_vst2lane: { 3213239462Sdim static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo, 3214239462Sdim ARM::VST2LNd16Pseudo, 3215239462Sdim ARM::VST2LNd32Pseudo }; 3216239462Sdim static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo, 3217239462Sdim ARM::VST2LNq32Pseudo }; 3218218893Sdim return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes); 3219198090Srdivacky } 3220198090Srdivacky 3221198090Srdivacky case Intrinsic::arm_neon_vst3lane: { 3222239462Sdim static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo, 3223239462Sdim ARM::VST3LNd16Pseudo, 3224239462Sdim ARM::VST3LNd32Pseudo }; 3225239462Sdim static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo, 3226239462Sdim ARM::VST3LNq32Pseudo }; 3227218893Sdim return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes); 3228198090Srdivacky } 3229198090Srdivacky 3230198090Srdivacky case Intrinsic::arm_neon_vst4lane: { 3231239462Sdim static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo, 3232239462Sdim ARM::VST4LNd16Pseudo, 3233239462Sdim ARM::VST4LNd32Pseudo }; 3234239462Sdim static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo, 3235239462Sdim ARM::VST4LNq32Pseudo }; 3236218893Sdim return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes); 3237198090Srdivacky } 3238198090Srdivacky } 3239208599Srdivacky break; 3240194710Sed } 3241208599Srdivacky 3242210299Sed case ISD::INTRINSIC_WO_CHAIN: { 3243210299Sed unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 3244210299Sed switch (IntNo) { 3245210299Sed default: 3246210299Sed break; 3247210299Sed 3248210299Sed case Intrinsic::arm_neon_vtbl2: 3249234353Sdim return SelectVTBL(N, false, 2, ARM::VTBL2); 3250210299Sed case Intrinsic::arm_neon_vtbl3: 3251218893Sdim return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo); 3252210299Sed case Intrinsic::arm_neon_vtbl4: 3253218893Sdim return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo); 3254210299Sed 3255210299Sed case Intrinsic::arm_neon_vtbx2: 3256234353Sdim return SelectVTBL(N, true, 2, ARM::VTBX2); 3257210299Sed case Intrinsic::arm_neon_vtbx3: 3258218893Sdim return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo); 3259210299Sed case Intrinsic::arm_neon_vtbx4: 3260218893Sdim return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo); 3261210299Sed } 3262210299Sed break; 3263210299Sed } 3264210299Sed 3265221345Sdim case ARMISD::VTBL1: { 3266261991Sdim SDLoc dl(N); 3267221345Sdim EVT VT = N->getValueType(0); 3268221345Sdim SmallVector<SDValue, 6> Ops; 3269221345Sdim 3270221345Sdim Ops.push_back(N->getOperand(0)); 3271221345Sdim Ops.push_back(N->getOperand(1)); 3272221345Sdim Ops.push_back(getAL(CurDAG)); // Predicate 3273221345Sdim Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register 3274251662Sdim return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops); 3275221345Sdim } 3276221345Sdim case ARMISD::VTBL2: { 3277261991Sdim SDLoc dl(N); 3278221345Sdim EVT VT = N->getValueType(0); 3279221345Sdim 3280221345Sdim // Form a REG_SEQUENCE to force register allocation. 3281221345Sdim SDValue V0 = N->getOperand(0); 3282221345Sdim SDValue V1 = N->getOperand(1); 3283249423Sdim SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0); 3284221345Sdim 3285221345Sdim SmallVector<SDValue, 6> Ops; 3286221345Sdim Ops.push_back(RegSeq); 3287221345Sdim Ops.push_back(N->getOperand(2)); 3288221345Sdim Ops.push_back(getAL(CurDAG)); // Predicate 3289221345Sdim Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register 3290251662Sdim return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops); 3291221345Sdim } 3292221345Sdim 3293208599Srdivacky case ISD::CONCAT_VECTORS: 3294208599Srdivacky return SelectConcatVector(N); 3295194710Sed } 3296194710Sed 3297202375Srdivacky return SelectCode(N); 3298193323Sed} 3299193323Sed 3300249423SdimSDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){ 3301249423Sdim std::vector<SDValue> AsmNodeOperands; 3302249423Sdim unsigned Flag, Kind; 3303249423Sdim bool Changed = false; 3304249423Sdim unsigned NumOps = N->getNumOperands(); 3305249423Sdim 3306249423Sdim // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint. 3307249423Sdim // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require 3308249423Sdim // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs 3309249423Sdim // respectively. Since there is no constraint to explicitly specify a 3310261991Sdim // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb, 3311261991Sdim // the 64-bit data may be referred by H, Q, R modifiers, so we still pack 3312261991Sdim // them into a GPRPair. 3313249423Sdim 3314261991Sdim SDLoc dl(N); 3315276479Sdim SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1) 3316276479Sdim : SDValue(nullptr,0); 3317249423Sdim 3318261991Sdim SmallVector<bool, 8> OpChanged; 3319249423Sdim // Glue node will be appended late. 3320261991Sdim for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) { 3321249423Sdim SDValue op = N->getOperand(i); 3322249423Sdim AsmNodeOperands.push_back(op); 3323249423Sdim 3324249423Sdim if (i < InlineAsm::Op_FirstOperand) 3325249423Sdim continue; 3326249423Sdim 3327249423Sdim if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) { 3328249423Sdim Flag = C->getZExtValue(); 3329249423Sdim Kind = InlineAsm::getKind(Flag); 3330249423Sdim } 3331249423Sdim else 3332249423Sdim continue; 3333249423Sdim 3334261991Sdim // Immediate operands to inline asm in the SelectionDAG are modeled with 3335261991Sdim // two operands. The first is a constant of value InlineAsm::Kind_Imm, and 3336261991Sdim // the second is a constant with the value of the immediate. If we get here 3337261991Sdim // and we have a Kind_Imm, skip the next operand, and continue. 3338261991Sdim if (Kind == InlineAsm::Kind_Imm) { 3339261991Sdim SDValue op = N->getOperand(++i); 3340261991Sdim AsmNodeOperands.push_back(op); 3341261991Sdim continue; 3342261991Sdim } 3343261991Sdim 3344261991Sdim unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag); 3345261991Sdim if (NumRegs) 3346261991Sdim OpChanged.push_back(false); 3347261991Sdim 3348261991Sdim unsigned DefIdx = 0; 3349261991Sdim bool IsTiedToChangedOp = false; 3350261991Sdim // If it's a use that is tied with a previous def, it has no 3351261991Sdim // reg class constraint. 3352261991Sdim if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx)) 3353261991Sdim IsTiedToChangedOp = OpChanged[DefIdx]; 3354261991Sdim 3355249423Sdim if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef 3356249423Sdim && Kind != InlineAsm::Kind_RegDefEarlyClobber) 3357249423Sdim continue; 3358249423Sdim 3359249423Sdim unsigned RC; 3360249423Sdim bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC); 3361261991Sdim if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID)) 3362261991Sdim || NumRegs != 2) 3363249423Sdim continue; 3364249423Sdim 3365261991Sdim assert((i+2 < NumOps) && "Invalid number of operands in inline asm"); 3366249423Sdim SDValue V0 = N->getOperand(i+1); 3367249423Sdim SDValue V1 = N->getOperand(i+2); 3368249423Sdim unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg(); 3369249423Sdim unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg(); 3370249423Sdim SDValue PairedReg; 3371249423Sdim MachineRegisterInfo &MRI = MF->getRegInfo(); 3372249423Sdim 3373249423Sdim if (Kind == InlineAsm::Kind_RegDef || 3374249423Sdim Kind == InlineAsm::Kind_RegDefEarlyClobber) { 3375249423Sdim // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to 3376249423Sdim // the original GPRs. 3377249423Sdim 3378249423Sdim unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass); 3379249423Sdim PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped); 3380249423Sdim SDValue Chain = SDValue(N,0); 3381249423Sdim 3382249423Sdim SDNode *GU = N->getGluedUser(); 3383249423Sdim SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped, 3384249423Sdim Chain.getValue(1)); 3385249423Sdim 3386249423Sdim // Extract values from a GPRPair reg and copy to the original GPR reg. 3387249423Sdim SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32, 3388249423Sdim RegCopy); 3389249423Sdim SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32, 3390249423Sdim RegCopy); 3391249423Sdim SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0, 3392249423Sdim RegCopy.getValue(1)); 3393249423Sdim SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1)); 3394249423Sdim 3395249423Sdim // Update the original glue user. 3396249423Sdim std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1); 3397249423Sdim Ops.push_back(T1.getValue(1)); 3398276479Sdim CurDAG->UpdateNodeOperands(GU, Ops); 3399249423Sdim } 3400249423Sdim else { 3401249423Sdim // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a 3402249423Sdim // GPRPair and then pass the GPRPair to the inline asm. 3403249423Sdim SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain]; 3404249423Sdim 3405249423Sdim // As REG_SEQ doesn't take RegisterSDNode, we copy them first. 3406249423Sdim SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32, 3407249423Sdim Chain.getValue(1)); 3408249423Sdim SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32, 3409249423Sdim T0.getValue(1)); 3410249423Sdim SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0); 3411249423Sdim 3412249423Sdim // Copy REG_SEQ into a GPRPair-typed VR and replace the original two 3413249423Sdim // i32 VRs of inline asm with it. 3414249423Sdim unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass); 3415249423Sdim PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped); 3416249423Sdim Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1)); 3417249423Sdim 3418249423Sdim AsmNodeOperands[InlineAsm::Op_InputChain] = Chain; 3419249423Sdim Glue = Chain.getValue(1); 3420249423Sdim } 3421249423Sdim 3422249423Sdim Changed = true; 3423249423Sdim 3424249423Sdim if(PairedReg.getNode()) { 3425261991Sdim OpChanged[OpChanged.size() -1 ] = true; 3426249423Sdim Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/); 3427261991Sdim if (IsTiedToChangedOp) 3428261991Sdim Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx); 3429261991Sdim else 3430261991Sdim Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID); 3431249423Sdim // Replace the current flag. 3432249423Sdim AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant( 3433249423Sdim Flag, MVT::i32); 3434249423Sdim // Add the new register node and skip the original two GPRs. 3435249423Sdim AsmNodeOperands.push_back(PairedReg); 3436249423Sdim // Skip the next two GPRs. 3437249423Sdim i += 2; 3438249423Sdim } 3439249423Sdim } 3440249423Sdim 3441261991Sdim if (Glue.getNode()) 3442261991Sdim AsmNodeOperands.push_back(Glue); 3443249423Sdim if (!Changed) 3444276479Sdim return nullptr; 3445249423Sdim 3446261991Sdim SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N), 3447276479Sdim CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands); 3448249423Sdim New->setNodeId(-1); 3449249423Sdim return New.getNode(); 3450249423Sdim} 3451249423Sdim 3452249423Sdim 3453193323Sedbool ARMDAGToDAGISel:: 3454193323SedSelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 3455193323Sed std::vector<SDValue> &OutOps) { 3456193323Sed assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 3457198090Srdivacky // Require the address to be in a register. That is safe for all ARM 3458198090Srdivacky // variants and it is hard to do anything much smarter without knowing 3459198090Srdivacky // how the operand is used. 3460198090Srdivacky OutOps.push_back(Op); 3461193323Sed return false; 3462193323Sed} 3463193323Sed 3464193323Sed/// createARMISelDag - This pass converts a legalized DAG into a 3465193323Sed/// ARM-specific DAG, ready for instruction scheduling. 3466193323Sed/// 3467198090SrdivackyFunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 3468198090Srdivacky CodeGenOpt::Level OptLevel) { 3469198090Srdivacky return new ARMDAGToDAGISel(TM, OptLevel); 3470193323Sed} 3471